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 |