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 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen 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 virtual ~ProducerThread() {} 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Run() OVERRIDE { 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t n = 0; n < kDataSize; ++n) { 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_->Wait(); 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_[n % kBufferSize] = kAlphabet[n % kAlphabetSize]; 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_->Signal(); 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char* buffer_; 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const free_space_; 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const used_space_; 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass ConsumerThread FINAL : public Thread { 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsumerThread(const char* buffer, Semaphore* free_space, 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* used_space) 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("ConsumerThread")), 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch buffer_(buffer), 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_(free_space), 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_(used_space) {} 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~ConsumerThread() {} 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Run() OVERRIDE { 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (size_t n = 0; n < kDataSize; ++n) { 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch used_space_->Wait(); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXPECT_EQ(kAlphabet[n % kAlphabetSize], buffer_[n % kBufferSize]); 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch free_space_->Signal(); 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const char* buffer_; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const free_space_; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const used_space_; 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochclass WaitAndSignalThread FINAL : public Thread { 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch public: 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch explicit WaitAndSignalThread(Semaphore* semaphore) 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch : Thread(Options("WaitAndSignalThread")), semaphore_(semaphore) {} 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual ~WaitAndSignalThread() {} 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch virtual void Run() OVERRIDE { 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int n = 0; n < 100; ++n) { 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore_->Wait(); 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore_->WaitFor(TimeDelta::FromMicroseconds(1))); 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore_->Signal(); 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch private: 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore* const semaphore_; 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch}; 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, ProducerConsumer) { 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char buffer[kBufferSize]; 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch std::memset(buffer, 0, sizeof(buffer)); 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore free_space(kBufferSize); 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore used_space(0); 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ProducerThread producer_thread(buffer, &free_space, &used_space); 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ConsumerThread consumer_thread(buffer, &free_space, &used_space); 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch producer_thread.Start(); 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch consumer_thread.Start(); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch producer_thread.Join(); 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch consumer_thread.Join(); 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, WaitAndSignal) { 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore semaphore(0); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WaitAndSignalThread t1(&semaphore); 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch WaitAndSignalThread t2(&semaphore); 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t1.Start(); 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t2.Start(); 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Make something available. 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t1.Join(); 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t2.Join(); 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Wait(); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch EXPECT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1))); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochTEST(Semaphore, WaitFor) { 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Semaphore semaphore(0); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Semaphore not signalled - timeout. 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_FALSE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Semaphore signalled - no timeout. 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(0))); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(100))); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch semaphore.Signal(); 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ASSERT_TRUE(semaphore.WaitFor(TimeDelta::FromMicroseconds(1000))); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace base 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8 146