| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2010 The Native Client Authors. All rights reserved. | 2 * Copyright 2010 The Native Client Authors. All rights reserved. |
| 3 * Use of this source code is governed by a BSD-style license that can | 3 * Use of this source code is governed by a BSD-style license that can |
| 4 * be found in the LICENSE file. | 4 * be found in the LICENSE file. |
| 5 */ | 5 */ |
| 6 | 6 |
| 7 #include <semaphore.h> | 7 #include <semaphore.h> |
| 8 | 8 |
| 9 #include <errno.h> | 9 #include <errno.h> |
| 10 #include <limits.h> | 10 #include <limits.h> |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 47 // sem_init should return -1 and errno should equal EINVAL | 47 // sem_init should return -1 and errno should equal EINVAL |
| 48 EXPECT(-1 == sem_init(&my_semaphore, 0, sem_max_plus_1)); | 48 EXPECT(-1 == sem_init(&my_semaphore, 0, sem_max_plus_1)); |
| 49 EXPECT(EINVAL == errno); | 49 EXPECT(EINVAL == errno); |
| 50 | 50 |
| 51 // Try with the largest possible unsigned int. | 51 // Try with the largest possible unsigned int. |
| 52 EXPECT(-1 == sem_init(&my_semaphore, | 52 EXPECT(-1 == sem_init(&my_semaphore, |
| 53 0, | 53 0, |
| 54 std::numeric_limits<unsigned int>::max())); | 54 std::numeric_limits<unsigned int>::max())); |
| 55 EXPECT(EINVAL == errno); | 55 EXPECT(EINVAL == errno); |
| 56 | 56 |
| 57 // NaCl semaphores do not currently support the pshared option, so this should | 57 #if !defined(__GLIBC__) |
| 58 // fail with an ENOSYS error. If pshared gets added, we should begin testing | 58 // nacl-newlib's semaphores do not currently support the pshared |
| 59 // it for proper successful behavior. | 59 // option, so this should fail with an ENOSYS error. If pshared |
| 60 // gets added, we should begin testing it for proper successful |
| 61 // behavior. |
| 60 EXPECT(-1 == sem_init(&my_semaphore, 1, 0)); | 62 EXPECT(-1 == sem_init(&my_semaphore, 1, 0)); |
| 61 EXPECT(ENOSYS == errno); | 63 EXPECT(ENOSYS == errno); |
| 64 #endif |
| 62 | 65 |
| 63 END_TEST(); | 66 END_TEST(); |
| 64 } | 67 } |
| 65 | |
| 66 // Test simple usages of sem_destroy and return the number of failed checks. | |
| 67 // | |
| 68 // According to the man page on Linux: | |
| 69 // =================================== | |
| 70 // RETURN VALUE | |
| 71 // | |
| 72 // sem_destroy() returns 0 on success; on error, -1 is returned, and | |
| 73 // errno is set to indicate the error. | |
| 74 // ERRORS | |
| 75 // | |
| 76 // EINVAL sem is not a valid semaphore. | |
| 77 // =================================== | |
| 78 int TestSemDestroy() { | |
| 79 START_TEST("sem_destroy"); | |
| 80 | |
| 81 // Try sem_destroy with a null pointer. | |
| 82 EXPECT(-1 == sem_destroy(NULL)); | |
| 83 EXPECT(EINVAL == errno); | |
| 84 | |
| 85 END_TEST(); | |
| 86 } | |
| 87 | 68 |
| 88 // Test error conditions of sem_post and return the number of failed checks. | 69 // Test error conditions of sem_post and return the number of failed checks. |
| 89 // | 70 // |
| 90 // According to the man page on Linux: | 71 // According to the man page on Linux: |
| 91 // =================================== | 72 // =================================== |
| 92 // RETURN VALUE | 73 // RETURN VALUE |
| 93 // sem_post() returns 0 on success; on error, the value of the semaphore | 74 // sem_post() returns 0 on success; on error, the value of the semaphore |
| 94 // is left unchanged, -1 is returned, and errno is set to indicate the | 75 // is left unchanged, -1 is returned, and errno is set to indicate the |
| 95 // error. | 76 // error. |
| 96 // | 77 // |
| 97 // ERRORS | 78 // ERRORS |
| 98 // EINVAL sem is not a valid semaphore. | 79 // EINVAL sem is not a valid semaphore. |
| 99 // | 80 // |
| 100 // EOVERFLOW | 81 // EOVERFLOW |
| 101 // The maximum allowable value for a semaphore would be exceeded. | 82 // The maximum allowable value for a semaphore would be exceeded. |
| 102 // =================================== | 83 // =================================== |
| 103 int TestSemPostErrors() { | 84 int TestSemPostErrors() { |
| 104 START_TEST("sem_post error conditions"); | 85 START_TEST("sem_post error conditions"); |
| 105 | 86 |
| 106 // Test an invalid semaphore: try a null pointer. | |
| 107 EXPECT(-1 == sem_post(NULL)); | |
| 108 EXPECT(EINVAL == errno); | |
| 109 | |
| 110 // Initialize a semaphore with the max value, and try to post to it. | 87 // Initialize a semaphore with the max value, and try to post to it. |
| 111 sem_t my_semaphore; | 88 sem_t my_semaphore; |
| 112 EXPECT(0 == sem_init(&my_semaphore, 0, SEM_VALUE_MAX)); | 89 EXPECT(0 == sem_init(&my_semaphore, 0, SEM_VALUE_MAX)); |
| 113 EXPECT(-1 == sem_post(&my_semaphore)); | 90 EXPECT(-1 == sem_post(&my_semaphore)); |
| 114 EXPECT(EOVERFLOW == errno); | 91 EXPECT(EOVERFLOW == errno); |
| 115 EXPECT(0 == sem_destroy(&my_semaphore)); | 92 EXPECT(0 == sem_destroy(&my_semaphore)); |
| 116 | 93 |
| 117 END_TEST(); | 94 END_TEST(); |
| 118 } | 95 } |
| 119 | 96 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 132 // post. poster_thread_arg must be of type PosterThreadArg. Returns NULL. | 109 // post. poster_thread_arg must be of type PosterThreadArg. Returns NULL. |
| 133 void* PostThreadFunc(void* poster_thread_arg) { | 110 void* PostThreadFunc(void* poster_thread_arg) { |
| 134 PostThreadArg* pta = static_cast<PostThreadArg*>(poster_thread_arg); | 111 PostThreadArg* pta = static_cast<PostThreadArg*>(poster_thread_arg); |
| 135 for (unsigned int i = 0; i < pta->iterations; ++i) { | 112 for (unsigned int i = 0; i < pta->iterations; ++i) { |
| 136 usleep(pta->sleep_microseconds); | 113 usleep(pta->sleep_microseconds); |
| 137 sem_post(pta->semaphore); | 114 sem_post(pta->semaphore); |
| 138 } | 115 } |
| 139 return NULL; | 116 return NULL; |
| 140 } | 117 } |
| 141 | 118 |
| 142 // TODO(dmichael): Add this code and appropriate tests back if/when signal | |
| 143 // support is added. | |
| 144 // The following is intended to be used to test that calls which may be | |
| 145 // interrupted by a signal (e.g., sem_wait) will stop and report failure | |
| 146 // properly. However, NaCl does not currently support signals. | |
| 147 // | |
| 148 // The real type of the void* argument to SignalThreadFunc. See | |
| 149 // SignalThreadFunc for more information. | |
| 150 // struct SignalThreadArg { | |
| 151 // // The signal to send. | |
| 152 // int signal; | |
| 153 // // The amount of time to sleep before sending the signal (in microseconds). | |
| 154 // unsigned int sleep_microseconds; | |
| 155 // }; | |
| 156 // | |
| 157 // Sleep for sleep_microseconds, then raise the given signal. signal_thread_arg | |
| 158 // must be of type SignalThreadArg. Returns NULL. | |
| 159 // void* SignalThreadFunc(void* signal_thread_arg) { | |
| 160 // SignalThreadArg* sta = static_cast<SignalThreadArg*>(signal_thread_arg); | |
| 161 // usleep(sta->sleep_microseconds); | |
| 162 // raise(sta->signal); // This currently results in link error; signals | |
| 163 // // are currently unsupported by NaCl. | |
| 164 // return NULL; | |
| 165 // } | |
| 166 | |
| 167 // Test error conditions of sem_wait and return the number of failed checks. | |
| 168 // | |
| 169 // According to the man page on Linux: | |
| 170 // =================================== | |
| 171 // RETURN VALUE | |
| 172 // All of these functions return 0 on success; on error, the value of the | |
| 173 // semaphore is left unchanged, -1 is returned, and errno is set to indi‐ | |
| 174 // cate the error. | |
| 175 // | |
| 176 // ERRORS | |
| 177 // EINTR The call was interrupted by a signal handler; see signal(7). | |
| 178 // | |
| 179 // EINVAL sem is not a valid semaphore. | |
| 180 // =================================== | |
| 181 int TestSemWaitErrors() { | |
| 182 START_TEST("sem_wait error conditions"); | |
| 183 | |
| 184 // Try a null pointer. | |
| 185 EXPECT(-1 == sem_wait(NULL)); | |
| 186 EXPECT(EINVAL == errno); | |
| 187 | |
| 188 // TODO(dmichael): Uncomment this test (and supporting code above) if/when | |
| 189 // NaCl support for signals is added. | |
| 190 // Now really initialize one with the a value of 1, wait on it until a signal. | |
| 191 // EXPECT(0 == sem_init(&my_semaphore[1], 0, SEM_VALUE_MAX)); | |
| 192 // // Spawn a thread to signal us so we'll get an EINTR error. | |
| 193 // SignalThreadArg sta = { SIGINT, /* signal */ | |
| 194 // 2000000u /* sleep_microseconds */ }; | |
| 195 | |
| 196 // pthread_t sig_thread; | |
| 197 // | |
| 198 // EXPECT(0 == pthread_create(&sig_thread, 0, &SignalThreadFunc, &sta)); | |
| 199 // EXPECT(-1 == sem_wait(&my_semaphore[1])); | |
| 200 // EXPECT(EINTR == errno); | |
| 201 // void* dummy_return; | |
| 202 // EXPECT(0 == pthread_join(sig_thread, &dummy_return)); | |
| 203 | |
| 204 END_TEST(); | |
| 205 } | |
| 206 | |
| 207 int TestSemNormalOperation() { | 119 int TestSemNormalOperation() { |
| 208 START_TEST("semaphore normal operation"); | 120 START_TEST("semaphore normal operation"); |
| 209 | 121 |
| 210 // Test 1 thread posting to 1 semaphore. | 122 // Test 1 thread posting to 1 semaphore. |
| 211 sem_t my_semaphore; | 123 sem_t my_semaphore; |
| 212 EXPECT(0 == sem_init(&my_semaphore, 0, 0)); | 124 EXPECT(0 == sem_init(&my_semaphore, 0, 0)); |
| 213 PostThreadArg pta = { &my_semaphore, /* semaphore */ | 125 PostThreadArg pta = { &my_semaphore, /* semaphore */ |
| 214 500000u, /* sleep_microseconds */ | 126 500000u, /* sleep_microseconds */ |
| 215 1 /* iterations */ }; | 127 1 /* iterations */ }; |
| 216 pthread_t my_thread; | 128 pthread_t my_thread; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 246 EXPECT(0 == sem_wait(&my_semaphore)); | 158 EXPECT(0 == sem_wait(&my_semaphore)); |
| 247 } | 159 } |
| 248 EXPECT(0 == pthread_join(my_thread, 0)); | 160 EXPECT(0 == pthread_join(my_thread, 0)); |
| 249 EXPECT(0 == sem_destroy(&my_semaphore)); | 161 EXPECT(0 == sem_destroy(&my_semaphore)); |
| 250 | 162 |
| 251 END_TEST(); | 163 END_TEST(); |
| 252 } | 164 } |
| 253 | 165 |
| 254 int main() { | 166 int main() { |
| 255 int fail_count = 0; | 167 int fail_count = 0; |
| 168 fail_count += TestSemInitErrors(); |
| 169 fail_count += TestSemPostErrors(); |
| 256 fail_count += TestSemNormalOperation(); | 170 fail_count += TestSemNormalOperation(); |
| 257 | |
| 258 // A semaphore implementation is not required to check for the | |
| 259 // errors that are tested for here. nacl-newlib checks, but glibc | |
| 260 // does not. | |
| 261 #ifndef __GLIBC__ | |
| 262 fail_count += TestSemInitErrors(); | |
| 263 fail_count += TestSemDestroy(); | |
| 264 fail_count += TestSemPostErrors(); | |
| 265 fail_count += TestSemWaitErrors(); | |
| 266 #endif | |
| 267 | |
| 268 std::exit(fail_count); | 171 std::exit(fail_count); |
| 269 } | 172 } |
| OLD | NEW |