<commit_before>#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "blackhole/extensions/writer.hpp"
#include <blackhole/logger.hpp>
#include <blackhole/record.hpp>
#include <blackhole/root.hpp>
#include <blackhole/scoped.hpp>

#include "mocks/handler.hpp"

namespace blackhole {
namespace testing {

using ::testing::Invoke;
using ::testing::_;

TEST(RootLogger, Constructor) {
    // Can be initialized with none handlers, does nothing.
    root_logger_t logger({});
    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, FilterConstructor) {
    int passed = 0;

    root_logger_t logger([&](const record_t&) -> bool {
        passed++;
        return false;
    }, {});

    logger.log(0, "GET /porn.png HTTP/1.1");

    EXPECT_EQ(1, passed);
}

TEST(RootLogger, LogInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                EXPECT_EQ(0, record.attributes().size());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, LogWithAttributesInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    const view_of<attributes_t>::type attributes{{"key#1", {42}}};
    attribute_pack pack{attributes};

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([&](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                ASSERT_EQ(1, record.attributes().size());
                EXPECT_EQ(attributes, record.attributes().at(0).get());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1", pack);
}

TEST(RootLogger, LogWithFormatterInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    const view_of<attributes_t>::type attributes{{"key#1", {42}}};
    attribute_pack pack{attributes};

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([&](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1 - {}/{}", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1 - 42/2345", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                ASSERT_EQ(1, record.attributes().size());
                EXPECT_EQ(attributes, record.attributes().at(0).get());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1 - {}/{}", pack, [](writer_t& writer) {
        writer.write("GET /porn.png HTTP/1.1 - {}/{}", 42, 2345);
    });
}

TEST(RootLogger, Scoped) {
    std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
    mock::handler_t* view = handler.get();

    std::vector<std::unique_ptr<handler_t>> handlers;
    handlers.push_back(std::move(handler));

    root_logger_t logger(std::move(handlers));
    const auto scoped = logger.scoped({{"key#1", {42}}});

    EXPECT_CALL(*view, execute(_))
        .Times(1)
        .WillOnce(Invoke([](const record_t& record) {
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
            EXPECT_EQ(0, record.severity());
            ASSERT_EQ(1, record.attributes().size());

            view_of<attributes_t>::type attributes{{"key#1", {42}}};
            EXPECT_EQ(attributes, record.attributes().at(0).get());
        }));

    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, Assignment) {
    std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
    mock::handler_t* view = handler.get();

    std::vector<std::unique_ptr<handler_t>> handlers;
    handlers.push_back(std::move(handler));

    root_logger_t logger1({});
    root_logger_t logger2(std::move(handlers));
    const auto scoped = logger2.scoped({{"key#1", {42}}});

    // All scoped attributes should be assigned to the new owner.
    logger1 = std::move(logger2);

    EXPECT_CALL(*view, execute(_))
        .Times(1)
        .WillOnce(Invoke([](const record_t& record) {
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
            EXPECT_EQ(0, record.severity());
            ASSERT_EQ(1, record.attributes().size());

            view_of<attributes_t>::type attributes{{"key#1", {42}}};
            EXPECT_EQ(attributes, record.attributes().at(0).get());
        }));

    logger1.log(0, "GET /porn.png HTTP/1.1");
}

}  // namespace testing
}  // namespace blackhole
<commit_msg>style(tests): remove duplicated with docs comment<commit_after>#include <gmock/gmock.h>
#include <gtest/gtest.h>

#include "blackhole/extensions/writer.hpp"
#include <blackhole/logger.hpp>
#include <blackhole/record.hpp>
#include <blackhole/root.hpp>
#include <blackhole/scoped.hpp>

#include "mocks/handler.hpp"

namespace blackhole {
namespace testing {

using ::testing::Invoke;
using ::testing::_;

TEST(RootLogger, Constructor) {
    root_logger_t logger({});
    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, FilterConstructor) {
    int passed = 0;

    root_logger_t logger([&](const record_t&) -> bool {
        passed++;
        return false;
    }, {});

    logger.log(0, "GET /porn.png HTTP/1.1");

    EXPECT_EQ(1, passed);
}

TEST(RootLogger, LogInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                EXPECT_EQ(0, record.attributes().size());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, LogWithAttributesInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    const view_of<attributes_t>::type attributes{{"key#1", {42}}};
    attribute_pack pack{attributes};

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([&](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                ASSERT_EQ(1, record.attributes().size());
                EXPECT_EQ(attributes, record.attributes().at(0).get());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1", pack);
}

TEST(RootLogger, LogWithFormatterInvokesDispatchingRecordToHandlers) {
    std::vector<std::unique_ptr<handler_t>> handlers;
    std::vector<mock::handler_t*> handlers_view;

    for (int i = 0; i < 4; ++i) {
        std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
        handlers_view.push_back(handler.get());
        handlers.push_back(std::move(handler));
    }

    root_logger_t logger(std::move(handlers));

    const view_of<attributes_t>::type attributes{{"key#1", {42}}};
    attribute_pack pack{attributes};

    for (auto handler : handlers_view) {
        EXPECT_CALL(*handler, execute(_))
            .Times(1)
            .WillOnce(Invoke([&](const record_t& record) {
                EXPECT_EQ("GET /porn.png HTTP/1.1 - {}/{}", record.message().to_string());
                EXPECT_EQ("GET /porn.png HTTP/1.1 - 42/2345", record.formatted().to_string());
                EXPECT_EQ(0, record.severity());
                ASSERT_EQ(1, record.attributes().size());
                EXPECT_EQ(attributes, record.attributes().at(0).get());
            }));
    }

    logger.log(0, "GET /porn.png HTTP/1.1 - {}/{}", pack, [](writer_t& writer) {
        writer.write("GET /porn.png HTTP/1.1 - {}/{}", 42, 2345);
    });
}

TEST(RootLogger, Scoped) {
    std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
    mock::handler_t* view = handler.get();

    std::vector<std::unique_ptr<handler_t>> handlers;
    handlers.push_back(std::move(handler));

    root_logger_t logger(std::move(handlers));
    const auto scoped = logger.scoped({{"key#1", {42}}});

    EXPECT_CALL(*view, execute(_))
        .Times(1)
        .WillOnce(Invoke([](const record_t& record) {
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
            EXPECT_EQ(0, record.severity());
            ASSERT_EQ(1, record.attributes().size());

            view_of<attributes_t>::type attributes{{"key#1", {42}}};
            EXPECT_EQ(attributes, record.attributes().at(0).get());
        }));

    logger.log(0, "GET /porn.png HTTP/1.1");
}

TEST(RootLogger, Assignment) {
    std::unique_ptr<mock::handler_t> handler(new mock::handler_t);
    mock::handler_t* view = handler.get();

    std::vector<std::unique_ptr<handler_t>> handlers;
    handlers.push_back(std::move(handler));

    root_logger_t logger1({});
    root_logger_t logger2(std::move(handlers));
    const auto scoped = logger2.scoped({{"key#1", {42}}});

    // All scoped attributes should be assigned to the new owner.
    logger1 = std::move(logger2);

    EXPECT_CALL(*view, execute(_))
        .Times(1)
        .WillOnce(Invoke([](const record_t& record) {
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.message().to_string());
            EXPECT_EQ("GET /porn.png HTTP/1.1", record.formatted().to_string());
            EXPECT_EQ(0, record.severity());
            ASSERT_EQ(1, record.attributes().size());

            view_of<attributes_t>::type attributes{{"key#1", {42}}};
            EXPECT_EQ(attributes, record.attributes().at(0).get());
        }));

    logger1.log(0, "GET /porn.png HTTP/1.1");
}

}  // namespace testing
}  // namespace blackhole
<|endoftext|>


<commit_before>/* vim: set ts=2 expandtab: */
/**
 *       @file  test.cpp
 *      @brief
 *
 *     @author  Josh King (jheretic), jking@chambana.net
 *
 *   @internal
 *      Created  11/17/2013 06:01:11 PM
 *     Compiler  gcc/g++
 * Organization  The Open Technology Institute
 *    Copyright  Copyright (c) 2013, Josh King
 *
 * This file is part of Commotion, Copyright (c) 2013, Josh King
 *
 * Commotion is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * Commotion is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Commotion.  If not, see <http://www.gnu.org/licenses/>.
 *
 * =====================================================================================
 */
extern "C" {
#include "../src/obj.h"
#include "../src/list.h"
#include "../src/tree.h"
}
#include "gtest/gtest.h"

/*
 * NOTE: Inserting keys with different length values will be interpreted as different keys (eg insert("test", 5) and insert("test", 6) are not the same
 * and their values will be stored in different nodes in the tree
 *
 *
 */

class TreeTest : public ::testing::Test
{
  protected:
    co_obj_t *Tree16;
    co_obj_t *Tree32;
    void InsertObj();
    void DeleteObj();
    void UpdateObj();
    co_obj_t *TestString1;
    co_obj_t *TestString2;
    co_obj_t *ReplaceString1;

    co_obj_t *TestString3;

    co_obj_t *ptr;
    int ret;

    TreeTest()
    {
      Tree16 = co_tree16_create();
      Tree32 = co_tree32_create();

      TestString1 = co_str8_create("1TESTVALUE1", 12, 0);
      TestString2 = co_str8_create("2TESTVALUE2", 12, 0);

      ReplaceString1 = co_str8_create("REPLACE", 9, 0);
    }

    virtual void SetUp()
    {
    }

    ~TreeTest()
    {
      co_obj_free(Tree16);
      co_obj_free(Tree32);
    }
};

void TreeTest::InsertObj()
{
  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  ret = co_tree_insert_force(Tree16, "1TESTKEY1", 10, ReplaceString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(ReplaceString1, ptr);

  // reinitialize TestString1 since it was freed by co_tree_insert_force()
  TestString1 = co_str8_create("1TESTVALUE1", 12, 0);

  // repeat for Tree 32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  ret = co_tree_insert_force(Tree32, "1TESTKEY1", 10, ReplaceString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(ReplaceString1, ptr);

}

void TreeTest::DeleteObj()
{

  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_delete(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ptr = co_tree_delete(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  // confirm deletions
  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(NULL, ptr);

  ptr = co_tree_find(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(NULL, ptr);

  // reinitialize
  TestString1 = co_str8_create("1TESTVALUE1", 12, 0);
  TestString2 = co_str8_create("2TESTVALUE2", 12, 0);

  // repeat for Tree32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_delete(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ptr = co_tree_delete(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  // confirm deletions
  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(NULL, ptr);

  ptr = co_tree_find(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(NULL, ptr);
}

void TreeTest::UpdateObj()
{
  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_set_str(Tree16, "1TESTKEY1", 10, "REPLACE", 9);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1));

  // repeat for Tree32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_set_str(Tree32, "1TESTKEY1", 10, "REPLACE", 9);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1));

}

TEST_F(TreeTest, TreeInsertTest)
{
  InsertObj();
}

TEST_F(TreeTest, TreeDeleteTest)
{
  DeleteObj();
}

/*
TEST_F(TreeTest, TreeUpdateTest)
{
    UpdateObj();
}
*/<commit_msg>Revert "did stuff"<commit_after>/* vim: set ts=2 expandtab: */
/**
 *       @file  test.cpp
 *      @brief
 *
 *     @author  Josh King (jheretic), jking@chambana.net
 *
 *   @internal
 *      Created  11/17/2013 06:01:11 PM
 *     Compiler  gcc/g++
 * Organization  The Open Technology Institute
 *    Copyright  Copyright (c) 2013, Josh King
 *
 * This file is part of Commotion, Copyright (c) 2013, Josh King
 *
 * Commotion is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published
 * by the Free Software Foundation, either version 3 of the License,
 * or (at your option) any later version.
 *
 * Commotion is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with Commotion.  If not, see <http://www.gnu.org/licenses/>.
 *
 * =====================================================================================
 */
extern "C" {
#include "../src/obj.h"
#include "../src/list.h"
#include "../src/tree.h"
}
#include "gtest/gtest.h"

/*
 * NOTE: Inserting keys with different length values will be interpreted as different keys (eg insert("test", 5) and insert("test", 6) are not the same
 * and their values will be stored in different nodes in the tree
 *
 *
 */

class TreeTest : public ::testing::Test
{
  protected:
    co_obj_t *Tree16;
    co_obj_t *Tree32;
    void InsertObj();
    void DeleteObj();
    void UpdateObj();
    co_obj_t *TestString1;
    co_obj_t *TestString2;
    co_obj_t *ReplaceString1;

    co_obj_t *TestString3;

    co_obj_t *ptr;
    int ret;

    TreeTest()
    {
      Tree16 = co_tree16_create();
      Tree32 = co_tree32_create();

      TestString1 = co_str8_create("1TESTVALUE1", 12, 0);
      TestString2 = co_str8_create("2TESTVALUE2", 12, 0);

      // TestString3 = co_str8_create("1TESTVALUE1", 12, 0);

      ReplaceString1 = co_str8_create("REPLACE", 9, 0);
    }

    virtual void SetUp()
    {
    }

    ~TreeTest()
    {
      co_obj_free(Tree16);
      co_obj_free(Tree32);
    }
};

void TreeTest::InsertObj()
{
  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  ret = co_tree_insert_force(Tree16, "1TESTKEY1", 10, ReplaceString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(ReplaceString1, ptr);

  // reinitialize TestString1 since it was freed by co_tree_insert_force()
  TestString1 = co_str8_create("1TESTVALUE1", 12, 0);

  // repeat for Tree 32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  ret = co_tree_insert_force(Tree32, "1TESTKEY1", 10, ReplaceString1);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(ReplaceString1, ptr);

}

void TreeTest::DeleteObj()
{

  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_insert(Tree16, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_delete(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ptr = co_tree_delete(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  // confirm deletions
  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(NULL, ptr);

  ptr = co_tree_find(Tree16, "2TESTKEY2", 10);
  ASSERT_EQ(NULL, ptr);

  // repeat for Tree32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_insert(Tree32, "2TESTKEY2", 10, TestString2);
  ASSERT_EQ(1, ret);

  ptr = co_tree_delete(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(TestString1, ptr);

  ptr = co_tree_delete(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(TestString2, ptr);

  // confirm deletions
  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(NULL, ptr);

  ptr = co_tree_find(Tree32, "2TESTKEY2", 10);
  ASSERT_EQ(NULL, ptr);
}

void TreeTest::UpdateObj()
{
  ret = co_tree_insert(Tree16, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_set_str(Tree16, "1TESTKEY1", 10, "REPLACE", 9);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree16, "1TESTKEY1", 10);
  ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1));

  /*
  // repeat for Tree32
  ret = co_tree_insert(Tree32, "1TESTKEY1", 10, TestString1);
  ASSERT_EQ(1, ret);

  ret = co_tree_set_str(Tree32, "1TESTKEY1", 10, "REPLACE", 9);
  ASSERT_EQ(1, ret);

  ptr = co_tree_find(Tree32, "1TESTKEY1", 10);
  ASSERT_EQ(0, co_str_cmp(ptr, ReplaceString1));
  */
}

TEST_F(TreeTest, TreeInsertTest)
{
  InsertObj();
}

TEST_F(TreeTest, TreeDeleteTest)
{
  DeleteObj();
}

TEST_F(TreeTest, TreeUpdateTest)
{
    UpdateObj();
}
<|endoftext|>


<commit_before>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/render_widget_fullscreen_pepper.h"

#include "chrome/common/render_messages.h"
#include "chrome/renderer/ggl/ggl.h"
#include "chrome/renderer/gpu_channel_host.h"
#include "chrome/renderer/pepper_platform_context_3d_impl.h"
#include "chrome/renderer/render_thread.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"

using WebKit::WebCanvas;
using WebKit::WebCompositionUnderline;
using WebKit::WebCursorInfo;
using WebKit::WebInputEvent;
using WebKit::WebRect;
using WebKit::WebSize;
using WebKit::WebString;
using WebKit::WebTextDirection;
using WebKit::WebTextInputType;
using WebKit::WebVector;
using WebKit::WebWidget;

namespace {

// WebWidget that simply wraps the pepper plugin.
class PepperWidget : public WebWidget {
 public:
  PepperWidget(webkit::ppapi::PluginInstance* plugin,
               RenderWidgetFullscreenPepper* widget)
      : plugin_(plugin),
        widget_(widget),
        cursor_(WebCursorInfo::TypePointer) {
  }

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->ViewChanged(plugin_rect, plugin_rect);
    widget_->Invalidate();
  }

  virtual void animate() {
  }

  virtual void layout() {
  }

  virtual void paint(WebCanvas* canvas, const WebRect& rect) {
    if (!plugin_)
      return;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->Paint(canvas, plugin_rect, rect);
  }

  virtual void composite(bool finish) {
    ggl::Context* context = widget_->context();
    DCHECK(context);
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context);
    unsigned int texture = plugin_->GetBackingTextureId();
    gl->BindTexture(GL_TEXTURE_2D, texture);
    gl->DrawArrays(GL_TRIANGLES, 0, 3);
    ggl::SwapBuffers(context);
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    if (!plugin_)
      return false;
    return plugin_->HandleInputEvent(event, &cursor_);
  }

  virtual void mouseCaptureLost() {
    NOTIMPLEMENTED();
  }

  virtual void setFocus(bool focus) {
    NOTIMPLEMENTED();
  }

  virtual bool setComposition(
      const WebString& text,
      const WebVector<WebCompositionUnderline>& underlines,
      int selectionStart,
      int selectionEnd) {
    NOTIMPLEMENTED();
    return false;
  }

  virtual bool confirmComposition() {
    NOTIMPLEMENTED();
    return false;
  }

  virtual bool confirmComposition(const WebString& text) {
    NOTIMPLEMENTED();
    return false;
  }

  virtual WebTextInputType textInputType() {
    NOTIMPLEMENTED();
    return WebKit::WebTextInputTypeNone;
  }

  virtual WebRect caretOrSelectionBounds() {
    NOTIMPLEMENTED();
    return WebRect();
  }

  virtual void setTextDirection(WebTextDirection) {
    NOTIMPLEMENTED();
  }

  virtual bool isAcceleratedCompositingActive() const {
    return widget_->context() && plugin_ &&
        (plugin_->GetBackingTextureId() != 0);
  }

 private:
  webkit::ppapi::PluginInstance* plugin_;
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;
  WebCursorInfo cursor_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id, RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(render_thread, plugin));
  widget->Init(opener_id);
  return widget.release();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin)
    : RenderWidgetFullscreen(render_thread),
      plugin_(plugin),
      context_(NULL),
      buffer_(0),
      program_(0) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
  DestroyContext();
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didInvalidateRect(rect);
  }
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didScrollRect(dx, dy, rect);
  }
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;
  Send(new ViewHostMsg_Close(routing_id_));
}

webkit::ppapi::PluginDelegate::PlatformContext3D*
RenderWidgetFullscreenPepper::CreateContext3D() {
  if (!context_) {
    CreateContext();
  }
  if (!context_)
    return NULL;
  return new PlatformContext3DImpl(context_);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
  if (plugin_)
    plugin_->ViewFlushedPaint();
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->SetFullscreen(false);
}

webkit::ppapi::PluginInstance*
RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
    const gfx::Rect& paint_bounds,
    TransportDIB** dib,
    gfx::Rect* location,
    gfx::Rect* clip) {
  if (plugin_ &&
      plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib,
                                                location, clip))
    return plugin_;
  return NULL;
}

void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
                                            const gfx::Rect& resizer_rect) {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
#if defined(OS_MACOSX)
    ggl::ResizeOnscreenContext(context_, size);
#else
    gl->ResizeCHROMIUM(size.width(), size.height());
#endif
    gl->Viewport(0, 0, size.width(), size.height());
  }
  RenderWidget::OnResize(size, resizer_rect);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(plugin_, this);
}

void RenderWidgetFullscreenPepper::CreateContext() {
  DCHECK(!context_);
  RenderThread* render_thread = RenderThread::current();
  DCHECK(render_thread);
  GpuChannelHost* host = render_thread->EstablishGpuChannelSync();
  if (!host)
    return;
  const int32 attribs[] = {
    ggl::GGL_ALPHA_SIZE, 8,
    ggl::GGL_DEPTH_SIZE, 0,
    ggl::GGL_STENCIL_SIZE, 0,
    ggl::GGL_SAMPLES, 0,
    ggl::GGL_SAMPLE_BUFFERS, 0,
    ggl::GGL_NONE,
  };
  context_ = ggl::CreateViewContext(
      host,
      routing_id(),
      "GL_OES_packed_depth_stencil GL_OES_depth24",
      attribs);
  if (!context_ || !InitContext()) {
    DestroyContext();
    return;
  }
  ggl::SetSwapBuffersCallback(
      context_,
      NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint));
}

void RenderWidgetFullscreenPepper::DestroyContext() {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
    if (program_) {
      gl->DeleteProgram(program_);
      program_ = 0;
    }
    if (buffer_) {
      gl->DeleteBuffers(1, &buffer_);
      buffer_ = 0;
    }
    ggl::DestroyContext(context_);
    context_ = NULL;
  }
}

namespace {

const char kVertexShader[] =
    "attribute vec2 in_tex_coord;\n"
    "varying vec2 tex_coord;\n"
    "void main() {\n"
    "  gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n"
    "                     in_tex_coord.y * 2. - 1.,\n"
    "                     0.,\n"
    "                     1.);\n"
    "  tex_coord = vec2(in_tex_coord.x, 1. - in_tex_coord.y);\n"
    "}\n";

const char kFragmentShader[] =
    "precision mediump float;\n"
    "varying vec2 tex_coord;\n"
    "uniform sampler2D in_texture;\n"
    "void main() {\n"
    "  gl_FragColor = texture2D(in_texture, tex_coord);\n"
    "}\n";

GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl,
                              GLenum type,
                              const char* source) {
    GLuint shader = gl->CreateShader(type);
    gl->ShaderSource(shader, 1, &source, NULL);
    gl->CompileShader(shader);
    int status;
    gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (!status) {
        int size = 0;
        gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
        scoped_array<char> log(new char[size]);
        gl->GetShaderInfoLog(shader, size, NULL, log.get());
        DLOG(ERROR) << "Compilation failed: " << log.get();
        gl->DeleteShader(shader);
        shader = 0;
    }
    return shader;
}

const float kTexCoords[] = {
    0.f, 0.f,
    0.f, 2.f,
    2.f, 0.f,
};

}  // anonymous namespace

bool RenderWidgetFullscreenPepper::InitContext() {
  gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
  program_ = gl->CreateProgram();

  GLuint vertex_shader =
      CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader);
  if (!vertex_shader)
    return false;
  gl->AttachShader(program_, vertex_shader);
  gl->DeleteShader(vertex_shader);

  GLuint fragment_shader =
      CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader);
  if (!fragment_shader)
    return false;
  gl->AttachShader(program_, fragment_shader);
  gl->DeleteShader(fragment_shader);

  gl->BindAttribLocation(program_, 0, "in_tex_coord");
  gl->LinkProgram(program_);
  int status;
  gl->GetProgramiv(program_, GL_LINK_STATUS, &status);
  if (!status) {
    int size = 0;
    gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size);
    scoped_array<char> log(new char[size]);
    gl->GetProgramInfoLog(program_, size, NULL, log.get());
    DLOG(ERROR) << "Link failed: " << log.get();
    return false;
  }
  gl->UseProgram(program_);
  int texture_location = gl->GetUniformLocation(program_, "in_texture");
  gl->Uniform1i(texture_location, 0);

  gl->GenBuffers(1, &buffer_);
  gl->BindBuffer(GL_ARRAY_BUFFER, buffer_);
  gl->BufferData(GL_ARRAY_BUFFER,
                 sizeof(kTexCoords),
                 kTexCoords,
                 GL_STATIC_DRAW);
  gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  gl->EnableVertexAttribArray(0);
  return true;
}

bool RenderWidgetFullscreenPepper::CheckCompositing() {
  bool compositing = webwidget_->isAcceleratedCompositingActive();
  if (compositing != is_accelerated_compositing_active_) {
    didActivateAcceleratedCompositing(compositing);
  }
  return compositing;
}
<commit_msg>Flip pepper fullscreen GL.<commit_after>// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/renderer/render_widget_fullscreen_pepper.h"

#include "chrome/common/render_messages.h"
#include "chrome/renderer/ggl/ggl.h"
#include "chrome/renderer/gpu_channel_host.h"
#include "chrome/renderer/pepper_platform_context_3d_impl.h"
#include "chrome/renderer/render_thread.h"
#include "gpu/command_buffer/client/gles2_implementation.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebCursorInfo.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
#include "webkit/plugins/ppapi/plugin_delegate.h"
#include "webkit/plugins/ppapi/ppapi_plugin_instance.h"

using WebKit::WebCanvas;
using WebKit::WebCompositionUnderline;
using WebKit::WebCursorInfo;
using WebKit::WebInputEvent;
using WebKit::WebRect;
using WebKit::WebSize;
using WebKit::WebString;
using WebKit::WebTextDirection;
using WebKit::WebTextInputType;
using WebKit::WebVector;
using WebKit::WebWidget;

namespace {

// WebWidget that simply wraps the pepper plugin.
class PepperWidget : public WebWidget {
 public:
  PepperWidget(webkit::ppapi::PluginInstance* plugin,
               RenderWidgetFullscreenPepper* widget)
      : plugin_(plugin),
        widget_(widget),
        cursor_(WebCursorInfo::TypePointer) {
  }

  // WebWidget API
  virtual void close() {
    delete this;
  }

  virtual WebSize size() {
    return size_;
  }

  virtual void resize(const WebSize& size) {
    size_ = size;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->ViewChanged(plugin_rect, plugin_rect);
    widget_->Invalidate();
  }

  virtual void animate() {
  }

  virtual void layout() {
  }

  virtual void paint(WebCanvas* canvas, const WebRect& rect) {
    if (!plugin_)
      return;
    WebRect plugin_rect(0, 0, size_.width, size_.height);
    plugin_->Paint(canvas, plugin_rect, rect);
  }

  virtual void composite(bool finish) {
    ggl::Context* context = widget_->context();
    DCHECK(context);
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context);
    unsigned int texture = plugin_->GetBackingTextureId();
    gl->BindTexture(GL_TEXTURE_2D, texture);
    gl->DrawArrays(GL_TRIANGLES, 0, 3);
    ggl::SwapBuffers(context);
  }

  virtual void themeChanged() {
    NOTIMPLEMENTED();
  }

  virtual bool handleInputEvent(const WebInputEvent& event) {
    if (!plugin_)
      return false;
    return plugin_->HandleInputEvent(event, &cursor_);
  }

  virtual void mouseCaptureLost() {
    NOTIMPLEMENTED();
  }

  virtual void setFocus(bool focus) {
    NOTIMPLEMENTED();
  }

  virtual bool setComposition(
      const WebString& text,
      const WebVector<WebCompositionUnderline>& underlines,
      int selectionStart,
      int selectionEnd) {
    NOTIMPLEMENTED();
    return false;
  }

  virtual bool confirmComposition() {
    NOTIMPLEMENTED();
    return false;
  }

  virtual bool confirmComposition(const WebString& text) {
    NOTIMPLEMENTED();
    return false;
  }

  virtual WebTextInputType textInputType() {
    NOTIMPLEMENTED();
    return WebKit::WebTextInputTypeNone;
  }

  virtual WebRect caretOrSelectionBounds() {
    NOTIMPLEMENTED();
    return WebRect();
  }

  virtual void setTextDirection(WebTextDirection) {
    NOTIMPLEMENTED();
  }

  virtual bool isAcceleratedCompositingActive() const {
    return widget_->context() && plugin_ &&
        (plugin_->GetBackingTextureId() != 0);
  }

 private:
  webkit::ppapi::PluginInstance* plugin_;
  RenderWidgetFullscreenPepper* widget_;
  WebSize size_;
  WebCursorInfo cursor_;

  DISALLOW_COPY_AND_ASSIGN(PepperWidget);
};

}  // anonymous namespace

// static
RenderWidgetFullscreenPepper* RenderWidgetFullscreenPepper::Create(
    int32 opener_id, RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin) {
  DCHECK_NE(MSG_ROUTING_NONE, opener_id);
  scoped_refptr<RenderWidgetFullscreenPepper> widget(
      new RenderWidgetFullscreenPepper(render_thread, plugin));
  widget->Init(opener_id);
  return widget.release();
}

RenderWidgetFullscreenPepper::RenderWidgetFullscreenPepper(
    RenderThreadBase* render_thread,
    webkit::ppapi::PluginInstance* plugin)
    : RenderWidgetFullscreen(render_thread),
      plugin_(plugin),
      context_(NULL),
      buffer_(0),
      program_(0) {
}

RenderWidgetFullscreenPepper::~RenderWidgetFullscreenPepper() {
  DestroyContext();
}

void RenderWidgetFullscreenPepper::Invalidate() {
  InvalidateRect(gfx::Rect(size_.width(), size_.height()));
}

void RenderWidgetFullscreenPepper::InvalidateRect(const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didInvalidateRect(rect);
  }
}

void RenderWidgetFullscreenPepper::ScrollRect(
    int dx, int dy, const WebKit::WebRect& rect) {
  if (CheckCompositing()) {
    scheduleComposite();
  } else {
    didScrollRect(dx, dy, rect);
  }
}

void RenderWidgetFullscreenPepper::Destroy() {
  // This function is called by the plugin instance as it's going away, so reset
  // plugin_ to NULL to avoid calling into a dangling pointer e.g. on Close().
  plugin_ = NULL;
  Send(new ViewHostMsg_Close(routing_id_));
}

webkit::ppapi::PluginDelegate::PlatformContext3D*
RenderWidgetFullscreenPepper::CreateContext3D() {
  if (!context_) {
    CreateContext();
  }
  if (!context_)
    return NULL;
  return new PlatformContext3DImpl(context_);
}

void RenderWidgetFullscreenPepper::DidInitiatePaint() {
  if (plugin_)
    plugin_->ViewInitiatedPaint();
}

void RenderWidgetFullscreenPepper::DidFlushPaint() {
  if (plugin_)
    plugin_->ViewFlushedPaint();
}

void RenderWidgetFullscreenPepper::Close() {
  // If the fullscreen window is closed (e.g. user pressed escape), reset to
  // normal mode.
  if (plugin_)
    plugin_->SetFullscreen(false);
}

webkit::ppapi::PluginInstance*
RenderWidgetFullscreenPepper::GetBitmapForOptimizedPluginPaint(
    const gfx::Rect& paint_bounds,
    TransportDIB** dib,
    gfx::Rect* location,
    gfx::Rect* clip) {
  if (plugin_ &&
      plugin_->GetBitmapForOptimizedPluginPaint(paint_bounds, dib,
                                                location, clip))
    return plugin_;
  return NULL;
}

void RenderWidgetFullscreenPepper::OnResize(const gfx::Size& size,
                                            const gfx::Rect& resizer_rect) {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
#if defined(OS_MACOSX)
    ggl::ResizeOnscreenContext(context_, size);
#else
    gl->ResizeCHROMIUM(size.width(), size.height());
#endif
    gl->Viewport(0, 0, size.width(), size.height());
  }
  RenderWidget::OnResize(size, resizer_rect);
}

WebWidget* RenderWidgetFullscreenPepper::CreateWebWidget() {
  return new PepperWidget(plugin_, this);
}

void RenderWidgetFullscreenPepper::CreateContext() {
  DCHECK(!context_);
  RenderThread* render_thread = RenderThread::current();
  DCHECK(render_thread);
  GpuChannelHost* host = render_thread->EstablishGpuChannelSync();
  if (!host)
    return;
  const int32 attribs[] = {
    ggl::GGL_ALPHA_SIZE, 8,
    ggl::GGL_DEPTH_SIZE, 0,
    ggl::GGL_STENCIL_SIZE, 0,
    ggl::GGL_SAMPLES, 0,
    ggl::GGL_SAMPLE_BUFFERS, 0,
    ggl::GGL_NONE,
  };
  context_ = ggl::CreateViewContext(
      host,
      routing_id(),
      "GL_OES_packed_depth_stencil GL_OES_depth24",
      attribs);
  if (!context_ || !InitContext()) {
    DestroyContext();
    return;
  }
  ggl::SetSwapBuffersCallback(
      context_,
      NewCallback(this, &RenderWidgetFullscreenPepper::DidFlushPaint));
}

void RenderWidgetFullscreenPepper::DestroyContext() {
  if (context_) {
    gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
    if (program_) {
      gl->DeleteProgram(program_);
      program_ = 0;
    }
    if (buffer_) {
      gl->DeleteBuffers(1, &buffer_);
      buffer_ = 0;
    }
    ggl::DestroyContext(context_);
    context_ = NULL;
  }
}

namespace {

const char kVertexShader[] =
    "attribute vec2 in_tex_coord;\n"
    "varying vec2 tex_coord;\n"
    "void main() {\n"
    "  gl_Position = vec4(in_tex_coord.x * 2. - 1.,\n"
    "                     in_tex_coord.y * 2. - 1.,\n"
    "                     0.,\n"
    "                     1.);\n"
    "  tex_coord = vec2(in_tex_coord.x, in_tex_coord.y);\n"
    "}\n";

const char kFragmentShader[] =
    "precision mediump float;\n"
    "varying vec2 tex_coord;\n"
    "uniform sampler2D in_texture;\n"
    "void main() {\n"
    "  gl_FragColor = texture2D(in_texture, tex_coord);\n"
    "}\n";

GLuint CreateShaderFromSource(gpu::gles2::GLES2Implementation* gl,
                              GLenum type,
                              const char* source) {
    GLuint shader = gl->CreateShader(type);
    gl->ShaderSource(shader, 1, &source, NULL);
    gl->CompileShader(shader);
    int status;
    gl->GetShaderiv(shader, GL_COMPILE_STATUS, &status);
    if (!status) {
        int size = 0;
        gl->GetShaderiv(shader, GL_INFO_LOG_LENGTH, &size);
        scoped_array<char> log(new char[size]);
        gl->GetShaderInfoLog(shader, size, NULL, log.get());
        DLOG(ERROR) << "Compilation failed: " << log.get();
        gl->DeleteShader(shader);
        shader = 0;
    }
    return shader;
}

const float kTexCoords[] = {
    0.f, 0.f,
    0.f, 2.f,
    2.f, 0.f,
};

}  // anonymous namespace

bool RenderWidgetFullscreenPepper::InitContext() {
  gpu::gles2::GLES2Implementation* gl = ggl::GetImplementation(context_);
  program_ = gl->CreateProgram();

  GLuint vertex_shader =
      CreateShaderFromSource(gl, GL_VERTEX_SHADER, kVertexShader);
  if (!vertex_shader)
    return false;
  gl->AttachShader(program_, vertex_shader);
  gl->DeleteShader(vertex_shader);

  GLuint fragment_shader =
      CreateShaderFromSource(gl, GL_FRAGMENT_SHADER, kFragmentShader);
  if (!fragment_shader)
    return false;
  gl->AttachShader(program_, fragment_shader);
  gl->DeleteShader(fragment_shader);

  gl->BindAttribLocation(program_, 0, "in_tex_coord");
  gl->LinkProgram(program_);
  int status;
  gl->GetProgramiv(program_, GL_LINK_STATUS, &status);
  if (!status) {
    int size = 0;
    gl->GetProgramiv(program_, GL_INFO_LOG_LENGTH, &size);
    scoped_array<char> log(new char[size]);
    gl->GetProgramInfoLog(program_, size, NULL, log.get());
    DLOG(ERROR) << "Link failed: " << log.get();
    return false;
  }
  gl->UseProgram(program_);
  int texture_location = gl->GetUniformLocation(program_, "in_texture");
  gl->Uniform1i(texture_location, 0);

  gl->GenBuffers(1, &buffer_);
  gl->BindBuffer(GL_ARRAY_BUFFER, buffer_);
  gl->BufferData(GL_ARRAY_BUFFER,
                 sizeof(kTexCoords),
                 kTexCoords,
                 GL_STATIC_DRAW);
  gl->VertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, NULL);
  gl->EnableVertexAttribArray(0);
  return true;
}

bool RenderWidgetFullscreenPepper::CheckCompositing() {
  bool compositing = webwidget_->isAcceleratedCompositingActive();
  if (compositing != is_accelerated_compositing_active_) {
    didActivateAcceleratedCompositing(compositing);
  }
  return compositing;
}
<|endoftext|>


<commit_before>/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Jean-David Gadina - www.xs-labs.com / www.digidna.net
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

/*!
 * @copyright   (c) 2015 - Jean-David Gadina - www.xs-labs.com / www.digidna.net
 * @brief       ...
 */

#include <XS/Atomic-Functions.hpp>

#ifdef _WIN32
#include <Windows.h>
#endif

namespace XS
{
    void MemoryBarrier( void )
    {
        #if defined( _WIN64 ) && defined( _M_AMD64 )

        ::__faststorefence();

        #elif defined( _WIN32 ) && defined( _M_IX86 )

        __asm mfence;

        #elif defined( _WIN32 ) && defined( _M_ARM )

        __asm dmb sy;

        #elif defined( __ARM_ARCH )

        __asm__ __volatile__
        (
            "dmb sy"
        );

        #elif defined( __i386__ ) || defined( __x86_64__ )

            __asm__ __volatile__
            (
                "mfence"
            );

        #else

        #error "XS::MemoryBarrier is not implemented for the current target architecture"

        #endif
    }
}
<commit_msg>Fixes for VisualStudio<commit_after>/*******************************************************************************
 * The MIT License (MIT)
 *
 * Copyright (c) 2015 Jean-David Gadina - www.xs-labs.com / www.digidna.net
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 ******************************************************************************/

/*!
 * @copyright   (c) 2015 - Jean-David Gadina - www.xs-labs.com / www.digidna.net
 * @brief       ...
 */

#include <XS/Atomic-Functions.hpp>

#ifdef _WIN32
#include <Windows.h>
#endif

namespace XS
{
    #ifdef MemoryBarrier
    #undef MemoryBarrier /* VisualStudio x64 */
    #endif
    void MemoryBarrier( void )
    {
        #if defined( _WIN64 ) && defined( _M_AMD64 )

        ::__faststorefence();

        #elif defined( _WIN32 ) && defined( _M_IX86 )

        __asm mfence;

        #elif defined( _WIN32 ) && defined( _M_ARM )

        __asm dmb sy;

        #elif defined( __ARM_ARCH )

        __asm__ __volatile__
        (
            "dmb sy"
        );

        #elif defined( __i386__ ) || defined( __x86_64__ )

            __asm__ __volatile__
            (
                "mfence"
            );

        #else

        #error "XS::MemoryBarrier is not implemented for the current target architecture"

        #endif
    }
}
<|endoftext|>


<commit_before>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/kernel/cpumgr.C $                                         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2010,2013              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <assert.h>
#include <kernel/cpumgr.H>
#include <kernel/task.H>
#include <kernel/cpu.H>
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/pagemgr.H>
#include <kernel/console.H>
#include <util/singleton.H>
#include <arch/ppc.H>
#include <kernel/timemgr.H>
#include <sys/sync.h>
#include <kernel/cpuid.H>
#include <kernel/ptmgr.H>
#include <kernel/heapmgr.H>
#include <kernel/intmsghandler.H>
#include <errno.h>
#include <kernel/deferred.H>
#include <kernel/misc.H>
#include <kernel/terminate.H>
#include <kernel/hbterminatetypes.H>
#include <kernel/kernel_reasoncodes.H>

cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES];
bool CpuManager::cv_shutdown_requested = false;
uint64_t CpuManager::cv_shutdown_status = 0;
size_t CpuManager::cv_cpuSeq = 0;
bool CpuManager::cv_forcedMemPeriodic = false;
InteractiveDebug CpuManager::cv_interactive_debug;

CpuManager::CpuManager() : iv_lastStartTimebase(0)
{
    for (int i = 0; i < KERNEL_MAX_SUPPORTED_NODES; i++)
        cv_cpus[i] = NULL;

    memset(&cv_interactive_debug, '\0', sizeof(cv_interactive_debug));
}

cpu_t* CpuManager::getMasterCPU()
{
    for (int i = 0; i < KERNEL_MAX_SUPPORTED_NODES; i++)
    {
        if (NULL == cv_cpus[i])
        {
            continue;
        }

        for (int j = 0; j < KERNEL_MAX_SUPPORTED_CPUS_PER_NODE; j++)
        {
            if ((cv_cpus[i][j] != NULL) && (cv_cpus[i][j]->master))
            {
                return cv_cpus[i][j];
            }
        }
    }
    return NULL;
}

void CpuManager::init()
{
    // For the initial boot we only want to set up CPU objects for the threads
    // on this core.  Otherwise we waste memory with kernel / idle task stacks.
    //
    // As long as the CPU object pointer is NULL, the start.S code won't
    // enter the kernel, so we skip initializing all the other CPUs for now.

    // Determine number of threads on this core.
    size_t threads = getThreadCount();

    // Set up CPU structure.
    cv_cpus[getPIR() / KERNEL_MAX_SUPPORTED_CPUS_PER_NODE] =
        new cpu_t*[KERNEL_MAX_SUPPORTED_CPUS_PER_NODE];

    // Create CPU objects starting at the thread-0 for this core.
    size_t baseCpu = getCpuId() & ~(threads-1);
    for (size_t i = 0; i < threads; i++)
        Singleton<CpuManager>::instance().startCPU(i + baseCpu);
}

void CpuManager::init_slave_smp(cpu_t* cpu)
{
    Singleton<CpuManager>::instance().startSlaveCPU(cpu);
}

void CpuManager::requestShutdown(uint64_t i_status)
{
    cv_shutdown_status = i_status;
    __sync_synchronize();
    cv_shutdown_requested = true;

    // If the shutdown was not called with a Good shutdown status
    // then we know we are shutting down due to error and the
    // status passed back is instead a PLID
    if (i_status != SHUTDOWN_STATUS_GOOD)
    {
        termWritePlid(TI_SHUTDOWN, i_status);

        printk("TI initiated on all threads (shutdown)\n");
    }

    class ExecuteShutdown : public DeferredWork
    {
        public:
            void masterPreWork()
            {
                // The stats can be retrieved from global variables as needed.
                // This can be uncommented for debug if desired
                #ifdef __MEMSTATS__
                if(c->master)
                    HeapManager::stats();
                #endif

            }

            void activeMainWork()
            {
                KernelMisc::shutdown();
            }

            void nonactiveMainWork()
            {
                // Something wasn't synchronized correctly if we got to here.
                // Should not have CPUs coming online while trying to execute
                // a shutdown.
                kassert(false);
            }
    };

    DeferredQueue::insert(new ExecuteShutdown());
}

void CpuManager::startCPU(ssize_t i)
{
    // Save away the current timebase for TB synchronization.
    iv_lastStartTimebase = getTB();

    bool currentCPU = false;
    if (i < 0)
    {
        i = getCpuId();
        currentCPU = true;
    }
    else if (getCpuId() == (uint64_t)i)
    {
        currentCPU = true;
    }

    size_t nodeId = i / KERNEL_MAX_SUPPORTED_CPUS_PER_NODE;
    size_t cpuId = i % KERNEL_MAX_SUPPORTED_CPUS_PER_NODE;

    // Initialize node structure.
    if (NULL == cv_cpus[nodeId])
    {
        cv_cpus[nodeId] = new cpu_t*[KERNEL_MAX_SUPPORTED_CPUS_PER_NODE];
    }

    // Initialize CPU structure.
    if (NULL == cv_cpus[nodeId][cpuId])
    {
        printk("Starting CPU %ld...", i);
        cpu_t* cpu = cv_cpus[nodeId][cpuId] = new cpu_t;

        // Initialize CPU.
        cpu->cpu = i;
        if (currentCPU)
        {
            cpu->master = true;
        }
        else
        {
            cpu->master = false;
        }
        cpu->scheduler = &Singleton<Scheduler>::instance();
        cpu->scheduler_extra = NULL;

        const size_t kernel_page_count = 4;
        const size_t kernel_page_offset = kernel_page_count * PAGESIZE -
                                          8 * sizeof(uint64_t);
        cpu->kernel_stack_bottom = PageManager::allocatePage(kernel_page_count);
        cpu->kernel_stack = reinterpret_cast<void*>(
            reinterpret_cast<uintptr_t>(cpu->kernel_stack_bottom) +
            kernel_page_offset);

        cpu->xscom_mutex = (mutex_t)MUTEX_INITIALIZER;

        // Create idle task.
        cpu->idle_task = TaskManager::createIdleTask();
        cpu->idle_task->cpu = cpu;
        cpu->periodic_count = 0;

        // Call TimeManager setup for a CPU.
        TimeManager::init_cpu(cpu);

        printk("done\n");
    }

    if (currentCPU)
    {
        setDEC(TimeManager::getTimeSliceCount());
        activateCPU(getCpu(i));
    }
    return;
}

void CpuManager::startSlaveCPU(cpu_t* cpu)
{
    // Activate CPU.
    activateCPU(cpu);

    // Sync timebase with master.
    while(getTB() < iv_lastStartTimebase)
    {
        class SyncTimebase : public DeferredWork
        {
            public:
                void masterPreWork()
                {
                    iv_timebase = getTB();
                }

                void activeMainWork()
                {
                    if (getTB() < iv_timebase)
                    {
                        setTB(iv_timebase);
                    }
                }

            private:
                uint64_t iv_timebase;
        };

        SyncTimebase* deferred = new SyncTimebase();
        DeferredQueue::insert(deferred);
        DeferredQueue::execute();
    }

    // Update decrementer.
    setDEC(TimeManager::getTimeSliceCount());

    return;
}

void CpuManager::activateCPU(cpu_t * i_cpu)
{
    // Set active.
    i_cpu->active = true;

    // Update sequence ID.
    do
    {
        uint64_t old_seq = cv_cpuSeq;
        i_cpu->cpu_start_seqid = old_seq + 1 + (1ull << 32);

        if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq,
                                         i_cpu->cpu_start_seqid))
        {
            break;
        }
    } while (1);
    i_cpu->cpu_start_seqid >>= 32;

    // Verify / set SPRs.
    uint64_t msr = getMSR();
    msr |= 0x1000; // TODO: RTC: 51148 - Simics workaround for SW170137.
    kassert(WAKEUP_MSR_VALUE == msr);
    setLPCR(WAKEUP_LPCR_VALUE);
    setRPR(WAKEUP_RPR_VALUE);
}

void CpuManager::deactivateCPU(cpu_t * i_cpu)
{
    // Set inactive.
    i_cpu->active = false;

    // Update sequence ID.
    do
    {
        uint64_t old_seq = cv_cpuSeq;
        uint64_t new_seq = old_seq - 1 + (1ull << 32);

        if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq, new_seq))
        {
            break;
        }
    } while(1);
}

void CpuManager::executePeriodics(cpu_t * i_cpu)
{
    if(i_cpu->master)
    {
        if (cv_interactive_debug.isReady())
        {
            cv_interactive_debug.startDebugTask();
        }

        bool forceMemoryPeriodic = __sync_fetch_and_and(&cv_forcedMemPeriodic,
                                                        false);

        ++(i_cpu->periodic_count);
        if((0 == (i_cpu->periodic_count % CPU_PERIODIC_CHECK_MEMORY)) ||
           (forceMemoryPeriodic))
        {
            uint64_t pcntAvail = PageManager::queryAvail();
            if((pcntAvail < PageManager::LOWMEM_NORM_LIMIT) ||
               (forceMemoryPeriodic))
            {
                VmmManager::flushPageTable();
                ++(i_cpu->periodic_count);   // prevent another flush below
                if(pcntAvail < PageManager::LOWMEM_CRIT_LIMIT)
                {
                    VmmManager::castOutPages(VmmManager::CRITICAL);
                }
                else
                {
                    VmmManager::castOutPages(VmmManager::NORMAL);
                }
            }
        }
        if(0 == (i_cpu->periodic_count % CPU_PERIODIC_FLUSH_PAGETABLE))
        {
            VmmManager::flushPageTable();
        }
        if((0 == (i_cpu->periodic_count % CPU_PERIODIC_DEFRAG)) ||
           (forceMemoryPeriodic))
        {
            class MemoryCoalesce : public DeferredWork
            {
                public:
                    void masterPreWork()
                    {
                        setThreadPriorityVeryHigh();

                        HeapManager::coalesce();
                        PageManager::coalesce();

                        setThreadPriorityHigh();
                    }
            };

            DeferredQueue::insert(new MemoryCoalesce());
        }
    }

    DeferredQueue::execute();

}

int CpuManager::startCore(uint64_t pir)
{
    size_t threads = getThreadCount();
    pir = pir & ~(threads-1);

    if (pir >=
        (KERNEL_MAX_SUPPORTED_NODES * KERNEL_MAX_SUPPORTED_CPUS_PER_NODE))
    {
        return -ENXIO;
    }

    for(size_t i = 0; i < threads; i++)
    {
        Singleton<CpuManager>::instance().startCPU(pir + i);
    }
    __sync_synchronize();

    InterruptMsgHdlr::addCpuCore(pir);

    return 0;
};

size_t CpuManager::getThreadCount()
{
    size_t threads = 0;
    switch (CpuID::getCpuType())
    {
        case CORE_POWER8_VENICE:
        case CORE_POWER8_MURANO:
            threads = 8;
            break;

        case CORE_UNKNOWN:
        default:
            kassert(false);
            break;
    }

    return threads;
}

void CpuManager::forceMemoryPeriodic()
{
    cv_forcedMemPeriodic = true;
}

void CpuManager::critAssert(uint64_t i_failAddr)
{
    /* create SRC amd call terminate immediate*/

    termWriteSRC(TI_CRIT_ASSERT,RC_SHUTDOWN, i_failAddr);

    class ExecuteCritAssert : public DeferredWork
    {
      public:
        void masterPreWork()
        {
            // print status to the console.
            printk("TI initiated on all threads (crit_assert)\n");

        }

        void activeMainWork()
        {
            // Call the function to perform the TI
            terminateExecuteTI();
        }

        void nonactiveMainWork()
        {
            // Something wasn't synchronized correctly if we got to here.
            // Should not have CPUs coming online while trying to execute
            // a shutdown.
            terminateExecuteTI();
        }
    };

    DeferredQueue::insert(new ExecuteCritAssert());

    // Force executeion of the deferred queue.
    DeferredQueue::execute();

}
<commit_msg>Zero out cpu_t struct on creation<commit_after>/* IBM_PROLOG_BEGIN_TAG                                                   */
/* This is an automatically generated prolog.                             */
/*                                                                        */
/* $Source: src/kernel/cpumgr.C $                                         */
/*                                                                        */
/* IBM CONFIDENTIAL                                                       */
/*                                                                        */
/* COPYRIGHT International Business Machines Corp. 2010,2013              */
/*                                                                        */
/* p1                                                                     */
/*                                                                        */
/* Object Code Only (OCO) source materials                                */
/* Licensed Internal Code Source Materials                                */
/* IBM HostBoot Licensed Internal Code                                    */
/*                                                                        */
/* The source code for this program is not published or otherwise         */
/* divested of its trade secrets, irrespective of what has been           */
/* deposited with the U.S. Copyright Office.                              */
/*                                                                        */
/* Origin: 30                                                             */
/*                                                                        */
/* IBM_PROLOG_END_TAG                                                     */
#include <assert.h>
#include <kernel/cpumgr.H>
#include <kernel/task.H>
#include <kernel/cpu.H>
#include <kernel/scheduler.H>
#include <kernel/taskmgr.H>
#include <kernel/pagemgr.H>
#include <kernel/console.H>
#include <util/singleton.H>
#include <arch/ppc.H>
#include <kernel/timemgr.H>
#include <sys/sync.h>
#include <kernel/cpuid.H>
#include <kernel/ptmgr.H>
#include <kernel/heapmgr.H>
#include <kernel/intmsghandler.H>
#include <errno.h>
#include <kernel/deferred.H>
#include <kernel/misc.H>
#include <kernel/terminate.H>
#include <kernel/hbterminatetypes.H>
#include <kernel/kernel_reasoncodes.H>

cpu_t** CpuManager::cv_cpus[KERNEL_MAX_SUPPORTED_NODES];
bool CpuManager::cv_shutdown_requested = false;
uint64_t CpuManager::cv_shutdown_status = 0;
size_t CpuManager::cv_cpuSeq = 0;
bool CpuManager::cv_forcedMemPeriodic = false;
InteractiveDebug CpuManager::cv_interactive_debug;

CpuManager::CpuManager() : iv_lastStartTimebase(0)
{
    for (int i = 0; i < KERNEL_MAX_SUPPORTED_NODES; i++)
        cv_cpus[i] = NULL;

    memset(&cv_interactive_debug, '\0', sizeof(cv_interactive_debug));
}

cpu_t* CpuManager::getMasterCPU()
{
    for (int i = 0; i < KERNEL_MAX_SUPPORTED_NODES; i++)
    {
        if (NULL == cv_cpus[i])
        {
            continue;
        }

        for (int j = 0; j < KERNEL_MAX_SUPPORTED_CPUS_PER_NODE; j++)
        {
            if ((cv_cpus[i][j] != NULL) && (cv_cpus[i][j]->master))
            {
                return cv_cpus[i][j];
            }
        }
    }
    return NULL;
}

void CpuManager::init()
{
    // For the initial boot we only want to set up CPU objects for the threads
    // on this core.  Otherwise we waste memory with kernel / idle task stacks.
    //
    // As long as the CPU object pointer is NULL, the start.S code won't
    // enter the kernel, so we skip initializing all the other CPUs for now.

    // Determine number of threads on this core.
    size_t threads = getThreadCount();

    // Set up CPU structure.
    cv_cpus[getPIR() / KERNEL_MAX_SUPPORTED_CPUS_PER_NODE] =
        new cpu_t*[KERNEL_MAX_SUPPORTED_CPUS_PER_NODE];

    // Create CPU objects starting at the thread-0 for this core.
    size_t baseCpu = getCpuId() & ~(threads-1);
    for (size_t i = 0; i < threads; i++)
        Singleton<CpuManager>::instance().startCPU(i + baseCpu);
}

void CpuManager::init_slave_smp(cpu_t* cpu)
{
    Singleton<CpuManager>::instance().startSlaveCPU(cpu);
}

void CpuManager::requestShutdown(uint64_t i_status)
{
    cv_shutdown_status = i_status;
    __sync_synchronize();
    cv_shutdown_requested = true;

    // If the shutdown was not called with a Good shutdown status
    // then we know we are shutting down due to error and the
    // status passed back is instead a PLID
    if (i_status != SHUTDOWN_STATUS_GOOD)
    {
        termWritePlid(TI_SHUTDOWN, i_status);

        printk("TI initiated on all threads (shutdown)\n");
    }

    class ExecuteShutdown : public DeferredWork
    {
        public:
            void masterPreWork()
            {
                // The stats can be retrieved from global variables as needed.
                // This can be uncommented for debug if desired
                #ifdef __MEMSTATS__
                if(c->master)
                    HeapManager::stats();
                #endif

            }

            void activeMainWork()
            {
                KernelMisc::shutdown();
            }

            void nonactiveMainWork()
            {
                // Something wasn't synchronized correctly if we got to here.
                // Should not have CPUs coming online while trying to execute
                // a shutdown.
                kassert(false);
            }
    };

    DeferredQueue::insert(new ExecuteShutdown());
}

void CpuManager::startCPU(ssize_t i)
{
    // Save away the current timebase for TB synchronization.
    iv_lastStartTimebase = getTB();

    bool currentCPU = false;
    if (i < 0)
    {
        i = getCpuId();
        currentCPU = true;
    }
    else if (getCpuId() == (uint64_t)i)
    {
        currentCPU = true;
    }

    size_t nodeId = i / KERNEL_MAX_SUPPORTED_CPUS_PER_NODE;
    size_t cpuId = i % KERNEL_MAX_SUPPORTED_CPUS_PER_NODE;

    // Initialize node structure.
    if (NULL == cv_cpus[nodeId])
    {
        cv_cpus[nodeId] = new cpu_t*[KERNEL_MAX_SUPPORTED_CPUS_PER_NODE];
    }

    // Initialize CPU structure.
    if (NULL == cv_cpus[nodeId][cpuId])
    {
        printk("Starting CPU %ld...", i);
        cpu_t* cpu = cv_cpus[nodeId][cpuId] = new cpu_t;
        memset(cpu, 0x0, sizeof(cpu_t));

        // Initialize CPU.
        cpu->cpu = i;
        if (currentCPU)
        {
            cpu->master = true;
        }
        else
        {
            cpu->master = false;
        }
        cpu->scheduler = &Singleton<Scheduler>::instance();
        cpu->scheduler_extra = NULL;

        const size_t kernel_page_count = 4;
        const size_t kernel_page_offset = kernel_page_count * PAGESIZE -
                                          8 * sizeof(uint64_t);
        cpu->kernel_stack_bottom = PageManager::allocatePage(kernel_page_count);
        cpu->kernel_stack = reinterpret_cast<void*>(
            reinterpret_cast<uintptr_t>(cpu->kernel_stack_bottom) +
            kernel_page_offset);

        cpu->xscom_mutex = (mutex_t)MUTEX_INITIALIZER;

        // Create idle task.
        cpu->idle_task = TaskManager::createIdleTask();
        cpu->idle_task->cpu = cpu;
        cpu->periodic_count = 0;

        // Call TimeManager setup for a CPU.
        TimeManager::init_cpu(cpu);

        printk("done\n");
    }

    if (currentCPU)
    {
        setDEC(TimeManager::getTimeSliceCount());
        activateCPU(getCpu(i));
    }
    return;
}

void CpuManager::startSlaveCPU(cpu_t* cpu)
{
    // Activate CPU.
    activateCPU(cpu);

    // Sync timebase with master.
    while(getTB() < iv_lastStartTimebase)
    {
        class SyncTimebase : public DeferredWork
        {
            public:
                void masterPreWork()
                {
                    iv_timebase = getTB();
                }

                void activeMainWork()
                {
                    if (getTB() < iv_timebase)
                    {
                        setTB(iv_timebase);
                    }
                }

            private:
                uint64_t iv_timebase;
        };

        SyncTimebase* deferred = new SyncTimebase();
        DeferredQueue::insert(deferred);
        DeferredQueue::execute();
    }

    // Update decrementer.
    setDEC(TimeManager::getTimeSliceCount());

    return;
}

void CpuManager::activateCPU(cpu_t * i_cpu)
{
    // Set active.
    i_cpu->active = true;

    // Update sequence ID.
    do
    {
        uint64_t old_seq = cv_cpuSeq;
        i_cpu->cpu_start_seqid = old_seq + 1 + (1ull << 32);

        if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq,
                                         i_cpu->cpu_start_seqid))
        {
            break;
        }
    } while (1);
    i_cpu->cpu_start_seqid >>= 32;

    // Verify / set SPRs.
    uint64_t msr = getMSR();
    msr |= 0x1000; // TODO: RTC: 51148 - Simics workaround for SW170137.
    kassert(WAKEUP_MSR_VALUE == msr);
    setLPCR(WAKEUP_LPCR_VALUE);
    setRPR(WAKEUP_RPR_VALUE);
}

void CpuManager::deactivateCPU(cpu_t * i_cpu)
{
    // Set inactive.
    i_cpu->active = false;

    // Update sequence ID.
    do
    {
        uint64_t old_seq = cv_cpuSeq;
        uint64_t new_seq = old_seq - 1 + (1ull << 32);

        if (__sync_bool_compare_and_swap(&cv_cpuSeq, old_seq, new_seq))
        {
            break;
        }
    } while(1);
}

void CpuManager::executePeriodics(cpu_t * i_cpu)
{
    if(i_cpu->master)
    {
        if (cv_interactive_debug.isReady())
        {
            cv_interactive_debug.startDebugTask();
        }

        bool forceMemoryPeriodic = __sync_fetch_and_and(&cv_forcedMemPeriodic,
                                                        false);

        ++(i_cpu->periodic_count);
        if((0 == (i_cpu->periodic_count % CPU_PERIODIC_CHECK_MEMORY)) ||
           (forceMemoryPeriodic))
        {
            uint64_t pcntAvail = PageManager::queryAvail();
            if((pcntAvail < PageManager::LOWMEM_NORM_LIMIT) ||
               (forceMemoryPeriodic))
            {
                VmmManager::flushPageTable();
                ++(i_cpu->periodic_count);   // prevent another flush below
                if(pcntAvail < PageManager::LOWMEM_CRIT_LIMIT)
                {
                    VmmManager::castOutPages(VmmManager::CRITICAL);
                }
                else
                {
                    VmmManager::castOutPages(VmmManager::NORMAL);
                }
            }
        }
        if(0 == (i_cpu->periodic_count % CPU_PERIODIC_FLUSH_PAGETABLE))
        {
            VmmManager::flushPageTable();
        }
        if((0 == (i_cpu->periodic_count % CPU_PERIODIC_DEFRAG)) ||
           (forceMemoryPeriodic))
        {
            class MemoryCoalesce : public DeferredWork
            {
                public:
                    void masterPreWork()
                    {
                        setThreadPriorityVeryHigh();

                        HeapManager::coalesce();
                        PageManager::coalesce();

                        setThreadPriorityHigh();
                    }
            };

            DeferredQueue::insert(new MemoryCoalesce());
        }
    }

    DeferredQueue::execute();

}

int CpuManager::startCore(uint64_t pir)
{
    size_t threads = getThreadCount();
    pir = pir & ~(threads-1);

    if (pir >=
        (KERNEL_MAX_SUPPORTED_NODES * KERNEL_MAX_SUPPORTED_CPUS_PER_NODE))
    {
        return -ENXIO;
    }

    for(size_t i = 0; i < threads; i++)
    {
        Singleton<CpuManager>::instance().startCPU(pir + i);
    }
    __sync_synchronize();

    InterruptMsgHdlr::addCpuCore(pir);

    return 0;
};

size_t CpuManager::getThreadCount()
{
    size_t threads = 0;
    switch (CpuID::getCpuType())
    {
        case CORE_POWER8_VENICE:
        case CORE_POWER8_MURANO:
            threads = 8;
            break;

        case CORE_UNKNOWN:
        default:
            kassert(false);
            break;
    }

    return threads;
}

void CpuManager::forceMemoryPeriodic()
{
    cv_forcedMemPeriodic = true;
}

void CpuManager::critAssert(uint64_t i_failAddr)
{
    /* create SRC amd call terminate immediate*/

    termWriteSRC(TI_CRIT_ASSERT,RC_SHUTDOWN, i_failAddr);

    class ExecuteCritAssert : public DeferredWork
    {
      public:
        void masterPreWork()
        {
            // print status to the console.
            printk("TI initiated on all threads (crit_assert)\n");

        }

        void activeMainWork()
        {
            // Call the function to perform the TI
            terminateExecuteTI();
        }

        void nonactiveMainWork()
        {
            // Something wasn't synchronized correctly if we got to here.
            // Should not have CPUs coming online while trying to execute
            // a shutdown.
            terminateExecuteTI();
        }
    };

    DeferredQueue::insert(new ExecuteCritAssert());

    // Force executeion of the deferred queue.
    DeferredQueue::execute();

}
<|endoftext|>


<commit_before>#include <ignition/math/Pose3.hh>
#include "gazebo/physics/physics.hh"
#include "gazebo/common/common.hh"
#include "gazebo/gazebo.hh"

#include <ros/ros.h>
#include <boost/bind/bind.hpp>
#include <tf2_msgs/TFMessage.h>

namespace gazebo
{

struct tokens: std::ctype<char>
{
    tokens(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        typedef std::ctype<char> cctype;
        static const cctype::mask *const_rc= cctype::classic_table();

        static cctype::mask rc[cctype::table_size];
        std::memcpy(rc, const_rc, cctype::table_size * sizeof(cctype::mask));

        rc[','] = std::ctype_base::space;
        rc[' '] = std::ctype_base::space;
        return &rc[0];
    }
};

class LabPhantoms;
void onTFData2(const tf2_msgs::TFMessage::ConstPtr& msg);
void onTFData(const tf2_msgs::TFMessage::ConstPtr& msg);//, LabPhantoms *plugin);

math::Pose Msg2Pose(geometry_msgs::Transform const& msg)
{
    math::Pose pose;
    math::Vector3 v;
    math::Quaternion q;

    v.x = msg.translation.x;
    v.y = msg.translation.y;
    v.z = msg.translation.z;
    q.w = msg.rotation.w;
    q.x = msg.rotation.x;
    q.y = msg.rotation.y;
    q.z = msg.rotation.z;

    pose.Set(v, q);
    return pose;
}

class LabPhantoms : public WorldPlugin
{
  protected:
  bool havePhantom(std::string const& name)
  {
      bool retq = false;
      int maxK = phantoms.size();
      for(int k = 0; (!retq) && (k < maxK); k++)
          retq = (phantoms[k] == name);
      return retq;
  }

  public:
  LabPhantoms()
  {
      n = 0;
      parentWorld.reset();
  }
  ~LabPhantoms()
  {
      if(n)
          delete n;
  }

  void onTFData(const tf2_msgs::TFMessageConstPtr& msg)
  {
      if(!(parentWorld.get()))
          return;
      physics::WorldPtr world = parentWorld;

      int maxK = msg->transforms.size();

      for(int k = 0; k < maxK; k++)
      {
          geometry_msgs::TransformStamped transform = msg->transforms[k];
          std::string parentFrame = transform.header.frame_id;
          std::string childFrame = transform.child_frame_id;

          if(havePhantom(childFrame))
          {
              physics::ModelPtr childModel = world->GetModel(childFrame);
              physics::ModelPtr parentModel = world->GetModel(parentFrame);

              if((childModel.get()) && (parentModel.get()))
              {
                  math::Pose parent2Child = Msg2Pose(transform.transform);
                  math::Pose world2Parent = parentModel->GetWorldPose();
                  childModel->SetWorldPose(parent2Child*world2Parent);
              }
          }
      }
  }

  void Load(physics::WorldPtr _parent, sdf::ElementPtr _sdf)
  {
    parentWorld = _parent;
    pluginParameters = _sdf;
    char nodeName[] = "labphantoms";
    char* argv[] = {nodeName};
    int argc = 1;
    ros::init(argc, argv, "labphantoms");
    n = new ros::NodeHandle();

    ros::Subscriber sub = n->subscribe("/tf", 1, &LabPhantoms::onTFData, this);

    if(pluginParameters->HasElement("trackedModels"))
    {
        std::string trackedModels = pluginParameters->Get<std::string>("trackedModels");
        ROS_INFO("Tracked Models as given by launch file: %s", trackedModels);

        std::stringstream ss(trackedModels);
        ss.imbue(std::locale(std::locale(), new tokens()));
        std::istream_iterator<std::string> begin(ss);
        std::istream_iterator<std::string> end;
        std::vector<std::string> vstrings(begin, end);
        std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
        phantoms = vstrings;
    }
  }

  protected:
    ros::NodeHandle *n;
    physics::WorldPtr parentWorld;
    sdf::ElementPtr pluginParameters;
    std::vector<std::string> phantoms;
};

// Register this plugin with the simulator
GZ_REGISTER_WORLD_PLUGIN(LabPhantoms)
}
<commit_msg>Code fix for printout.<commit_after>#include <ignition/math/Pose3.hh>
#include "gazebo/physics/physics.hh"
#include "gazebo/common/common.hh"
#include "gazebo/gazebo.hh"

#include <ros/ros.h>
#include <boost/bind/bind.hpp>
#include <tf2_msgs/TFMessage.h>

namespace gazebo
{

struct tokens: std::ctype<char>
{
    tokens(): std::ctype<char>(get_table()) {}

    static std::ctype_base::mask const* get_table()
    {
        typedef std::ctype<char> cctype;
        static const cctype::mask *const_rc= cctype::classic_table();

        static cctype::mask rc[cctype::table_size];
        std::memcpy(rc, const_rc, cctype::table_size * sizeof(cctype::mask));

        rc[','] = std::ctype_base::space;
        rc[' '] = std::ctype_base::space;
        return &rc[0];
    }
};

class LabPhantoms;
void onTFData2(const tf2_msgs::TFMessage::ConstPtr& msg);
void onTFData(const tf2_msgs::TFMessage::ConstPtr& msg);//, LabPhantoms *plugin);

math::Pose Msg2Pose(geometry_msgs::Transform const& msg)
{
    math::Pose pose;
    math::Vector3 v;
    math::Quaternion q;

    v.x = msg.translation.x;
    v.y = msg.translation.y;
    v.z = msg.translation.z;
    q.w = msg.rotation.w;
    q.x = msg.rotation.x;
    q.y = msg.rotation.y;
    q.z = msg.rotation.z;

    pose.Set(v, q);
    return pose;
}

class LabPhantoms : public WorldPlugin
{
  protected:
  bool havePhantom(std::string const& name)
  {
      bool retq = false;
      int maxK = phantoms.size();
      for(int k = 0; (!retq) && (k < maxK); k++)
          retq = (phantoms[k] == name);
      return retq;
  }

  public:
  LabPhantoms()
  {
      n = 0;
      parentWorld.reset();
  }
  ~LabPhantoms()
  {
      if(n)
          delete n;
  }

  void onTFData(const tf2_msgs::TFMessageConstPtr& msg)
  {
      if(!(parentWorld.get()))
          return;
      physics::WorldPtr world = parentWorld;

      int maxK = msg->transforms.size();

      for(int k = 0; k < maxK; k++)
      {
          geometry_msgs::TransformStamped transform = msg->transforms[k];
          std::string parentFrame = transform.header.frame_id;
          std::string childFrame = transform.child_frame_id;

          if(havePhantom(childFrame))
          {
              physics::ModelPtr childModel = world->GetModel(childFrame);
              physics::ModelPtr parentModel = world->GetModel(parentFrame);

              if((childModel.get()) && (parentModel.get()))
              {
                  math::Pose parent2Child = Msg2Pose(transform.transform);
                  math::Pose world2Parent = parentModel->GetWorldPose();
                  childModel->SetWorldPose(parent2Child*world2Parent);
              }
          }
      }
  }

  void Load(physics::WorldPtr _parent, sdf::ElementPtr _sdf)
  {
    parentWorld = _parent;
    pluginParameters = _sdf;
    char nodeName[] = "labphantoms";
    char* argv[] = {nodeName};
    int argc = 1;
    ros::init(argc, argv, "labphantoms");
    n = new ros::NodeHandle();

    ros::Subscriber sub = n->subscribe("/tf", 1, &LabPhantoms::onTFData, this);

    if(pluginParameters->HasElement("trackedModels"))
    {
        std::string trackedModels = pluginParameters->Get<std::string>("trackedModels");
        std::string dbgStr = "Tracked Models as given by launch file: ";
        dbgStr = dbgStr + trackedModels;
        ROS_INFO(dbgStr.c_str());

        std::stringstream ss(trackedModels);
        ss.imbue(std::locale(std::locale(), new tokens()));
        std::istream_iterator<std::string> begin(ss);
        std::istream_iterator<std::string> end;
        std::vector<std::string> vstrings(begin, end);
        std::copy(vstrings.begin(), vstrings.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
        phantoms = vstrings;
    }
  }

  protected:
    ros::NodeHandle *n;
    physics::WorldPtr parentWorld;
    sdf::ElementPtr pluginParameters;
    std::vector<std::string> phantoms;
};

// Register this plugin with the simulator
GZ_REGISTER_WORLD_PLUGIN(LabPhantoms)
}
<|endoftext|>


<commit_before>#include "LOADSAVE.H"

#include "SPECIFIC.H"

static struct REQUESTER InsertReq;
static struct REQUESTER CheckingReq;
static struct REQUESTER FormatReq;
static struct REQUESTER OverwriteReq;
static struct REQUESTER LoadingReq;
static struct REQUESTER SavingReq;
static struct REQUESTER FormattingReq;
static struct REQUESTER LoadOkReq;
static struct REQUESTER LoadErrorReq;
static struct REQUESTER SaveOkReq;
static struct REQUESTER SaveErrorReq;
static struct REQUESTER FormatErrorReq;
static struct REQUESTER NotFormatReq;
static struct REQUESTER NoSpaceReq;
static struct REQUESTER NoGamesReq;

int SaveGame()//62E3C, 63520
{
	S_Warn("[SaveGame] - Unimplemented!\n");
	return 0;
}

int LoadGame()//6297C, 63060
{
	S_Warn("[LoadGame] - Unimplemented!\n");
	return 0;
}

int DisplayFiles(int cursor, int maxfiles)//626E4, 62DC8
{
	S_Warn("[DisplayFiles] - Unimplemented!\n");
	return 0;
}<commit_msg>Add Partial DisplayFiles();<commit_after>#include "LOADSAVE.H"

#include "DRAWPHAS.H"
#include "GAMEFLOW.H"
#include "MEMCARD.H"
#include "SPECIFIC.H"

#include <stdio.h>
#include <string.h>

static struct REQUESTER InsertReq;
static struct REQUESTER CheckingReq;
static struct REQUESTER FormatReq;
static struct REQUESTER OverwriteReq;
static struct REQUESTER LoadingReq;
static struct REQUESTER SavingReq;
static struct REQUESTER FormattingReq;
static struct REQUESTER LoadOkReq;
static struct REQUESTER LoadErrorReq;
static struct REQUESTER SaveOkReq;
static struct REQUESTER SaveErrorReq;
static struct REQUESTER FormatErrorReq;
static struct REQUESTER NotFormatReq;
static struct REQUESTER NoSpaceReq;
static struct REQUESTER NoGamesReq;

int SaveGame()//62E3C, 63520
{
	S_Warn("[SaveGame] - Unimplemented!\n");
	return 0;
}

int LoadGame()//6297C, 63060
{
	S_Warn("[LoadGame] - Unimplemented!\n");
	return 0;
}

int DisplayFiles(int cursor, int maxfiles)//626E4(<), 62DC8(<)
{
	int i;
	int n;
	int y;
	unsigned short flags;
	char buf[80];
	struct PACKEDNAME* pn = (struct PACKEDNAME*)&mcFileNames[0][0];

	if (Gameflow->Language - 1 & 7 < 4)
	{
		flags = 0x9001;
	}
	else
	{
		flags = 0x8000;
	}

	//loc_62E24
	n = mcNumFiles + (mcBlocksFree / 2);
	if (n > maxfiles)
	{
		n = maxfiles;
	}

	//loc_62768
	y = 120 - ((n * 2) + n) * 4;

	//s2 = 0x404040;

	//loc_6279C
	if (n > 0)
	{
		for (i = 0; i < n; i++, pn++, y += 24)
		{
			if (mcNumFiles < 0)
			{
				///@FIXME I have no idea what's going on here!!
				//a1 = BASLUS-01311@@@[]@@A so how on earth is sprintf working?

				//a1 = 0xA1F28//? - this points to SLUS string, confusing looks like static arr.
				//a3 = pn->Days & 0x3F;
				//t1 = gfStringOffset;
				//a2 = gfStringWad;
				//a2 = ;
				//v0 = &gfStringWad[gfStringOffset[STR_SECRETS_NUM]];
				//v1 = pn->Hours & 0x3F;
				//v0 = pn->Min & 0x3F;
				//v1 = pn->Sec & 0x3F;
				//sprintf(&buf[0], "" &gfStringWad[gfStringOffset[gfLevelNames[pn->Level & 0x3F]]], pn->Days & 0x3F, pn->Hours & 0x3F, pn->Min & 0x3F, pn->Sec & 0x3F);
			}
			else
			{
				//loc_62838
				strcpy(&buf[0], &gfStringWad[gfStringOffset[STR_RESUME]]);
			}

			//flags on stack_88
			if (i == cursor)
			{
				//loc_62870
				PrintString(256, (y + 15) & 0xFFFF, 1, &buf[0]);
			}
			else
			{
				PrintString(256, (y + 15) & 0xFFFF, 5, &buf[0]);
			}

			//DrawF4(32, y & 0xFFFF, 448, 23);
			//DrawTPage(0, 0);
			//DrawLineH(34,  (y + 1)  & 0xFFFF, 444, 0);
			//DrawLineH(34,  (y + 21) & 0xFFFF, 444, 0);
			//DrawLineV(34,  (y + 1)  & 0xFFFF,  21, 0);
			//DrawLineV(477, (y + 1)  & 0xFFFF,  21, 0);
			//DrawTPage(0, 1);
		}
	}

	return n;
}<|endoftext|>