summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2004-01-17 02:45:37 +0000
committerdavidxu <davidxu@FreeBSD.org>2004-01-17 02:45:37 +0000
commitf9aac56ad7dea97108acd58f36d211e416fb0322 (patch)
tree9a5afc1ab068736e470c190a1fa85d4ae3ed2869 /lib/libc
parent8a660e960711826394a7a18bfe6a9cfe071e7a21 (diff)
downloadFreeBSD-src-f9aac56ad7dea97108acd58f36d211e416fb0322.zip
FreeBSD-src-f9aac56ad7dea97108acd58f36d211e416fb0322.tar.gz
Enable cancellation point in sem_wait, it is required by POSIX.
For pshared semaphore, this commit still does not enable cancellation point, I think there should be a pthread_enter_cancellation_point_np for libc to implement a safe cancellation point.
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/gen/sem.c20
1 files changed, 18 insertions, 2 deletions
diff --git a/lib/libc/gen/sem.c b/lib/libc/gen/sem.c
index e37eccd..e9a918b 100644
--- a/lib/libc/gen/sem.c
+++ b/lib/libc/gen/sem.c
@@ -254,7 +254,19 @@ sem_unlink(const char *name)
return (ksem_unlink(name));
}
-int
+static void
+decrease_nwaiters(void *arg)
+{
+ sem_t *sem = (sem_t *)arg;
+
+ (*sem)->nwaiters--;
+ /*
+ * this function is called from cancellation point,
+ * the mutex should already be hold.
+ */
+ _pthread_mutex_unlock(&(*sem)->lock);
+}
+
sem_wait(sem_t *sem)
{
int retval;
@@ -266,11 +278,15 @@ sem_wait(sem_t *sem)
goto RETURN;
}
+ _pthread_testcancel();
+
_pthread_mutex_lock(&(*sem)->lock);
while ((*sem)->count == 0) {
(*sem)->nwaiters++;
- _pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
+ _pthread_cleanup_push(decrease_nwaiters);
+ pthread_cond_wait(&(*sem)->gtzero, &(*sem)->lock);
+ pthread_cleanup_pop(0);
(*sem)->nwaiters--;
}
(*sem)->count--;
OpenPOWER on IntegriCloud