1 1.11 christos /* $NetBSD: sem.c,v 1.11 2017/01/13 21:30:42 christos Exp $ */ 2 1.1 pooka 3 1.1 pooka /* 4 1.1 pooka * Common code for semaphore tests. This can be included both into 5 1.1 pooka * programs using librt and libpthread. 6 1.1 pooka */ 7 1.1 pooka 8 1.1 pooka #include <sys/types.h> 9 1.1 pooka 10 1.1 pooka #include <rump/rump.h> 11 1.1 pooka #include <rump/rump_syscalls.h> 12 1.1 pooka 13 1.1 pooka #include <atf-c.h> 14 1.1 pooka #include <errno.h> 15 1.1 pooka #include <fcntl.h> 16 1.1 pooka #include <pthread.h> 17 1.1 pooka #include <semaphore.h> 18 1.1 pooka #include <sched.h> 19 1.1 pooka #include <stdint.h> 20 1.1 pooka #include <stdio.h> 21 1.1 pooka #include <stdlib.h> 22 1.1 pooka #include <unistd.h> 23 1.1 pooka 24 1.11 christos #include "h_macros.h" 25 1.1 pooka 26 1.1 pooka ATF_TC(postwait); 27 1.1 pooka ATF_TC_HEAD(postwait, tc) 28 1.1 pooka { 29 1.1 pooka 30 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests post and wait from a " 31 1.1 pooka "single thread (%s)", LIBNAME); 32 1.1 pooka } 33 1.1 pooka 34 1.1 pooka ATF_TC_BODY(postwait, tc) 35 1.1 pooka { 36 1.1 pooka sem_t sem; 37 1.1 pooka int rv; 38 1.1 pooka 39 1.1 pooka rump_init(); 40 1.1 pooka 41 1.1 pooka ATF_REQUIRE_EQ(sem_init(&sem, 1, 0), 0); 42 1.1 pooka 43 1.1 pooka sem_post(&sem); 44 1.1 pooka sem_post(&sem); 45 1.1 pooka 46 1.1 pooka sem_wait(&sem); 47 1.1 pooka sem_wait(&sem); 48 1.1 pooka rv = sem_trywait(&sem); 49 1.1 pooka ATF_REQUIRE(errno == EAGAIN); 50 1.1 pooka ATF_REQUIRE(rv == -1); 51 1.1 pooka } 52 1.1 pooka 53 1.1 pooka ATF_TC(initvalue); 54 1.1 pooka ATF_TC_HEAD(initvalue, tc) 55 1.1 pooka { 56 1.1 pooka 57 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests initialization with a non-zero " 58 1.1 pooka "value (%s)", LIBNAME); 59 1.1 pooka } 60 1.1 pooka 61 1.1 pooka ATF_TC_BODY(initvalue, tc) 62 1.1 pooka { 63 1.1 pooka sem_t sem; 64 1.1 pooka 65 1.1 pooka rump_init(); 66 1.1 pooka sem_init(&sem, 1, 4); 67 1.1 pooka 68 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0); 69 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0); 70 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0); 71 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0); 72 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), -1); 73 1.1 pooka } 74 1.1 pooka 75 1.1 pooka ATF_TC(destroy); 76 1.1 pooka ATF_TC_HEAD(destroy, tc) 77 1.1 pooka { 78 1.1 pooka 79 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_destroy works (%s)", LIBNAME); 80 1.1 pooka } 81 1.1 pooka 82 1.1 pooka ATF_TC_BODY(destroy, tc) 83 1.1 pooka { 84 1.1 pooka sem_t sem; 85 1.1 pooka int rv, i; 86 1.1 pooka 87 1.1 pooka rump_init(); 88 1.1 pooka for (i = 0; i < 2; i++) { 89 1.1 pooka sem_init(&sem, 1, 1); 90 1.1 pooka 91 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), 0); 92 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(&sem), -1); 93 1.1 pooka ATF_REQUIRE_EQ(sem_destroy(&sem), 0); 94 1.1 pooka rv = sem_trywait(&sem); 95 1.1 pooka ATF_REQUIRE_EQ(errno, EINVAL); 96 1.1 pooka ATF_REQUIRE_EQ(rv, -1); 97 1.1 pooka } 98 1.1 pooka } 99 1.1 pooka 100 1.1 pooka ATF_TC(busydestroy); 101 1.1 pooka ATF_TC_HEAD(busydestroy, tc) 102 1.1 pooka { 103 1.1 pooka 104 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_destroy report EBUSY for " 105 1.1 pooka "a busy semaphore (%s)", LIBNAME); 106 1.1 pooka } 107 1.1 pooka 108 1.1 pooka static void * 109 1.1 pooka hthread(void *arg) 110 1.1 pooka { 111 1.1 pooka sem_t *semmarit = arg; 112 1.1 pooka 113 1.1 pooka for (;;) { 114 1.1 pooka sem_post(&semmarit[2]); 115 1.1 pooka sem_wait(&semmarit[1]); 116 1.1 pooka sem_wait(&semmarit[0]); 117 1.1 pooka } 118 1.3 pooka 119 1.3 pooka return NULL; 120 1.1 pooka } 121 1.1 pooka 122 1.1 pooka ATF_TC_BODY(busydestroy, tc) 123 1.1 pooka { 124 1.1 pooka sem_t semmarit[3]; 125 1.1 pooka pthread_t pt; 126 1.1 pooka int i; 127 1.1 pooka 128 1.1 pooka /* use a unicpu rump kernel. this means less chance for race */ 129 1.1 pooka setenv("RUMP_NCPU", "1", 1); 130 1.1 pooka 131 1.1 pooka rump_init(); 132 1.1 pooka sem_init(&semmarit[0], 1, 0); 133 1.1 pooka sem_init(&semmarit[1], 1, 0); 134 1.1 pooka sem_init(&semmarit[2], 1, 0); 135 1.1 pooka 136 1.1 pooka pthread_create(&pt, NULL, hthread, semmarit); 137 1.1 pooka 138 1.1 pooka /* 139 1.1 pooka * Make a best-effort to catch the other thread with its pants down. 140 1.1 pooka * We can't do this for sure, can we? Although, we could reach 141 1.1 pooka * inside the rump kernel and inquire about the thread's sleep 142 1.1 pooka * status. 143 1.1 pooka */ 144 1.1 pooka for (i = 0; i < 1000; i++) { 145 1.1 pooka sem_wait(&semmarit[2]); 146 1.1 pooka usleep(1); 147 1.1 pooka if (sem_destroy(&semmarit[1]) == -1) 148 1.1 pooka if (errno == EBUSY) 149 1.1 pooka break; 150 1.1 pooka 151 1.1 pooka /* 152 1.1 pooka * Didn't catch it? ok, recreate and post to make the 153 1.1 pooka * other thread run 154 1.1 pooka */ 155 1.1 pooka sem_init(&semmarit[1], 1, 0); 156 1.1 pooka sem_post(&semmarit[0]); 157 1.1 pooka sem_post(&semmarit[1]); 158 1.1 pooka 159 1.1 pooka } 160 1.1 pooka if (i == 1000) 161 1.1 pooka atf_tc_fail("sem destroy not reporting EBUSY"); 162 1.8 joerg 163 1.8 joerg pthread_cancel(pt); 164 1.8 joerg pthread_join(pt, NULL); 165 1.1 pooka } 166 1.1 pooka 167 1.1 pooka ATF_TC(blockwait); 168 1.1 pooka ATF_TC_HEAD(blockwait, tc) 169 1.1 pooka { 170 1.1 pooka 171 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests sem_wait can handle blocking " 172 1.1 pooka "(%s)", LIBNAME); 173 1.5 pooka atf_tc_set_md_var(tc, "timeout", "2"); 174 1.1 pooka } 175 1.1 pooka 176 1.1 pooka ATF_TC_BODY(blockwait, tc) 177 1.1 pooka { 178 1.1 pooka sem_t semmarit[3]; 179 1.1 pooka pthread_t pt; 180 1.1 pooka int i; 181 1.1 pooka 182 1.1 pooka rump_init(); 183 1.1 pooka sem_init(&semmarit[0], 1, 0); 184 1.1 pooka sem_init(&semmarit[1], 1, 0); 185 1.1 pooka sem_init(&semmarit[2], 1, 0); 186 1.1 pooka 187 1.1 pooka pthread_create(&pt, NULL, hthread, semmarit); 188 1.1 pooka 189 1.1 pooka /* 190 1.1 pooka * Make a best-effort. Unless we're extremely unlucky, we should 191 1.1 pooka * at least one blocking wait. 192 1.1 pooka */ 193 1.1 pooka for (i = 0; i < 10; i++) { 194 1.1 pooka sem_wait(&semmarit[2]); 195 1.1 pooka usleep(1); 196 1.1 pooka sem_post(&semmarit[0]); 197 1.1 pooka sem_post(&semmarit[1]); 198 1.1 pooka 199 1.1 pooka } 200 1.8 joerg 201 1.8 joerg pthread_cancel(pt); 202 1.8 joerg pthread_join(pt, NULL); 203 1.1 pooka } 204 1.1 pooka 205 1.9 joerg ATF_TC(blocktimedwait); 206 1.9 joerg ATF_TC_HEAD(blocktimedwait, tc) 207 1.9 joerg { 208 1.9 joerg 209 1.9 joerg atf_tc_set_md_var(tc, "descr", "tests sem_timedwait can handle blocking" 210 1.9 joerg " (%s)", LIBNAME); 211 1.9 joerg atf_tc_set_md_var(tc, "timeout", "2"); 212 1.9 joerg } 213 1.9 joerg 214 1.9 joerg ATF_TC_BODY(blocktimedwait, tc) 215 1.9 joerg { 216 1.9 joerg sem_t semid; 217 1.9 joerg struct timespec tp; 218 1.9 joerg 219 1.9 joerg rump_init(); 220 1.9 joerg 221 1.9 joerg clock_gettime(CLOCK_REALTIME, &tp); 222 1.9 joerg tp.tv_nsec += 50000000; 223 1.9 joerg tp.tv_sec += tp.tv_nsec / 1000000000; 224 1.9 joerg tp.tv_nsec %= 1000000000; 225 1.9 joerg 226 1.9 joerg ATF_REQUIRE_EQ(sem_init(&semid, 1, 0), 0); 227 1.9 joerg ATF_REQUIRE_ERRNO(ETIMEDOUT, sem_timedwait(&semid, &tp) == -1); 228 1.9 joerg } 229 1.9 joerg 230 1.1 pooka ATF_TC(named); 231 1.1 pooka ATF_TC_HEAD(named, tc) 232 1.1 pooka { 233 1.1 pooka 234 1.1 pooka atf_tc_set_md_var(tc, "descr", "tests named semaphores (%s)", LIBNAME); 235 1.1 pooka } 236 1.1 pooka 237 1.1 pooka /* 238 1.1 pooka * Wow, easy naming rules. it's these times i'm really happy i can 239 1.1 pooka * single-step into the kernel. 240 1.1 pooka */ 241 1.7 pooka #define SEM1 "/precious_sem" 242 1.1 pooka #define SEM2 "/justsem" 243 1.1 pooka ATF_TC_BODY(named, tc) 244 1.1 pooka { 245 1.1 pooka sem_t *sem1, *sem2; 246 1.1 pooka void *rv; 247 1.1 pooka 248 1.1 pooka rump_init(); 249 1.1 pooka sem1 = sem_open(SEM1, 0); 250 1.1 pooka ATF_REQUIRE_EQ(errno, ENOENT); 251 1.1 pooka ATF_REQUIRE_EQ(sem1, NULL); 252 1.1 pooka 253 1.1 pooka sem1 = sem_open(SEM1, O_CREAT, 0444, 1); 254 1.1 pooka if (sem1 == NULL) 255 1.1 pooka atf_tc_fail_errno("sem_open O_CREAT"); 256 1.1 pooka 257 1.1 pooka rv = sem_open(SEM1, O_CREAT | O_EXCL); 258 1.1 pooka ATF_REQUIRE_EQ(errno, EEXIST); 259 1.1 pooka ATF_REQUIRE_EQ(rv, NULL); 260 1.1 pooka 261 1.1 pooka sem2 = sem_open(SEM2, O_CREAT, 0444, 0); 262 1.1 pooka if (sem2 == NULL) 263 1.1 pooka atf_tc_fail_errno("sem_open O_CREAT"); 264 1.1 pooka 265 1.1 pooka /* check that semaphores are independent */ 266 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1); 267 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), 0); 268 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), -1); 269 1.1 pooka 270 1.1 pooka /* check that unlinked remains valid */ 271 1.1 pooka sem_unlink(SEM2); 272 1.1 pooka ATF_REQUIRE_EQ(sem_post(sem2), 0); 273 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), 0); 274 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1); 275 1.1 pooka ATF_REQUIRE_EQ(errno, EAGAIN); 276 1.1 pooka 277 1.1 pooka #if 0 /* see unlink */ 278 1.1 pooka /* close it and check that it's gone */ 279 1.1 pooka if (sem_close(sem2) != 0) 280 1.1 pooka atf_tc_fail_errno("sem close"); 281 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem2), -1); 282 1.1 pooka ATF_REQUIRE_EQ(errno, EINVAL); 283 1.1 pooka #endif 284 1.1 pooka 285 1.1 pooka /* check that we still have sem1 */ 286 1.1 pooka sem_post(sem1); 287 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), 0); 288 1.1 pooka ATF_REQUIRE_EQ(sem_trywait(sem1), -1); 289 1.1 pooka ATF_REQUIRE_EQ(errno, EAGAIN); 290 1.1 pooka } 291 1.1 pooka 292 1.1 pooka ATF_TC(unlink); 293 1.1 pooka ATF_TC_HEAD(unlink, tc) 294 1.1 pooka { 295 1.1 pooka 296 1.1 pooka /* this is currently broken. i'll append the PR number soon */ 297 1.2 pooka atf_tc_set_md_var(tc, "descr", "tests unlinked semaphores can be " 298 1.4 pooka "closed (%s)", LIBNAME); 299 1.1 pooka } 300 1.1 pooka 301 1.1 pooka #define SEM "/thesem" 302 1.1 pooka ATF_TC_BODY(unlink, tc) 303 1.1 pooka { 304 1.1 pooka sem_t *sem; 305 1.1 pooka 306 1.1 pooka rump_init(); 307 1.1 pooka sem = sem_open(SEM, O_CREAT, 0444, 0); 308 1.1 pooka ATF_REQUIRE(sem); 309 1.1 pooka 310 1.1 pooka if (sem_unlink(SEM) == -1) 311 1.1 pooka atf_tc_fail_errno("unlink"); 312 1.1 pooka if (sem_close(sem) == -1) 313 1.1 pooka atf_tc_fail_errno("close unlinked semaphore"); 314 1.1 pooka } 315 1.1 pooka 316 1.1 pooka /* use rump calls for libpthread _ksem_foo() calls */ 317 1.1 pooka #define F1(name, a) int _ksem_##name(a); \ 318 1.1 pooka int _ksem_##name(a v1) {return rump_sys__ksem_##name(v1);} 319 1.1 pooka #define F2(name, a, b) int _ksem_##name(a, b); \ 320 1.1 pooka int _ksem_##name(a v1, b v2) {return rump_sys__ksem_##name(v1, v2);} 321 1.1 pooka F2(init, unsigned int, intptr_t *); 322 1.1 pooka F1(close, intptr_t); 323 1.1 pooka F1(destroy, intptr_t); 324 1.1 pooka F1(post, intptr_t); 325 1.1 pooka F1(unlink, const char *); 326 1.1 pooka F1(trywait, intptr_t); 327 1.1 pooka F1(wait, intptr_t); 328 1.1 pooka F2(getvalue, intptr_t, unsigned int *); 329 1.9 joerg F2(timedwait, intptr_t, const struct timespec *); 330 1.1 pooka int _ksem_open(const char *, int, mode_t, unsigned int, intptr_t *); 331 1.1 pooka int _ksem_open(const char *a, int b, mode_t c, unsigned int d, intptr_t *e) 332 1.1 pooka {return rump_sys__ksem_open(a,b,c,d,e);} 333