blob: 0fb86d6fc50ab703ee7d84b434518fabfcd11cf1 [file] [log] [blame]
Riley Andrews9e558792014-06-05 19:34:40 -07001#include <gtest/gtest.h>
Jesse Hall41129a22017-02-13 15:19:24 -08002#include <android/sync.h>
Riley Andrews9e558792014-06-05 19:34:40 -07003#include <sw_sync.h>
4#include <fcntl.h>
5#include <vector>
6#include <string>
7#include <cassert>
8#include <iostream>
9#include <unistd.h>
10#include <thread>
11#include <poll.h>
12#include <mutex>
13#include <algorithm>
14#include <tuple>
15#include <random>
16#include <unordered_map>
17
18// TODO: better stress tests?
19// Handle more than 64 fd's simultaneously, i.e. fix sync_fence_info's 4k limit.
20// Handle wraparound in timelines like nvidia.
21
22using namespace std;
23
24namespace {
25
26// C++ wrapper class for sync timeline.
27class SyncTimeline {
28 int m_fd = -1;
29 bool m_fdInitialized = false;
30public:
31 SyncTimeline(const SyncTimeline &) = delete;
32 SyncTimeline& operator=(SyncTimeline&) = delete;
33 SyncTimeline() noexcept {
34 int fd = sw_sync_timeline_create();
35 if (fd == -1)
36 return;
37 m_fdInitialized = true;
38 m_fd = fd;
39 }
40 void destroy() {
41 if (m_fdInitialized) {
42 close(m_fd);
43 m_fd = -1;
44 m_fdInitialized = false;
45 }
46 }
47 ~SyncTimeline() {
48 destroy();
49 }
50 bool isValid() const {
51 if (m_fdInitialized) {
52 int status = fcntl(m_fd, F_GETFD, 0);
Tom Cherrya7c7bce2015-11-05 10:07:53 -080053 if (status >= 0)
Riley Andrews9e558792014-06-05 19:34:40 -070054 return true;
55 else
56 return false;
57 }
58 else {
59 return false;
60 }
61 }
62 int getFd() const {
63 return m_fd;
64 }
65 int inc(int val = 1) {
66 return sw_sync_timeline_inc(m_fd, val);
67 }
68};
69
70struct SyncPointInfo {
71 std::string driverName;
72 std::string objectName;
73 uint64_t timeStampNs;
74 int status; // 1 sig, 0 active, neg is err
75};
76
77// Wrapper class for sync fence.
78class SyncFence {
79 int m_fd = -1;
80 bool m_fdInitialized = false;
81 static int s_fenceCount;
82
83 void setFd(int fd) {
84 m_fd = fd;
85 m_fdInitialized = true;
86 }
87 void clearFd() {
88 m_fd = -1;
89 m_fdInitialized = false;
90 }
91public:
92 bool isValid() const {
93 if (m_fdInitialized) {
94 int status = fcntl(m_fd, F_GETFD, 0);
Tom Cherrya7c7bce2015-11-05 10:07:53 -080095 if (status >= 0)
Riley Andrews9e558792014-06-05 19:34:40 -070096 return true;
97 else
98 return false;
99 }
100 else {
101 return false;
102 }
103 }
104 SyncFence& operator=(SyncFence &&rhs) noexcept {
105 destroy();
106 if (rhs.isValid()) {
107 setFd(rhs.getFd());
108 rhs.clearFd();
109 }
110 return *this;
111 }
112 SyncFence(SyncFence &&fence) noexcept {
113 if (fence.isValid()) {
114 setFd(fence.getFd());
115 fence.clearFd();
116 }
117 }
118 SyncFence(const SyncFence &fence) noexcept {
119 // This is ok, as sync fences are immutable after construction, so a dup
120 // is basically the same thing as a copy.
121 if (fence.isValid()) {
122 int fd = dup(fence.getFd());
123 if (fd == -1)
124 return;
125 setFd(fd);
126 }
127 }
128 SyncFence(const SyncTimeline &timeline,
129 int value,
130 const char *name = nullptr) noexcept {
131 std::string autoName = "allocFence";
132 autoName += s_fenceCount;
133 s_fenceCount++;
134 int fd = sw_sync_fence_create(timeline.getFd(), name ? name : autoName.c_str(), value);
135 if (fd == -1)
136 return;
137 setFd(fd);
138 }
139 SyncFence(const SyncFence &a, const SyncFence &b, const char *name = nullptr) noexcept {
140 std::string autoName = "mergeFence";
141 autoName += s_fenceCount;
142 s_fenceCount++;
143 int fd = sync_merge(name ? name : autoName.c_str(), a.getFd(), b.getFd());
144 if (fd == -1)
145 return;
146 setFd(fd);
147 }
148 SyncFence(const vector<SyncFence> &sources) noexcept {
149 assert(sources.size());
150 SyncFence temp(*begin(sources));
151 for (auto itr = ++begin(sources); itr != end(sources); ++itr) {
152 temp = SyncFence(*itr, temp);
153 }
154 if (temp.isValid()) {
155 setFd(temp.getFd());
156 temp.clearFd();
157 }
158 }
159 void destroy() {
160 if (isValid()) {
161 close(m_fd);
162 clearFd();
163 }
164 }
165 ~SyncFence() {
166 destroy();
167 }
168 int getFd() const {
169 return m_fd;
170 }
171 int wait(int timeout = -1) {
172 return sync_wait(m_fd, timeout);
173 }
174 vector<SyncPointInfo> getInfo() const {
Riley Andrews9e558792014-06-05 19:34:40 -0700175 vector<SyncPointInfo> fenceInfo;
Jesse Hall83666162017-02-12 16:32:39 -0800176 struct sync_file_info *info = sync_file_info(getFd());
Riley Andrews9e558792014-06-05 19:34:40 -0700177 if (!info) {
178 return fenceInfo;
179 }
Jesse Hall83666162017-02-12 16:32:39 -0800180 const auto fences = sync_get_fence_info(info);
181 for (uint32_t i = 0; i < info->num_fences; i++) {
Riley Andrews9e558792014-06-05 19:34:40 -0700182 fenceInfo.push_back(SyncPointInfo{
Jesse Hall83666162017-02-12 16:32:39 -0800183 fences[i].driver_name,
184 fences[i].obj_name,
185 fences[i].timestamp_ns,
186 fences[i].status});
Riley Andrews9e558792014-06-05 19:34:40 -0700187 }
Jesse Hall83666162017-02-12 16:32:39 -0800188 sync_file_info_free(info);
Riley Andrews9e558792014-06-05 19:34:40 -0700189 return fenceInfo;
190 }
191 int getSize() const {
192 return getInfo().size();
193 }
194 int getSignaledCount() const {
195 return countWithStatus(1);
196 }
197 int getActiveCount() const {
198 return countWithStatus(0);
199 }
200 int getErrorCount() const {
201 return countWithStatus(-1);
202 }
203private:
204 int countWithStatus(int status) const {
205 int count = 0;
206 for (auto &info : getInfo()) {
207 if (info.status == status) {
208 count++;
209 }
210 }
211 return count;
212 }
213};
214
Jesse Hall83666162017-02-12 16:32:39 -0800215static void CheckModernLegacyInfoMatch(const SyncFence& f) {
216 struct sync_file_info* modern = sync_file_info(f.getFd());
217 struct sync_fence_info_data* legacy = sync_fence_info(f.getFd());
218
219 ASSERT_TRUE(modern != NULL);
220 ASSERT_TRUE(legacy != NULL);
221
222 EXPECT_STREQ(modern->name, legacy->name);
223 EXPECT_EQ(modern->status, legacy->status);
224
225 uint32_t fenceIdx = 0;
226 struct sync_pt_info* pt = sync_pt_info(legacy, NULL);
227 const struct sync_fence_info* fences = sync_get_fence_info(modern);
228 while (fenceIdx < modern->num_fences && pt != NULL) {
229 EXPECT_STREQ(fences[fenceIdx].obj_name, pt->obj_name);
230 EXPECT_STREQ(fences[fenceIdx].driver_name, pt->driver_name);
231 EXPECT_EQ(fences[fenceIdx].status, pt->status);
232 EXPECT_EQ(fences[fenceIdx].timestamp_ns, pt->timestamp_ns);
233
234 fenceIdx++;
235 pt = sync_pt_info(legacy, pt);
236 }
237 EXPECT_EQ(fenceIdx, modern->num_fences);
238 EXPECT_EQ(NULL, pt);
239}
240
Riley Andrews9e558792014-06-05 19:34:40 -0700241int SyncFence::s_fenceCount = 0;
242
243TEST(AllocTest, Timeline) {
244 SyncTimeline timeline;
245 ASSERT_TRUE(timeline.isValid());
246}
247
248TEST(AllocTest, Fence) {
249 SyncTimeline timeline;
250 ASSERT_TRUE(timeline.isValid());
251
252 SyncFence fence(timeline, 1);
253 ASSERT_TRUE(fence.isValid());
Jesse Hall83666162017-02-12 16:32:39 -0800254 CheckModernLegacyInfoMatch(fence);
Riley Andrews9e558792014-06-05 19:34:40 -0700255}
256
257TEST(AllocTest, FenceNegative) {
258 int timeline = sw_sync_timeline_create();
259 ASSERT_GT(timeline, 0);
260
261 // bad fd.
262 ASSERT_LT(sw_sync_fence_create(-1, "fence", 1), 0);
263
264 // No name - segfaults in user space.
265 // Maybe we should be friendlier here?
266 /*
267 ASSERT_LT(sw_sync_fence_create(timeline, nullptr, 1), 0);
268 */
269 close(timeline);
270}
271
272TEST(FenceTest, OneTimelineWait) {
273 SyncTimeline timeline;
274 ASSERT_TRUE(timeline.isValid());
275
276 SyncFence fence(timeline, 5);
277 ASSERT_TRUE(fence.isValid());
278
279 // Wait on fence until timeout.
280 ASSERT_EQ(fence.wait(0), -1);
281 ASSERT_EQ(errno, ETIME);
282
283 // Advance timeline from 0 -> 1
284 ASSERT_EQ(timeline.inc(1), 0);
285
286 // Wait on fence until timeout.
287 ASSERT_EQ(fence.wait(0), -1);
288 ASSERT_EQ(errno, ETIME);
289
290 // Signal the fence.
291 ASSERT_EQ(timeline.inc(4), 0);
292
293 // Wait successfully.
294 ASSERT_EQ(fence.wait(0), 0);
295
296 // Go even futher, and confirm wait still succeeds.
297 ASSERT_EQ(timeline.inc(10), 0);
298 ASSERT_EQ(fence.wait(0), 0);
299}
300
301TEST(FenceTest, OneTimelinePoll) {
302 SyncTimeline timeline;
303 ASSERT_TRUE(timeline.isValid());
304
305 SyncFence fence(timeline, 100);
306 ASSERT_TRUE(fence.isValid());
307
308 fd_set set;
309 FD_ZERO(&set);
310 FD_SET(fence.getFd(), &set);
311
312 // Poll the fence, and wait till timeout.
313 timeval time = {0};
314 ASSERT_EQ(select(fence.getFd() + 1, &set, nullptr, nullptr, &time), 0);
315
316 // Advance the timeline.
317 timeline.inc(100);
318 timeline.inc(100);
319
320 // Select should return that the fd is read for reading.
321 FD_ZERO(&set);
322 FD_SET(fence.getFd(), &set);
323
324 ASSERT_EQ(select(fence.getFd() + 1, &set, nullptr, nullptr, &time), 1);
325 ASSERT_TRUE(FD_ISSET(fence.getFd(), &set));
326}
327
328TEST(FenceTest, OneTimelineMerge) {
329 SyncTimeline timeline;
330 ASSERT_TRUE(timeline.isValid());
331
332 // create fence a,b,c and then merge them all into fence d.
333 SyncFence a(timeline, 1), b(timeline, 2), c(timeline, 3);
334 ASSERT_TRUE(a.isValid());
335 ASSERT_TRUE(b.isValid());
336 ASSERT_TRUE(c.isValid());
337
338 SyncFence d({a,b,c});
339 ASSERT_TRUE(d.isValid());
340
341 // confirm all fences have one active point (even d).
342 ASSERT_EQ(a.getActiveCount(), 1);
343 ASSERT_EQ(b.getActiveCount(), 1);
344 ASSERT_EQ(c.getActiveCount(), 1);
345 ASSERT_EQ(d.getActiveCount(), 1);
346
347 // confirm that d is not signaled until the max of a,b,c
348 timeline.inc(1);
349 ASSERT_EQ(a.getSignaledCount(), 1);
350 ASSERT_EQ(d.getActiveCount(), 1);
Jesse Hall83666162017-02-12 16:32:39 -0800351 CheckModernLegacyInfoMatch(a);
352 CheckModernLegacyInfoMatch(d);
Riley Andrews9e558792014-06-05 19:34:40 -0700353
354 timeline.inc(1);
355 ASSERT_EQ(b.getSignaledCount(), 1);
356 ASSERT_EQ(d.getActiveCount(), 1);
Jesse Hall83666162017-02-12 16:32:39 -0800357 CheckModernLegacyInfoMatch(b);
358 CheckModernLegacyInfoMatch(d);
Riley Andrews9e558792014-06-05 19:34:40 -0700359
360 timeline.inc(1);
361 ASSERT_EQ(c.getSignaledCount(), 1);
362 ASSERT_EQ(d.getActiveCount(), 0);
363 ASSERT_EQ(d.getSignaledCount(), 1);
Jesse Hall83666162017-02-12 16:32:39 -0800364 CheckModernLegacyInfoMatch(c);
365 CheckModernLegacyInfoMatch(d);
Riley Andrews9e558792014-06-05 19:34:40 -0700366}
367
368TEST(FenceTest, MergeSameFence) {
369 SyncTimeline timeline;
370 ASSERT_TRUE(timeline.isValid());
371
372 SyncFence fence(timeline, 5);
373 ASSERT_TRUE(fence.isValid());
374
375 SyncFence selfMergeFence(fence, fence);
376 ASSERT_TRUE(selfMergeFence.isValid());
377
378 ASSERT_EQ(selfMergeFence.getSignaledCount(), 0);
Jesse Hall83666162017-02-12 16:32:39 -0800379 CheckModernLegacyInfoMatch(selfMergeFence);
Riley Andrews9e558792014-06-05 19:34:40 -0700380
381 timeline.inc(5);
382 ASSERT_EQ(selfMergeFence.getSignaledCount(), 1);
Jesse Hall83666162017-02-12 16:32:39 -0800383 CheckModernLegacyInfoMatch(selfMergeFence);
Riley Andrews9e558792014-06-05 19:34:40 -0700384}
385
Riley Andrews9e558792014-06-05 19:34:40 -0700386TEST(FenceTest, PollOnDestroyedTimeline) {
387 SyncTimeline timeline;
388 ASSERT_TRUE(timeline.isValid());
389
390 SyncFence fenceSig(timeline, 100);
391 SyncFence fenceKill(timeline, 200);
392
393 // Spawn a thread to wait on a fence when the timeline is killed.
394 thread waitThread{
395 [&]() {
396 ASSERT_EQ(timeline.inc(100), 0);
397
398 // Wait on the fd.
399 struct pollfd fds;
400 fds.fd = fenceKill.getFd();
401 fds.events = POLLIN | POLLERR;
Gustavo Padovan801492b2016-12-06 16:13:17 -0200402 ASSERT_EQ(poll(&fds, 1, 0), 0);
Riley Andrews9e558792014-06-05 19:34:40 -0700403 }
404 };
405
406 // Wait for the thread to spool up.
407 fenceSig.wait();
408
409 // Kill the timeline.
410 timeline.destroy();
411
412 // wait for the thread to clean up.
413 waitThread.join();
414}
415
416TEST(FenceTest, MultiTimelineWait) {
417 SyncTimeline timelineA, timelineB, timelineC;
418
419 SyncFence fenceA(timelineA, 5);
420 SyncFence fenceB(timelineB, 5);
421 SyncFence fenceC(timelineC, 5);
422
423 // Make a larger fence using 3 other fences from different timelines.
424 SyncFence mergedFence({fenceA, fenceB, fenceC});
425 ASSERT_TRUE(mergedFence.isValid());
426
427 // Confirm fence isn't signaled
428 ASSERT_EQ(mergedFence.getActiveCount(), 3);
429 ASSERT_EQ(mergedFence.wait(0), -1);
430 ASSERT_EQ(errno, ETIME);
431
432 timelineA.inc(5);
433 ASSERT_EQ(mergedFence.getActiveCount(), 2);
434 ASSERT_EQ(mergedFence.getSignaledCount(), 1);
Jesse Hall83666162017-02-12 16:32:39 -0800435 CheckModernLegacyInfoMatch(mergedFence);
Riley Andrews9e558792014-06-05 19:34:40 -0700436
437 timelineB.inc(5);
438 ASSERT_EQ(mergedFence.getActiveCount(), 1);
439 ASSERT_EQ(mergedFence.getSignaledCount(), 2);
Jesse Hall83666162017-02-12 16:32:39 -0800440 CheckModernLegacyInfoMatch(mergedFence);
Riley Andrews9e558792014-06-05 19:34:40 -0700441
442 timelineC.inc(5);
443 ASSERT_EQ(mergedFence.getActiveCount(), 0);
444 ASSERT_EQ(mergedFence.getSignaledCount(), 3);
Jesse Hall83666162017-02-12 16:32:39 -0800445 CheckModernLegacyInfoMatch(mergedFence);
Riley Andrews9e558792014-06-05 19:34:40 -0700446
447 // confirm you can successfully wait.
448 ASSERT_EQ(mergedFence.wait(100), 0);
449}
450
Alexandros Frantzis68223502017-09-15 09:45:40 +0300451TEST(FenceTest, GetInfoActive) {
452 SyncTimeline timeline;
453 ASSERT_TRUE(timeline.isValid());
454
455 SyncFence fence(timeline, 1);
456 ASSERT_TRUE(fence.isValid());
457
458 vector<SyncPointInfo> info = fence.getInfo();
459 ASSERT_EQ(info.size(), 1);
460
461 ASSERT_FALSE(info[0].driverName.empty());
462 ASSERT_FALSE(info[0].objectName.empty());
463 ASSERT_EQ(info[0].timeStampNs, 0);
464 ASSERT_EQ(info[0].status, 0);
465}
466
467TEST(FenceTest, GetInfoSignaled) {
468 SyncTimeline timeline;
469 ASSERT_TRUE(timeline.isValid());
470
471 SyncFence fence(timeline, 1);
472 ASSERT_TRUE(fence.isValid());
473
474 ASSERT_EQ(timeline.inc(1), 0);
475 ASSERT_EQ(fence.wait(), 0);
476
477 vector<SyncPointInfo> info = fence.getInfo();
478 ASSERT_EQ(info.size(), 1);
479
480 ASSERT_FALSE(info[0].driverName.empty());
481 ASSERT_FALSE(info[0].objectName.empty());
482 ASSERT_GT(info[0].timeStampNs, 0);
483 ASSERT_EQ(info[0].status, 1);
484}
485
Riley Andrews9e558792014-06-05 19:34:40 -0700486TEST(StressTest, TwoThreadsSharedTimeline) {
487 const int iterations = 1 << 16;
488 int counter = 0;
489 SyncTimeline timeline;
490 ASSERT_TRUE(timeline.isValid());
491
492 // Use a single timeline to synchronize two threads
493 // hammmering on the same counter.
494 auto threadMain = [&](int threadId) {
495 for (int i = 0; i < iterations; i++) {
496 SyncFence fence(timeline, i * 2 + threadId);
497 ASSERT_TRUE(fence.isValid());
498
499 // Wait on the prior thread to complete.
500 ASSERT_EQ(fence.wait(), 0);
501
502 // Confirm the previous thread's writes are visible and then inc.
503 ASSERT_EQ(counter, i * 2 + threadId);
504 counter++;
505
506 // Kick off the other thread.
507 ASSERT_EQ(timeline.inc(), 0);
508 }
509 };
510
511 thread a{threadMain, 0};
512 thread b{threadMain, 1};
513 a.join();
514 b.join();
515
516 // make sure the threads did not trample on one another.
517 ASSERT_EQ(counter, iterations * 2);
518}
519
520class ConsumerStressTest : public ::testing::TestWithParam<int> {};
521
522TEST_P(ConsumerStressTest, MultiProducerSingleConsumer) {
523 mutex lock;
524 int counter = 0;
525 int iterations = 1 << 12;
526
527 vector<SyncTimeline> producerTimelines(GetParam());
528 vector<thread> threads;
529 SyncTimeline consumerTimeline;
530
531 // Producer threads run this lambda.
532 auto threadMain = [&](int threadId) {
533 for (int i = 0; i < iterations; i++) {
534 SyncFence fence(consumerTimeline, i);
535 ASSERT_TRUE(fence.isValid());
536
537 // Wait for the consumer to finish. Use alternate
538 // means of waiting on the fence.
539 if ((iterations + threadId) % 8 != 0) {
540 ASSERT_EQ(fence.wait(), 0);
541 }
542 else {
543 while (fence.getSignaledCount() != 1) {
544 ASSERT_EQ(fence.getErrorCount(), 0);
545 }
546 }
547
548 // Every producer increments the counter, the consumer checks + erases it.
549 lock.lock();
550 counter++;
551 lock.unlock();
552
553 ASSERT_EQ(producerTimelines[threadId].inc(), 0);
554 }
555 };
556
557 for (int i = 0; i < GetParam(); i++) {
558 threads.push_back(thread{threadMain, i});
559 }
560
561 // Consumer thread runs this loop.
562 for (int i = 1; i <= iterations; i++) {
563 // Create a fence representing all producers final timelines.
564 vector<SyncFence> fences;
565 for (auto& timeline : producerTimelines) {
566 fences.push_back(SyncFence(timeline, i));
567 }
568 SyncFence mergeFence(fences);
569 ASSERT_TRUE(mergeFence.isValid());
570
571 // Make sure we see an increment from every producer thread. Vary
572 // the means by which we wait.
573 if (iterations % 8 != 0) {
574 ASSERT_EQ(mergeFence.wait(), 0);
575 }
576 else {
577 while (mergeFence.getSignaledCount() != mergeFence.getSize()) {
578 ASSERT_EQ(mergeFence.getErrorCount(), 0);
579 }
580 }
581 ASSERT_EQ(counter, GetParam()*i);
582
583 // Release the producer threads.
584 ASSERT_EQ(consumerTimeline.inc(), 0);
585 }
586
587 for_each(begin(threads), end(threads), [](thread& thread) { thread.join(); });
588}
589INSTANTIATE_TEST_CASE_P(
590 ParameterizedStressTest,
591 ConsumerStressTest,
592 ::testing::Values(2,4,16));
593
594class MergeStressTest : public ::testing::TestWithParam<tuple<int, int>> {};
595
596template <typename K, typename V> using dict = unordered_map<K,V>;
597
598TEST_P(MergeStressTest, RandomMerge) {
599 int timelineCount = get<0>(GetParam());
600 int mergeCount = get<1>(GetParam());
601
602 vector<SyncTimeline> timelines(timelineCount);
603
604 default_random_engine generator;
605 uniform_int_distribution<int> timelineDist(0, timelines.size()-1);
606 uniform_int_distribution<int> syncPointDist(0, numeric_limits<int>::max());
607
608 SyncFence fence(timelines[0], 0);
609 ASSERT_TRUE(fence.isValid());
610
611 unordered_map<int, int> fenceMap;
mtezych380b2f42017-01-29 19:45:57 +0100612 fenceMap.insert(make_pair(0, 0));
Riley Andrews9e558792014-06-05 19:34:40 -0700613
614 // Randomly create syncpoints out of a fixed set of timelines, and merge them together.
615 for (int i = 0; i < mergeCount; i++) {
616
617 // Generate syncpoint.
618 int timelineOffset = timelineDist(generator);
619 const SyncTimeline& timeline = timelines[timelineOffset];
620 int syncPoint = syncPointDist(generator);
621
622 // Keep track of the latest syncpoint in each timeline.
623 auto itr = fenceMap.find(timelineOffset);
624 if (itr == end(fenceMap)) {
mtezych380b2f42017-01-29 19:45:57 +0100625 fenceMap.insert(make_pair(timelineOffset, syncPoint));
Riley Andrews9e558792014-06-05 19:34:40 -0700626 }
627 else {
628 int oldSyncPoint = itr->second;
629 fenceMap.erase(itr);
mtezych380b2f42017-01-29 19:45:57 +0100630 fenceMap.insert(make_pair(timelineOffset, max(syncPoint, oldSyncPoint)));
Riley Andrews9e558792014-06-05 19:34:40 -0700631 }
632
633 // Merge.
634 fence = SyncFence(fence, SyncFence(timeline, syncPoint));
635 ASSERT_TRUE(fence.isValid());
Jesse Hall83666162017-02-12 16:32:39 -0800636 CheckModernLegacyInfoMatch(fence);
Riley Andrews9e558792014-06-05 19:34:40 -0700637 }
638
639 // Confirm our map matches the fence.
640 ASSERT_EQ(fence.getSize(), fenceMap.size());
641
642 // Trigger the merged fence.
643 for (auto& item: fenceMap) {
644 ASSERT_EQ(fence.wait(0), -1);
645 ASSERT_EQ(errno, ETIME);
646
647 // Increment the timeline to the last syncpoint.
648 timelines[item.first].inc(item.second);
649 }
650
651 // Check that the fence is triggered.
652 ASSERT_EQ(fence.wait(0), 0);
653}
654
655INSTANTIATE_TEST_CASE_P(
656 ParameterizedMergeStressTest,
657 MergeStressTest,
658 ::testing::Combine(::testing::Values(16,32), ::testing::Values(32, 1024, 1024*32)));
659
660}
661