1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2014 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include <cstring> 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/platform.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/semaphore.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/base/platform/time.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "testing/gtest/include/gtest/gtest.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace base { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const char kAlphabet[] = "XKOAD"; 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const size_t kAlphabetSize = sizeof(kAlphabet) - 1; 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const size_t kBufferSize = 987; // GCD(buffer size, alphabet size) = 1 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const size_t kDataSize = kBufferSize * kAlphabetSize * 10; 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass ProducerThread final : public Thread { 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProducerThread(char* buffer, Semaphore* free_space, Semaphore* used_space) 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("ProducerThread")), 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_(buffer), 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_(free_space), 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_(used_space) {} 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 31014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Run() override { 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t n = 0; n < kDataSize; ++n) { 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_->Wait(); 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize]; 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_->Signal(); 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* buffer_; 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const free_space_; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const used_space_; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass ConsumerThread final : public Thread { 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsumerThread(const char* buffer, Semaphore* free_space, 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* used_space) 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("ConsumerThread")), 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_(buffer), 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_(free_space), 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_(used_space) {} 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 55014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Run() override { 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t n = 0; n < kDataSize; ++n) { 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_->Wait(); 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]); 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_->Signal(); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* buffer_; 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const free_space_; 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const used_space_; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 70014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochclass WaitAndSignalThread final : public Thread { 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit WaitAndSignalThread(Semaphore* semaphore) 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {} 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 75014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch void Run() override { 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int n = 0; n < 100; ++n) { 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore_->Wait(); 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1))); 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore_->Signal(); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const semaphore_; 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, ProducerConsumer) { 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char buffer[kBufferSize]; 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::memset(buffer, 0, sizeof(buffer)); 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore free_space(kBufferSize); 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore used_space(0); 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProducerThread producer_thread(buffer, &free_space, &used_space); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsumerThread consumer_thread(buffer, &free_space, &used_space); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch producer_thread.Start(); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch consumer_thread.Start(); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch producer_thread.Join(); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch consumer_thread.Join(); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, WaitAndSignal) { 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore semaphore(0); 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WaitAndSignalThread t1(&semaphore); 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WaitAndSignalThread t2(&semaphore); 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t1.Start(); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t2.Start(); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make something available. 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t1.Join(); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t2.Join(); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Wait(); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1))); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, WaitFor) { 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore semaphore(0); 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Semaphore not signalled - timeout. 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Semaphore signalled - no timeout. 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace base 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8 143