| OLD | NEW |
| 1 /* Copyright (c) 2011 The Native Client Authors. All rights reserved. | 1 /* Copyright (c) 2011 The Native Client Authors. All rights reserved. |
| 2 * Use of this source code is governed by a BSD-style license that can be | 2 * Use of this source code is governed by a BSD-style license that can be |
| 3 * found in the LICENSE file. | 3 * found in the LICENSE file. |
| 4 */ | 4 */ |
| 5 | 5 |
| 6 #include <stdio.h> | 6 #include <stdio.h> |
| 7 #include "native_client/src/include/atomic_ops.h" | 7 #include "native_client/src/include/atomic_ops.h" |
| 8 #include "native_client/src/shared/platform/nacl_threads.h" | 8 #include "native_client/src/shared/platform/nacl_threads.h" |
| 9 #include "native_client/src/shared/platform/nacl_sync_checked.h" | 9 #include "native_client/src/shared/platform/nacl_sync_checked.h" |
| 10 #include "native_client/src/shared/platform/nacl_sync.h" | 10 #include "native_client/src/shared/platform/nacl_sync.h" |
| 11 | 11 |
| 12 #define THREAD_STACK_SIZE (128*1024) | 12 #define THREAD_STACK_SIZE (128*1024) |
| 13 | 13 |
| 14 int32_t gIncrementsPerThread = 1000; | 14 int32_t gIncrementsPerThread = 1000; |
| 15 int32_t gNumThreads; | 15 int32_t gNumThreads; |
| 16 | 16 |
| 17 struct NaClMutex gMutex; | 17 struct NaClMutex gMutex; |
| 18 struct NaClCondVar gFinishedCv; | |
| 19 int32_t gFinishedCount = 0; | |
| 20 | 18 |
| 21 | 19 |
| 22 /* For atomic counter test */ | 20 /* For atomic counter test */ |
| 23 Atomic32 gCounter = 0; | 21 Atomic32 gCounter = 0; |
| 24 | 22 |
| 25 static void IncrementTest() { | 23 static void IncrementTest() { |
| 26 /* Increment the counter, gIncrementsPerThread times, | 24 /* Increment the counter, gIncrementsPerThread times, |
| 27 * with the values 1...gIncrementsPerThread | 25 * with the values 1...gIncrementsPerThread |
| 28 */ | 26 */ |
| 29 Atomic32 i; | 27 Atomic32 i; |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 83 IncrementTest(); | 81 IncrementTest(); |
| 84 DecrementTest(); | 82 DecrementTest(); |
| 85 } else { | 83 } else { |
| 86 DecrementTest(); | 84 DecrementTest(); |
| 87 IncrementTest(); | 85 IncrementTest(); |
| 88 } | 86 } |
| 89 | 87 |
| 90 ExchangeTest(tid); | 88 ExchangeTest(tid); |
| 91 | 89 |
| 92 CompareAndSwapTest(tid); | 90 CompareAndSwapTest(tid); |
| 93 | |
| 94 /* Signal that we're finished */ | |
| 95 NaClXMutexLock(&gMutex); | |
| 96 gFinishedCount++; | |
| 97 NaClXCondVarSignal(&gFinishedCv); | |
| 98 NaClXMutexUnlock(&gMutex); | |
| 99 | |
| 100 NaClThreadExit(0); | |
| 101 } | 91 } |
| 102 | 92 |
| 103 int main(int argc, const char *argv[]) { | 93 int main(int argc, const char *argv[]) { |
| 104 struct NaClThread *threads; | 94 struct NaClThread *threads; |
| 105 int rv; | 95 int rv; |
| 106 int32_t tid; | 96 int32_t tid; |
| 107 int32_t tmp; | 97 int32_t tmp; |
| 108 | 98 |
| 109 if (argc != 2) { | 99 if (argc != 2) { |
| 110 fprintf(stderr, "Usage: %s <NumThreads>\n", argv[0]); | 100 fprintf(stderr, "Usage: %s <NumThreads>\n", argv[0]); |
| 111 exit(EXIT_FAILURE); | 101 exit(EXIT_FAILURE); |
| 112 } | 102 } |
| 113 | 103 |
| 114 gNumThreads = strtol(argv[1], NULL, 10); | 104 gNumThreads = strtol(argv[1], NULL, 10); |
| 115 | 105 |
| 116 threads = (struct NaClThread*)malloc(gNumThreads*sizeof(struct NaClThread)); | 106 threads = (struct NaClThread*)malloc(gNumThreads*sizeof(struct NaClThread)); |
| 117 if (threads == NULL) { | 107 if (threads == NULL) { |
| 118 fprintf(stderr, "malloc returned NULL\n"); | 108 fprintf(stderr, "malloc returned NULL\n"); |
| 119 exit(EXIT_FAILURE); | 109 exit(EXIT_FAILURE); |
| 120 } | 110 } |
| 121 | 111 |
| 122 if (!NaClMutexCtor(&gMutex)) { | 112 if (!NaClMutexCtor(&gMutex)) { |
| 123 fprintf(stderr, "NaClMutexCtor failed\n"); | 113 fprintf(stderr, "NaClMutexCtor failed\n"); |
| 124 exit(EXIT_FAILURE); | 114 exit(EXIT_FAILURE); |
| 125 } | 115 } |
| 126 | 116 |
| 127 if (!NaClCondVarCtor(&gFinishedCv)) { | |
| 128 fprintf(stderr, "NaClCondVarCtor failed\n"); | |
| 129 exit(EXIT_FAILURE); | |
| 130 } | |
| 131 NaClXMutexLock(&gMutex); | 117 NaClXMutexLock(&gMutex); |
| 132 | 118 |
| 133 for (tid = 1; tid <= gNumThreads; ++tid) { | 119 for (tid = 1; tid <= gNumThreads; ++tid) { |
| 134 fprintf(stderr, "Creating thread %d\n", (int)tid); | 120 fprintf(stderr, "Creating thread %d\n", (int)tid); |
| 135 | 121 |
| 136 rv = NaClThreadCtor(&threads[tid-1], | 122 rv = NaClThreadCreateJoinable(&threads[tid-1], |
| 137 ThreadMain, | 123 ThreadMain, |
| 138 (void*) (intptr_t) tid, | 124 (void*) (intptr_t) tid, |
| 139 THREAD_STACK_SIZE); | 125 THREAD_STACK_SIZE); |
| 140 if (!rv) { | 126 if (!rv) { |
| 141 fprintf(stderr, "NaClThreadCtor failed\n"); | 127 fprintf(stderr, "NaClThreadCtor failed\n"); |
| 142 exit(EXIT_FAILURE); | 128 exit(EXIT_FAILURE); |
| 143 } | 129 } |
| 144 } | 130 } |
| 145 | 131 |
| 146 while (gFinishedCount != gNumThreads) { | 132 NaClXMutexUnlock(&gMutex); |
| 147 /* This releases the mutex, so the tests begin */ | 133 |
| 148 NaClXCondVarWait(&gFinishedCv, &gMutex); | 134 for (tid = 1; tid <= gNumThreads; ++tid) { |
| 135 NaClThreadJoin(&threads[tid-1]); |
| 149 } | 136 } |
| 150 NaClXMutexUnlock(&gMutex); | |
| 151 | 137 |
| 152 /* Check the results */ | 138 /* Check the results */ |
| 153 tmp = gIncrementsPerThread * gNumThreads; | 139 tmp = gIncrementsPerThread * gNumThreads; |
| 154 if (gCounter != tmp) { | 140 if (gCounter != tmp) { |
| 155 fprintf(stderr, "ERROR: gCounter is wrong. Expected %d, got %d\n", | 141 fprintf(stderr, "ERROR: gCounter is wrong. Expected %d, got %d\n", |
| 156 (int)tmp, (int)gCounter); | 142 (int)tmp, (int)gCounter); |
| 157 exit(EXIT_FAILURE); | 143 exit(EXIT_FAILURE); |
| 158 } | 144 } |
| 159 | 145 |
| 160 tmp = gNumThreads*(gNumThreads+1)/2; | 146 tmp = gNumThreads*(gNumThreads+1)/2; |
| 161 if (gExchange + gExchangeSum != tmp) { | 147 if (gExchange + gExchangeSum != tmp) { |
| 162 fprintf(stderr, | 148 fprintf(stderr, |
| 163 "ERROR: gExchange+gExchangeSum is wrong. Expected %d, got %d\n", | 149 "ERROR: gExchange+gExchangeSum is wrong. Expected %d, got %d\n", |
| 164 (int)tmp, (int)(gExchange + gExchangeSum)); | 150 (int)tmp, (int)(gExchange + gExchangeSum)); |
| 165 exit(EXIT_FAILURE); | 151 exit(EXIT_FAILURE); |
| 166 } | 152 } |
| 167 | 153 |
| 168 if (gSwap != gNumThreads+1) { | 154 if (gSwap != gNumThreads+1) { |
| 169 fprintf(stderr, "ERROR: gSwap is wrong. Expected %d, got %d\n", | 155 fprintf(stderr, "ERROR: gSwap is wrong. Expected %d, got %d\n", |
| 170 (int)(gNumThreads+1), (int)gSwap); | 156 (int)(gNumThreads+1), (int)gSwap); |
| 171 exit(EXIT_FAILURE); | 157 exit(EXIT_FAILURE); |
| 172 } | 158 } |
| 173 | 159 |
| 174 fprintf(stderr, "PASSED\n"); | 160 fprintf(stderr, "PASSED\n"); |
| 175 NaClCondVarDtor(&gFinishedCv); | |
| 176 NaClMutexDtor(&gMutex); | 161 NaClMutexDtor(&gMutex); |
| 177 free(threads); | 162 free(threads); |
| 178 return 0; | 163 return 0; |
| 179 } | 164 } |
| OLD | NEW |