1 /* 2 * sync stress test: parallelism 3 * Copyright 2015-2016 Collabora Ltd. 4 * 5 * Based on the implementation from the Android Open Source Project, 6 * 7 * Copyright 2012 Google, Inc 8 * 9 * Permission is hereby granted, free of charge, to any person obtaining a 10 * copy of this software and associated documentation files (the "Software"), 11 * to deal in the Software without restriction, including without limitation 12 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 13 * and/or sell copies of the Software, and to permit persons to whom the 14 * Software is furnished to do so, subject to the following conditions: 15 * 16 * The above copyright notice and this permission notice shall be included in 17 * all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 22 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 23 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 24 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 25 * OTHER DEALINGS IN THE SOFTWARE. 26 */ 27 28 #include <pthread.h> 29 30 #include "sync.h" 31 #include "sw_sync.h" 32 #include "synctest.h" 33 34 static struct { 35 int iterations; 36 int timeline; 37 int counter; 38 } test_data_two_threads; 39 40 static int test_stress_two_threads_shared_timeline_thread(void *d) 41 { 42 int thread_id = (long)d; 43 int timeline = test_data_two_threads.timeline; 44 int iterations = test_data_two_threads.iterations; 45 int fence, valid, ret, i; 46 47 for (i = 0; i < iterations; i++) { 48 fence = sw_sync_fence_create(timeline, "fence", 49 i * 2 + thread_id); 50 valid = sw_sync_fence_is_valid(fence); 51 ASSERT(valid, "Failure allocating fence\n"); 52 53 /* Wait on the prior thread to complete */ 54 ret = sync_wait(fence, -1); 55 ASSERT(ret > 0, "Problem occurred on prior thread\n"); 56 57 /* 58 * Confirm the previous thread's writes are visible 59 * and then increment 60 */ 61 ASSERT(test_data_two_threads.counter == i * 2 + thread_id, 62 "Counter got damaged!\n"); 63 test_data_two_threads.counter++; 64 65 /* Kick off the other thread */ 66 ret = sw_sync_timeline_inc(timeline, 1); 67 ASSERT(ret == 0, "Advancing timeline failed\n"); 68 69 sw_sync_fence_destroy(fence); 70 } 71 72 return 0; 73 } 74 75 int test_stress_two_threads_shared_timeline(void) 76 { 77 pthread_t a, b; 78 int valid; 79 int timeline = sw_sync_timeline_create(); 80 81 valid = sw_sync_timeline_is_valid(timeline); 82 ASSERT(valid, "Failure allocating timeline\n"); 83 84 test_data_two_threads.iterations = 1 << 16; 85 test_data_two_threads.counter = 0; 86 test_data_two_threads.timeline = timeline; 87 88 /* 89 * Use a single timeline to synchronize two threads 90 * hammmering on the same counter. 91 */ 92 93 pthread_create(&a, NULL, (void *(*)(void *)) 94 test_stress_two_threads_shared_timeline_thread, 95 (void *)0); 96 pthread_create(&b, NULL, (void *(*)(void *)) 97 test_stress_two_threads_shared_timeline_thread, 98 (void *)1); 99 100 pthread_join(a, NULL); 101 pthread_join(b, NULL); 102 103 /* make sure the threads did not trample on one another */ 104 ASSERT(test_data_two_threads.counter == 105 test_data_two_threads.iterations * 2, 106 "Counter has unexpected value\n"); 107 108 sw_sync_timeline_destroy(timeline); 109 110 return 0; 111 } 112