| OLD | NEW |
| 1 // Copyright 2010 the V8 project authors. All rights reserved. | 1 // Copyright 2010 the V8 project authors. All rights reserved. |
| 2 // | 2 // |
| 3 // Tests of circular queues. | 3 // Tests of circular queues. |
| 4 | 4 |
| 5 #include "v8.h" | 5 #include "v8.h" |
| 6 #include "circular-queue-inl.h" | 6 #include "circular-queue-inl.h" |
| 7 #include "cctest.h" | 7 #include "cctest.h" |
| 8 | 8 |
| 9 namespace i = v8::internal; | 9 namespace i = v8::internal; |
| 10 | 10 |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 CHECK(cq.IsEmpty()); | 54 CHECK(cq.IsEmpty()); |
| 55 } | 55 } |
| 56 | 56 |
| 57 | 57 |
| 58 TEST(SamplingCircularQueue) { | 58 TEST(SamplingCircularQueue) { |
| 59 typedef SamplingCircularQueue::Cell Record; | 59 typedef SamplingCircularQueue::Cell Record; |
| 60 const int kRecordsPerChunk = 4; | 60 const int kRecordsPerChunk = 4; |
| 61 SamplingCircularQueue scq(sizeof(Record), | 61 SamplingCircularQueue scq(sizeof(Record), |
| 62 kRecordsPerChunk * sizeof(Record), | 62 kRecordsPerChunk * sizeof(Record), |
| 63 3); | 63 3); |
| 64 scq.SetUpProducer(); | |
| 65 scq.SetUpConsumer(); | |
| 66 | 64 |
| 67 // Check that we are using non-reserved values. | 65 // Check that we are using non-reserved values. |
| 68 CHECK_NE(SamplingCircularQueue::kClear, 1); | 66 CHECK_NE(SamplingCircularQueue::kClear, 1); |
| 69 CHECK_NE(SamplingCircularQueue::kEnd, 1); | 67 CHECK_NE(SamplingCircularQueue::kEnd, 1); |
| 70 // Fill up the first chunk. | 68 // Fill up the first chunk. |
| 71 CHECK_EQ(NULL, scq.StartDequeue()); | 69 CHECK_EQ(NULL, scq.StartDequeue()); |
| 72 for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { | 70 for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { |
| 73 Record* rec = reinterpret_cast<Record*>(scq.Enqueue()); | 71 Record* rec = reinterpret_cast<Record*>(scq.Enqueue()); |
| 74 CHECK_NE(NULL, rec); | 72 CHECK_NE(NULL, rec); |
| 75 *rec = i; | 73 *rec = i; |
| (...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 114 Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); | 112 Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); |
| 115 CHECK_NE(NULL, rec); | 113 CHECK_NE(NULL, rec); |
| 116 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); | 114 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); |
| 117 CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); | 115 CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 118 scq.FinishDequeue(); | 116 scq.FinishDequeue(); |
| 119 CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); | 117 CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 120 } | 118 } |
| 121 // Consumption must still be possible as the first cell of the | 119 // Consumption must still be possible as the first cell of the |
| 122 // last chunk is not clean. | 120 // last chunk is not clean. |
| 123 CHECK_NE(NULL, scq.StartDequeue()); | 121 CHECK_NE(NULL, scq.StartDequeue()); |
| 122 } |
| 124 | 123 |
| 125 scq.TearDownConsumer(); | 124 |
| 126 scq.TearDownProducer(); | 125 namespace { |
| 126 |
| 127 class ProducerThread: public i::Thread { |
| 128 public: |
| 129 typedef SamplingCircularQueue::Cell Record; |
| 130 |
| 131 ProducerThread(SamplingCircularQueue* scq, |
| 132 int records_per_chunk, |
| 133 Record value, |
| 134 i::Semaphore* finished) |
| 135 : scq_(scq), |
| 136 records_per_chunk_(records_per_chunk), |
| 137 value_(value), |
| 138 finished_(finished) { } |
| 139 |
| 140 virtual void Run() { |
| 141 for (Record i = value_; i < value_ + records_per_chunk_; ++i) { |
| 142 Record* rec = reinterpret_cast<Record*>(scq_->Enqueue()); |
| 143 CHECK_NE(NULL, rec); |
| 144 *rec = i; |
| 145 } |
| 146 |
| 147 finished_->Signal(); |
| 148 } |
| 149 |
| 150 private: |
| 151 SamplingCircularQueue* scq_; |
| 152 const int records_per_chunk_; |
| 153 Record value_; |
| 154 i::Semaphore* finished_; |
| 155 }; |
| 156 |
| 157 } // namespace |
| 158 |
| 159 TEST(SamplingCircularQueueMultithreading) { |
| 160 // Emulate multiple VM threads working 'one thread at a time.' |
| 161 // This test enqueues data from different threads. This corresponds |
| 162 // to the case of profiling under Linux, where signal handler that |
| 163 // does sampling is called in the context of different VM threads. |
| 164 |
| 165 typedef ProducerThread::Record Record; |
| 166 const int kRecordsPerChunk = 4; |
| 167 SamplingCircularQueue scq(sizeof(Record), |
| 168 kRecordsPerChunk * sizeof(Record), |
| 169 3); |
| 170 i::Semaphore* semaphore = i::OS::CreateSemaphore(0); |
| 171 // Don't poll ahead, making possible to check data in the buffer |
| 172 // immediately after enqueuing. |
| 173 scq.FlushResidualRecords(); |
| 174 |
| 175 // Check that we are using non-reserved values. |
| 176 CHECK_NE(SamplingCircularQueue::kClear, 1); |
| 177 CHECK_NE(SamplingCircularQueue::kEnd, 1); |
| 178 ProducerThread producer1(&scq, kRecordsPerChunk, 1, semaphore); |
| 179 ProducerThread producer2(&scq, kRecordsPerChunk, 10, semaphore); |
| 180 ProducerThread producer3(&scq, kRecordsPerChunk, 20, semaphore); |
| 181 |
| 182 CHECK_EQ(NULL, scq.StartDequeue()); |
| 183 producer1.Start(); |
| 184 semaphore->Wait(); |
| 185 for (Record i = 1; i < 1 + kRecordsPerChunk; ++i) { |
| 186 Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); |
| 187 CHECK_NE(NULL, rec); |
| 188 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); |
| 189 CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 190 scq.FinishDequeue(); |
| 191 CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 192 } |
| 193 |
| 194 CHECK_EQ(NULL, scq.StartDequeue()); |
| 195 producer2.Start(); |
| 196 semaphore->Wait(); |
| 197 for (Record i = 10; i < 10 + kRecordsPerChunk; ++i) { |
| 198 Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); |
| 199 CHECK_NE(NULL, rec); |
| 200 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); |
| 201 CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 202 scq.FinishDequeue(); |
| 203 CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 204 } |
| 205 |
| 206 CHECK_EQ(NULL, scq.StartDequeue()); |
| 207 producer3.Start(); |
| 208 semaphore->Wait(); |
| 209 for (Record i = 20; i < 20 + kRecordsPerChunk; ++i) { |
| 210 Record* rec = reinterpret_cast<Record*>(scq.StartDequeue()); |
| 211 CHECK_NE(NULL, rec); |
| 212 CHECK_EQ(static_cast<int64_t>(i), static_cast<int64_t>(*rec)); |
| 213 CHECK_EQ(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 214 scq.FinishDequeue(); |
| 215 CHECK_NE(rec, reinterpret_cast<Record*>(scq.StartDequeue())); |
| 216 } |
| 217 |
| 218 CHECK_EQ(NULL, scq.StartDequeue()); |
| 219 |
| 220 delete semaphore; |
| 127 } | 221 } |
| OLD | NEW |