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 |