0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028 #include <pthread.h>
0029
0030 #include "sync.h"
0031 #include "sw_sync.h"
0032 #include "synctest.h"
0033
0034
0035
0036
0037
0038
0039
0040 static int busy_wait_on_fence(int fence)
0041 {
0042 int error, active;
0043
0044 do {
0045 error = sync_fence_count_with_status(fence, FENCE_STATUS_ERROR);
0046 ASSERT(error == 0, "Error occurred on fence\n");
0047 active = sync_fence_count_with_status(fence,
0048 FENCE_STATUS_ACTIVE);
0049 } while (active);
0050
0051 return 0;
0052 }
0053
0054 static struct {
0055 int iterations;
0056 int threads;
0057 int counter;
0058 int consumer_timeline;
0059 int *producer_timelines;
0060 pthread_mutex_t lock;
0061 } test_data_mpsc;
0062
0063 static int mpsc_producer_thread(void *d)
0064 {
0065 int id = (long)d;
0066 int fence, valid, i;
0067 int *producer_timelines = test_data_mpsc.producer_timelines;
0068 int consumer_timeline = test_data_mpsc.consumer_timeline;
0069 int iterations = test_data_mpsc.iterations;
0070
0071 for (i = 0; i < iterations; i++) {
0072 fence = sw_sync_fence_create(consumer_timeline, "fence", i);
0073 valid = sw_sync_fence_is_valid(fence);
0074 ASSERT(valid, "Failure creating fence\n");
0075
0076
0077
0078
0079
0080
0081 if ((iterations + id) % 8 != 0) {
0082 ASSERT(sync_wait(fence, -1) > 0,
0083 "Failure waiting on fence\n");
0084 } else {
0085 ASSERT(busy_wait_on_fence(fence) == 0,
0086 "Failure waiting on fence\n");
0087 }
0088
0089
0090
0091
0092
0093 pthread_mutex_lock(&test_data_mpsc.lock);
0094 test_data_mpsc.counter++;
0095 pthread_mutex_unlock(&test_data_mpsc.lock);
0096
0097 ASSERT(sw_sync_timeline_inc(producer_timelines[id], 1) == 0,
0098 "Error advancing producer timeline\n");
0099
0100 sw_sync_fence_destroy(fence);
0101 }
0102
0103 return 0;
0104 }
0105
0106 static int mpcs_consumer_thread(void)
0107 {
0108 int fence, merged, tmp, valid, it, i;
0109 int *producer_timelines = test_data_mpsc.producer_timelines;
0110 int consumer_timeline = test_data_mpsc.consumer_timeline;
0111 int iterations = test_data_mpsc.iterations;
0112 int n = test_data_mpsc.threads;
0113
0114 for (it = 1; it <= iterations; it++) {
0115 fence = sw_sync_fence_create(producer_timelines[0], "name", it);
0116 for (i = 1; i < n; i++) {
0117 tmp = sw_sync_fence_create(producer_timelines[i],
0118 "name", it);
0119 merged = sync_merge("name", tmp, fence);
0120 sw_sync_fence_destroy(tmp);
0121 sw_sync_fence_destroy(fence);
0122 fence = merged;
0123 }
0124
0125 valid = sw_sync_fence_is_valid(fence);
0126 ASSERT(valid, "Failure merging fences\n");
0127
0128
0129
0130
0131
0132 if (iterations % 8 != 0) {
0133 ASSERT(sync_wait(fence, -1) > 0,
0134 "Producers did not increment as expected\n");
0135 } else {
0136 ASSERT(busy_wait_on_fence(fence) == 0,
0137 "Producers did not increment as expected\n");
0138 }
0139
0140 ASSERT(test_data_mpsc.counter == n * it,
0141 "Counter value mismatch!\n");
0142
0143
0144 ASSERT(sw_sync_timeline_inc(consumer_timeline, 1) == 0,
0145 "Failure releasing producer threads\n");
0146
0147 sw_sync_fence_destroy(fence);
0148 }
0149
0150 return 0;
0151 }
0152
0153 int test_consumer_stress_multi_producer_single_consumer(void)
0154 {
0155 int iterations = 1 << 12;
0156 int n = 5;
0157 long i, ret;
0158 int producer_timelines[n];
0159 int consumer_timeline;
0160 pthread_t threads[n];
0161
0162 consumer_timeline = sw_sync_timeline_create();
0163 for (i = 0; i < n; i++)
0164 producer_timelines[i] = sw_sync_timeline_create();
0165
0166 test_data_mpsc.producer_timelines = producer_timelines;
0167 test_data_mpsc.consumer_timeline = consumer_timeline;
0168 test_data_mpsc.iterations = iterations;
0169 test_data_mpsc.threads = n;
0170 test_data_mpsc.counter = 0;
0171 pthread_mutex_init(&test_data_mpsc.lock, NULL);
0172
0173 for (i = 0; i < n; i++) {
0174 pthread_create(&threads[i], NULL, (void * (*)(void *))
0175 mpsc_producer_thread, (void *)i);
0176 }
0177
0178
0179 ret = mpcs_consumer_thread();
0180
0181 for (i = 0; i < n; i++)
0182 pthread_join(threads[i], NULL);
0183
0184 return ret;
0185 }