Page MenuHomeFreeBSD

D27574.id80591.diff
No OneTemporary

D27574.id80591.diff

Index: contrib/netbsd-tests/lib/libpthread/t_cond.c
===================================================================
--- contrib/netbsd-tests/lib/libpthread/t_cond.c
+++ contrib/netbsd-tests/lib/libpthread/t_cond.c
@@ -541,23 +541,45 @@
static void
unlock(void *arg)
{
- pthread_mutex_unlock((pthread_mutex_t *)arg);
+ fprintf(stderr, "2: cancel callback\n");
+ /*
+ * We may or may not hold the mutex here depending on when the
+ * cancellation request was handled.
+ */
+ if (pthread_mutex_isowned_np((pthread_mutex_t *)arg)) {
+ pthread_mutex_unlock((pthread_mutex_t *)arg);
+ fprintf(stderr, "2: unlocked\n");
+ } else {
+ fprintf(stderr, "2: mutex was not owned\n");
+ }
}
static void *
destroy_after_cancel_threadfunc(void *arg)
{
+ // fprintf(stderr, "2: locking\n");
PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
-
+ ATF_REQUIRE(pthread_mutex_isowned_np(&mutex));
+ // fprintf(stderr, "2: locked\n");
pthread_cleanup_push(unlock, &mutex);
+ // fprintf(stderr, "2: pushed\n");
+ PTHREAD_REQUIRE(pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS,
+ NULL));
+ // fprintf(stderr, "2: enabled async cancel\n");
while (1) {
share = 1;
+ // fprintf(stderr, "2: bcast\n");
+ ATF_REQUIRE(pthread_mutex_isowned_np(&mutex));
PTHREAD_REQUIRE(pthread_cond_broadcast(&cond));
+ // fprintf(stderr, "2: wait...\n");
PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
+ // fprintf(stderr, "2: waited\n");
}
-
+ // Should be unreachable.
+ // fprintf(stderr, "2: pop\n");
pthread_cleanup_pop(0);
+ // fprintf(stderr, "2: unlock\n");
PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
return NULL;
@@ -572,23 +594,48 @@
ATF_TC_BODY(destroy_after_cancel, tc)
{
pthread_t thread;
+ void *retval;
+ unsigned num_cancel_requests = 0;
PTHREAD_REQUIRE(pthread_mutex_init(&mutex, NULL));
PTHREAD_REQUIRE(pthread_cond_init(&cond, NULL));
PTHREAD_REQUIRE(pthread_mutex_lock(&mutex));
+ ATF_REQUIRE(pthread_mutex_isowned_np(&mutex));
+ // fprintf(stderr, "1: creating...\n");
PTHREAD_REQUIRE(pthread_create(&thread, NULL,
destroy_after_cancel_threadfunc, NULL));
while (share == 0) {
+ // fprintf(stderr, "1: share=0 waiting...\n");
PTHREAD_REQUIRE(pthread_cond_wait(&cond, &mutex));
+ // fprintf(stderr, "1: woken\n");
}
+ // fprintf(stderr, "1: after loop\n");
+ ATF_REQUIRE(pthread_mutex_isowned_np(&mutex));
+ // fprintf(stderr, "1: unlock\n");
PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
- PTHREAD_REQUIRE(pthread_cancel(thread));
-
- PTHREAD_REQUIRE(pthread_join(thread, NULL));
+ // fprintf(stderr, "1: unlocked\n");
+ /*
+ * Note: The pthread_cancel request might not be received by the target
+ * thread depending on where it is in the pthread_cond_wait()
+ * implementation. To avoid this missed wakeup, keep cancelling the
+ * thread until the mutex is unlocked (i.e. the callback finished).
+ */
+ // fprintf(stderr, "1: pthread_cancel loop\n");
+ while (!pthread_mutex_trylock(&mutex)) {
+ num_cancel_requests++;
+ // fprintf(stderr, "1: pthread_cancel #%d\n", num_cancel_requests);
+ PTHREAD_REQUIRE(pthread_cancel(thread));
+ pthread_yield();
+ }
+ // fprintf(stderr, "1: mutex acquired, joining...\n");
+ PTHREAD_REQUIRE(pthread_join(thread, &retval));
+ PTHREAD_REQUIRE(pthread_mutex_unlock(&mutex));
+ ATF_CHECK_EQ(retval, PTHREAD_CANCELED);
+ // fprintf(stderr, "1: destroy cond\n");
PTHREAD_REQUIRE(pthread_cond_destroy(&cond));
-
+ // fprintf(stderr, "1: destroy mutex\n");
PTHREAD_REQUIRE(pthread_mutex_destroy(&mutex));
}

File Metadata

Mime Type
text/plain
Expires
Sun, Jul 5, 10:54 AM (2 h, 31 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34693765
Default Alt Text
D27574.id80591.diff (3 KB)

Event Timeline