static void unlocked_wait(void) { semid_t id; u_int elapsed; if (ksem_init(&id, 1) < 0) { fail_errno("ksem_init"); return; } /* This should succeed right away and set the value to 0. */ if (testwait(id, &elapsed) < 0) { ksem_destroy(id); return; } if (!ELAPSED(elapsed, 0)) { fail_err("ksem_wait() of unlocked sem took %ums", elapsed); ksem_destroy(id); return; } if (checkvalue(id, 0) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void expired_timedwait(void) { semid_t id; u_int elapsed; if (ksem_init(&id, 0) < 0) { fail_errno("ksem_init"); return; } /* This should fail with a timeout and leave the value at 0. */ if (timedwait(id, 2500, &elapsed, ETIMEDOUT) < 0) { ksem_destroy(id); return; } if (!ELAPSED(elapsed, 2500)) { fail_err( "ksem_timedwait() of locked sem took %ums instead of 2500ms", elapsed); ksem_destroy(id); return; } if (checkvalue(id, 0) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void unlocked_trywait(void) { semid_t id; if (ksem_init(&id, 1) < 0) { fail_errno("ksem_init"); return; } /* This should succeed and decrement the value to 0. */ if (ksem_trywait(id) < 0) { fail_errno("ksem_trywait()"); ksem_destroy(id); return; } if (checkvalue(id, 0) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void locked_trywait(void) { semid_t id; if (ksem_init(&id, 0) < 0) { fail_errno("ksem_init"); return; } /* This should fail with EAGAIN and leave the value at 0. */ if (ksem_trywait(id) >= 0) { fail_err("ksem_trywait() didn't fail"); ksem_destroy(id); return; } if (errno != EAGAIN) { fail_errno("wrong error from ksem_trywait()"); ksem_destroy(id); return; } if (checkvalue(id, 0) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void maxvalue_test(void) { semid_t id; int val; if (ksem_init(&id, SEM_VALUE_MAX) < 0) { fail_errno("ksem_init"); return; } if (ksem_getvalue(id, &val) < 0) { fail_errno("ksem_getvalue"); ksem_destroy(id); return; } if (val != SEM_VALUE_MAX) { fail_err("value %d != SEM_VALUE_MAX"); ksem_destroy(id); return; } if (val < 0) { fail_err("value < 0"); ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void post_test(void) { semid_t id; if (ksem_init(&id, 1) < 0) { fail_errno("ksem_init"); return; } if (checkvalue(id, 1) < 0) { ksem_destroy(id); return; } if (ksem_post(id) < 0) { fail_errno("ksem_post"); ksem_destroy(id); return; } if (checkvalue(id, 2) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void close_unnamed_semaphore(void) { semid_t id; if (ksem_init(&id, 1) < 0) { fail_errno("ksem_init"); return; } ksem_close_should_fail(id, EINVAL); ksem_destroy(id); }
static void maxvalue_post_test(void) { semid_t id; if (ksem_init(&id, SEM_VALUE_MAX) < 0) { fail_errno("ksem_init"); return; } ksem_post_should_fail(id, EOVERFLOW); ksem_destroy(id); }
static void create_unnamed_semaphore(void) { semid_t id; if (ksem_init(&id, 1) < 0) { fail_errno("ksem_init"); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
/* * Attempt a ksem_init() that should fail with an expected error of * 'error'. */ static void ksem_init_should_fail(unsigned int value, int error) { semid_t id; if (ksem_init(&id, value) >= 0) { fail_err("ksem_init() didn't fail"); ksem_destroy(id); return; } if (errno != error) { fail_errno("ksem_init"); return; } pass(); }
static int exhaust_unnamed_child(void *arg) { semid_t id; int i, max; max = (intptr_t)arg; for (i = 0; i < max + 1; i++) { if (ksem_init(&id, 1) < 0) { if (errno == ENOSPC) return (CSTAT(0, 0)); return (CSTAT(1, errno)); } } return (CSTAT(2, 0)); }
int _sem_init(sem_t *sem, int pshared, unsigned int value) { semid_t semid; semid = (semid_t)SEM_USER; if ((pshared != 0) && (ksem_init(&semid, value) != 0)) return (-1); (*sem) = sem_alloc(value, semid, pshared); if ((*sem) == NULL) { if (pshared != 0) ksem_destroy(semid); return (-1); } return (0); }
static void locked_timedwait(void) { semid_t id; u_int elapsed; if (ksem_init(&id, 0) < 0) { fail_errno("ksem_init"); return; } /* * Schedule a post to trigger after 1000 ms. The subsequent * timedwait should succeed after 1000 ms as a result w/o * timing out. */ if (schedule_post(id, 1000) < 0) { ksem_destroy(id); return; } if (timedwait(id, 2000, &elapsed, 0) < 0) { check_alarm(1); ksem_destroy(id); return; } if (!ELAPSED(elapsed, 1000)) { fail_err( "ksem_timedwait() with delayed post took %ums instead of 1000ms", elapsed); check_alarm(1); ksem_destroy(id); return; } if (check_alarm(0) < 0) { ksem_destroy(id); return; } if (ksem_destroy(id) < 0) { fail_errno("ksem_destroy"); return; } pass(); }
static void busy_destroy_test(void) { char errbuf[_POSIX2_LINE_MAX]; struct kinfo_proc *kp; semid_t id; pid_t pid; kvm_t *kd; int count; kd = kvm_openfiles(NULL, "/dev/null", NULL, O_RDONLY, errbuf); if (kd == NULL) { fail_err("kvm_openfiles: %s", errbuf); return; } if (ksem_init(&id, 0) < 0) { fail_errno("ksem_init"); kvm_close(kd); return; } pid = fork(); switch (pid) { case -1: /* Error. */ fail_errno("fork"); ksem_destroy(id); kvm_close(kd); return; case 0: /* Child. */ ksem_wait(id); exit(0); } /* * Wait for the child process to block on the semaphore. This * is a bit gross. */ for (;;) { kp = kvm_getprocs(kd, KERN_PROC_PID, pid, &count); if (kp == NULL) { fail_err("kvm_getprocs: %s", kvm_geterr(kd)); kvm_close(kd); ksem_destroy(id); return; } if (kp->ki_stat == SSLEEP && (strcmp(kp->ki_wmesg, "sem") == 0 || strcmp(kp->ki_wmesg, "ksem") == 0)) break; usleep(1000); } kvm_close(kd); ksem_destroy_should_fail(id, EBUSY); /* Cleanup. */ ksem_post(id); waitpid(pid, NULL, 0); ksem_destroy(id); }