/*
* Make a best-effort to catch the other thread with its pants down.
* We can't do this for sure, can we? Although, we could reach
* inside the rump kernel and inquire about the thread's sleep
* status.
*/
for (i = 0; i < 1000; i++) {
sem_wait(&semmarit[2]);
usleep(1);
if (sem_destroy(&semmarit[1]) == -1)
if (errno == EBUSY)
break;
/*
* Didn't catch it? ok, recreate and post to make the
* other thread run
*/
sem_init(&semmarit[1], 1, 0);
sem_post(&semmarit[0]);
sem_post(&semmarit[1]);
}
if (i == 1000)
atf_tc_fail("sem destroy not reporting EBUSY");
/*
* Make a best-effort. Unless we're extremely unlucky, we should
* at least one blocking wait.
*/
for (i = 0; i < 10; i++) {
sem_wait(&semmarit[2]);
usleep(1);
sem_post(&semmarit[0]);
sem_post(&semmarit[1]);
#if 0 /* see unlink */
/* close it and check that it's gone */
if (sem_close(sem2) != 0)
atf_tc_fail_errno("sem close");
ATF_REQUIRE_EQ(sem_trywait(sem2), -1);
ATF_REQUIRE_EQ(errno, EINVAL);
#endif
/* check that we still have sem1 */
sem_post(sem1);
ATF_REQUIRE_EQ(sem_trywait(sem1), 0);
ATF_REQUIRE_EQ(sem_trywait(sem1), -1);
ATF_REQUIRE_EQ(errno, EAGAIN);
}
ATF_TC(unlink);
ATF_TC_HEAD(unlink, tc)
{
/* this is currently broken. i'll append the PR number soon */
atf_tc_set_md_var(tc, "descr", "tests unlinked semaphores can be "
"closed (%s)", LIBNAME);
}
#define SEM "/thesem"
ATF_TC_BODY(unlink, tc)
{
sem_t *sem;
rump_init();
sem = sem_open(SEM, O_CREAT, 0444, 0);
ATF_REQUIRE(sem);
if (sem_unlink(SEM) == -1)
atf_tc_fail_errno("unlink");
if (sem_close(sem) == -1)
atf_tc_fail_errno("close unlinked semaphore");
}
/* use rump calls for libpthread _ksem_foo() calls */
#define F1(name, a) int _ksem_##name(a); \
int _ksem_##name(a v1) {return rump_sys__ksem_##name(v1);}
#define F2(name, a, b) int _ksem_##name(a, b); \
int _ksem_##name(a v1, b v2) {return rump_sys__ksem_##name(v1, v2);}
F2(init, unsigned int, intptr_t *);
F1(close, intptr_t);
F1(destroy, intptr_t);
F1(post, intptr_t);
F1(unlink, const char *);
F1(trywait, intptr_t);
F1(wait, intptr_t);
F2(getvalue, intptr_t, unsigned int *);
F2(timedwait, intptr_t, const struct timespec *);
int _ksem_open(const char *, int, mode_t, unsigned int, intptr_t *);
int _ksem_open(const char *a, int b, mode_t c, unsigned int d, intptr_t *e)
{return rump_sys__ksem_open(a,b,c,d,e);}