summaryrefslogtreecommitdiff
path: root/lib/libc_r/uthread
diff options
context:
space:
mode:
authorFederico G. Schwindt <fgsch@cvs.openbsd.org>2001-12-08 14:51:37 +0000
committerFederico G. Schwindt <fgsch@cvs.openbsd.org>2001-12-08 14:51:37 +0000
commitf12d711b8ff30cbb7e08bb32d88af46cc64c0769 (patch)
tree5fd6e5a28182f82c323032d9dce6aa32a60b622b /lib/libc_r/uthread
parent203c9a03b47df77947e1b30e3a939aa45a9a35e0 (diff)
Partially sync with FreeBSD; mostly pthread_cancel(3) related changes.
make includes is needed in case you want to play.
Diffstat (limited to 'lib/libc_r/uthread')
-rw-r--r--lib/libc_r/uthread/pthread_private.h25
-rw-r--r--lib/libc_r/uthread/uthread_cancel.c139
-rw-r--r--lib/libc_r/uthread/uthread_cond.c13
-rw-r--r--lib/libc_r/uthread/uthread_create.c7
-rw-r--r--lib/libc_r/uthread/uthread_info_openbsd.c5
-rw-r--r--lib/libc_r/uthread/uthread_init.c6
-rw-r--r--lib/libc_r/uthread/uthread_kern.c36
7 files changed, 140 insertions, 91 deletions
diff --git a/lib/libc_r/uthread/pthread_private.h b/lib/libc_r/uthread/pthread_private.h
index 1fbe0dce592..a07ebaf431d 100644
--- a/lib/libc_r/uthread/pthread_private.h
+++ b/lib/libc_r/uthread/pthread_private.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: pthread_private.h,v 1.29 2001/09/04 23:28:31 fgsch Exp $ */
+/* $OpenBSD: pthread_private.h,v 1.30 2001/12/08 14:51:36 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -588,12 +588,6 @@ struct pthread {
int sig_saved;
/*
- * Cancelability state.
- */
- int cancelstate;
- int canceltype;
-
- /*
* Cancelability flags - the lower 2 bits are used by cancel
* definitions in pthread.h
*/
@@ -703,13 +697,16 @@ struct pthread {
int flags;
#define PTHREAD_FLAGS_PRIVATE 0x0001
#define PTHREAD_EXITING 0x0002
-#define PTHREAD_FLAGS_IN_CONDQ 0x0004 /* in condition queue using qe link*/
-#define PTHREAD_FLAGS_IN_WORKQ 0x0008 /* in work queue using qe link */
-#define PTHREAD_FLAGS_IN_WAITQ 0x0010 /* in waiting queue using pqe link*/
-#define PTHREAD_FLAGS_IN_PRIOQ 0x0020 /* in priority queue using pqe link*/
-#define PTHREAD_FLAGS_TRACE 0x0040 /* for debugging purposes */
-#define PTHREAD_FLAGS_CANCELED 0x1000 /* thread has been cancelled */
-#define PTHREAD_FLAGS_CANCELPT 0x2000 /* thread at cancel point */
+#define PTHREAD_FLAGS_IN_WAITQ 0x0004 /* in waiting queue using pqe link*/
+#define PTHREAD_FLAGS_IN_PRIOQ 0x0008 /* in priority queue using pqe link*/
+#define PTHREAD_FLAGS_IN_WORKQ 0x0010 /* in work queue using qe link */
+#define PTHREAD_FLAGS_IN_FILEQ 0x0020 /* in file lock queue using qe link */
+#define PTHREAD_FLAGS_IN_FDQ 0x0040 /* in fd lock queue using qe link */
+#define PTHREAD_FLAGS_IN_CONDQ 0x0080 /* in condition queue using sqe link*/
+#define PTHREAD_FLAGS_IN_MUTEXQ 0x0100 /* in mutex queue using sqe link*/
+#define PTHREAD_FLAGS_TRACE 0x0200 /* for debugging purposes */
+#define PTHREAD_FLAGS_IN_SYNQ \
+ (PTHREAD_FLAGS_IN_CONDQ | PTHREAD_FLAGS_IN_MUTEXQ)
/*
* Base priority is the user setable and retrievable priority
diff --git a/lib/libc_r/uthread/uthread_cancel.c b/lib/libc_r/uthread/uthread_cancel.c
index 7f53aed66ce..b536acc4b8e 100644
--- a/lib/libc_r/uthread/uthread_cancel.c
+++ b/lib/libc_r/uthread/uthread_cancel.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_cancel.c,v 1.6 2001/09/04 22:17:45 fgsch Exp $ */
+/* $OpenBSD: uthread_cancel.c,v 1.7 2001/12/08 14:51:36 fgsch Exp $ */
/*
* David Leonard <d@openbsd.org>, 1999. Public domain.
*/
@@ -6,6 +6,9 @@
#include <pthread.h>
#include "pthread_private.h"
+
+static void finish_cancellation(void *arg);
+
int
pthread_cancel(pthread)
pthread_t pthread;
@@ -16,47 +19,75 @@ pthread_cancel(pthread)
/* NOTHING */
} else if (pthread->state == PS_DEAD || pthread->state == PS_DEADLOCK) {
ret = 0;
- } else if ((pthread->flags & PTHREAD_FLAGS_CANCELED) == 0) {
- /* Set the thread's I've-been-cancelled flag: */
- pthread->flags |= PTHREAD_FLAGS_CANCELED;
- /* Check if we need to kick it back into the run queue: */
- if ((pthread->cancelstate == PTHREAD_CANCEL_ENABLE) &&
- ((pthread->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS) ||
- (pthread->flags & PTHREAD_FLAGS_CANCELPT)))
+ } else {
+ /* Protect the scheduling queues: */
+ _thread_kern_sig_defer();
+
+ if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) ||
+ (((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) &&
+ ((pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0)))
+ /* Just mark it for cancellation: */
+ pthread->cancelflags |= PTHREAD_CANCELLING;
+ else {
+ /*
+ * Check if we need to kick it back into the
+ * run queue:
+ */
switch (pthread->state) {
- case PS_WAIT_WAIT:
+ case PS_RUNNING:
+ /* No need to resume: */
+ pthread->cancelflags |= PTHREAD_CANCELLING;
+ break;
+
+ case PS_SPINBLOCK:
case PS_FDR_WAIT:
case PS_FDW_WAIT:
- case PS_SLEEP_WAIT:
- case PS_SELECT_WAIT:
case PS_POLL_WAIT:
+ case PS_SELECT_WAIT:
+ if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
+ != 0)
+ PTHREAD_WORKQ_REMOVE(pthread);
+ /* Fall through: */
+ case PS_SIGTHREAD:
+ case PS_SLEEP_WAIT:
+ case PS_WAIT_WAIT:
case PS_SIGSUSPEND:
+ case PS_SIGWAIT:
/* Interrupt and resume: */
pthread->interrupted = 1;
- if (pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
- PTHREAD_WORKQ_REMOVE(pthread);
+ pthread->cancelflags |= PTHREAD_CANCELLING;
PTHREAD_NEW_STATE(pthread,PS_RUNNING);
break;
+
case PS_MUTEX_WAIT:
case PS_COND_WAIT:
- case PS_SIGWAIT:
case PS_FDLR_WAIT:
case PS_FDLW_WAIT:
case PS_FILE_WAIT:
+ pthread->interrupted = 1;
+ pthread->cancelflags |= PTHREAD_CANCEL_NEEDED;
+ PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ pthread->continuation = finish_cancellation;
+ break;
+
case PS_JOIN:
case PS_SUSPENDED:
- case PS_SIGTHREAD:
/* Simply wake: */
/* XXX may be incorrect */
PTHREAD_NEW_STATE(pthread,PS_RUNNING);
break;
- case PS_RUNNING:
- case PS_DEADLOCK:
- case PS_SPINBLOCK:
+
case PS_DEAD:
- /* Ignore */
+ case PS_DEADLOCK:
+ case PS_STATE_MAX:
+ /* Ignore - only here to silence -Wall: */
break;
+ }
}
+
+ /* Unprotect the scheduling queues: */
+ _thread_kern_sig_undefer();
+
ret = 0;
}
return (ret);
@@ -71,21 +102,21 @@ pthread_setcancelstate(state, oldstate)
int ostate;
int ret;
- ostate = curthread->cancelstate;
+ ostate = curthread->cancelflags & PTHREAD_CANCEL_DISABLE;
switch (state) {
case PTHREAD_CANCEL_ENABLE:
- if (oldstate)
+ if (oldstate != NULL)
*oldstate = ostate;
- curthread->cancelstate = PTHREAD_CANCEL_ENABLE;
- if (curthread->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
- _thread_cancellation_point();
+ curthread->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
+ if ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
+ pthread_testcancel();
ret = 0;
break;
case PTHREAD_CANCEL_DISABLE:
- if (oldstate)
+ if (oldstate != NULL)
*oldstate = ostate;
- curthread->cancelstate = PTHREAD_CANCEL_DISABLE;
+ curthread->cancelflags |= PTHREAD_CANCEL_DISABLE;
ret = 0;
break;
default:
@@ -105,19 +136,19 @@ pthread_setcanceltype(type, oldtype)
int otype;
int ret;
- otype = curthread->canceltype;
+ otype = curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS;
switch (type) {
case PTHREAD_CANCEL_ASYNCHRONOUS:
- if (oldtype)
+ if (oldtype != NULL)
*oldtype = otype;
- curthread->canceltype = PTHREAD_CANCEL_ASYNCHRONOUS;
- _thread_cancellation_point();
+ curthread->cancelflags |= PTHREAD_CANCEL_ASYNCHRONOUS;
+ pthread_testcancel();
ret = 0;
break;
case PTHREAD_CANCEL_DEFERRED:
- if (oldtype)
+ if (oldtype != NULL)
*oldtype = otype;
- curthread->canceltype = PTHREAD_CANCEL_DEFERRED;
+ curthread->cancelflags &= ~PTHREAD_CANCEL_ASYNCHRONOUS;
ret = 0;
break;
default:
@@ -130,44 +161,52 @@ pthread_setcanceltype(type, oldtype)
void
pthread_testcancel()
{
+ struct pthread *curthread = _get_curthread();
- _thread_cancellation_point();
+ if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
+ ((curthread->cancelflags & PTHREAD_CANCELLING) != 0)) {
+ curthread->cancelflags &= ~PTHREAD_CANCELLING;
+#ifdef notyet
+ _thread_exit_cleanup();
+#endif
+ pthread_exit(PTHREAD_CANCELED);
+ PANIC("cancel");
+ }
}
void
-_thread_enter_cancellation_point()
+_thread_enter_cancellation_point(void)
{
struct pthread *curthread = _get_curthread();
/* Look for a cancellation before we block: */
- _thread_cancellation_point();
- curthread->flags |= PTHREAD_FLAGS_CANCELPT;
+ pthread_testcancel();
+ curthread->cancelflags |= PTHREAD_AT_CANCEL_POINT;
}
void
-_thread_leave_cancellation_point()
+_thread_leave_cancellation_point(void)
{
struct pthread *curthread = _get_curthread();
- curthread->flags &=~ PTHREAD_FLAGS_CANCELPT;
+ curthread->cancelflags &= ~PTHREAD_AT_CANCEL_POINT;
/* Look for a cancellation after we unblock: */
- _thread_cancellation_point();
+ pthread_testcancel();
}
-/*
- * Must only be called when in asynchronous cancel mode, or
- * from pthread_testcancel().
- */
-void
-_thread_cancellation_point()
+static void
+finish_cancellation(void *arg)
{
struct pthread *curthread = _get_curthread();
- if ((curthread->cancelstate == PTHREAD_CANCEL_ENABLE) &&
- ((curthread->flags & (PTHREAD_FLAGS_CANCELED|PTHREAD_EXITING)) ==
- PTHREAD_FLAGS_CANCELED)) {
- curthread->flags &=~ PTHREAD_FLAGS_CANCELED;
+ curthread->continuation = NULL;
+ curthread->interrupted = 0;
+
+ if ((curthread->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
+ curthread->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
+#ifdef notyet
+ _thread_exit_cleanup();
+#endif
pthread_exit(PTHREAD_CANCELED);
- PANIC("cancel");
}
}
diff --git a/lib/libc_r/uthread/uthread_cond.c b/lib/libc_r/uthread/uthread_cond.c
index 48ee72a6b2f..dea5d5ffa39 100644
--- a/lib/libc_r/uthread/uthread_cond.c
+++ b/lib/libc_r/uthread/uthread_cond.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_cond.c,v 1.10 2001/08/21 19:24:53 fgsch Exp $ */
+/* $OpenBSD: uthread_cond.c,v 1.11 2001/12/08 14:51:36 fgsch Exp $ */
/*
* Copyright (c) 1995 John Birrell <jb@cimlogic.com.au>.
* All rights reserved.
@@ -159,7 +159,8 @@ int
pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
{
struct pthread *curthread = _get_curthread();
- int rval = 0;
+ int rval = 0;
+ int interrupted = 0;
/* This is a cancellation point: */
_thread_enter_cancellation_point();
@@ -252,6 +253,9 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
rval = EINVAL;
break;
}
+
+ if ((interrupted != 0) && (curthread->continuation != NULL))
+ curthread->continuation((void *) curthread);
}
/* No longer in a cancellation point: */
@@ -266,7 +270,8 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
const struct timespec * abstime)
{
struct pthread *curthread = _get_curthread();
- int rval = 0;
+ int rval = 0;
+ int interrupted = 0;
/* This is a cancellation point: */
_thread_enter_cancellation_point();
@@ -396,6 +401,8 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
break;
}
+ if ((interrupted != 0) && (curthread->continuation != NULL))
+ curthread->continuation((void *) curthread);
}
/* No longer in a cancellation point: */
diff --git a/lib/libc_r/uthread/uthread_create.c b/lib/libc_r/uthread/uthread_create.c
index 82606872c1d..5b1897b7ef4 100644
--- a/lib/libc_r/uthread/uthread_create.c
+++ b/lib/libc_r/uthread/uthread_create.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_create.c,v 1.15 2001/08/21 19:24:53 fgsch Exp $ */
+/* $OpenBSD: uthread_create.c,v 1.16 2001/12/08 14:51:36 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -93,8 +93,8 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->stack = stack;
new_thread->start_routine = start_routine;
new_thread->arg = arg;
- new_thread->cancelstate = PTHREAD_CANCEL_ENABLE;
- new_thread->canceltype = PTHREAD_CANCEL_DEFERRED;
+ new_thread->cancelflags = PTHREAD_CANCEL_ENABLE |
+ PTHREAD_CANCEL_DEFERRED;
/*
* Write a magic value to the thread structure
@@ -152,6 +152,7 @@ pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->flags = 0;
new_thread->poll_data.nfds = 0;
new_thread->poll_data.fds = NULL;
+ new_thread->continuation = NULL;
/*
* Defer signals to protect the scheduling queues
diff --git a/lib/libc_r/uthread/uthread_info_openbsd.c b/lib/libc_r/uthread/uthread_info_openbsd.c
index 6a5d24ddf3d..439bf6a7655 100644
--- a/lib/libc_r/uthread/uthread_info_openbsd.c
+++ b/lib/libc_r/uthread/uthread_info_openbsd.c
@@ -29,7 +29,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $OpenBSD: uthread_info_openbsd.c,v 1.3 2000/02/26 13:32:01 d Exp $
+ * $OpenBSD: uthread_info_openbsd.c,v 1.4 2001/12/08 14:51:36 fgsch Exp $
*/
#include <stdio.h>
#include <fcntl.h>
@@ -129,8 +129,7 @@ _thread_dump_entry(pthread, fd, verbose)
pthread->active_priority,
(pthread->flags & PTHREAD_FLAGS_PRIVATE) ? 'p' : '-',
(pthread->flags & PTHREAD_EXITING) ? 'E' :
- (pthread->flags & PTHREAD_FLAGS_CANCELED) ? 'C' :
- (pthread->flags & PTHREAD_FLAGS_CANCELPT) ? 'c' : '-',
+ (pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) ? 'c' : '-',
(pthread->flags & PTHREAD_FLAGS_TRACE) ? 't' : '-',
(pthread->flags & PTHREAD_FLAGS_IN_CONDQ) ? 'C' : '-',
(pthread->flags & PTHREAD_FLAGS_IN_WORKQ) ? 'R' : '-',
diff --git a/lib/libc_r/uthread/uthread_init.c b/lib/libc_r/uthread/uthread_init.c
index caf5b9e9989..a0aaf8e8964 100644
--- a/lib/libc_r/uthread/uthread_init.c
+++ b/lib/libc_r/uthread/uthread_init.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_init.c,v 1.16 2001/09/04 22:17:45 fgsch Exp $ */
+/* $OpenBSD: uthread_init.c,v 1.17 2001/12/08 14:51:36 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -175,8 +175,8 @@ _thread_init(void)
_thread_initial->magic = PTHREAD_MAGIC;
/* Set the initial cancel state */
- _thread_initial->cancelstate = PTHREAD_CANCEL_ENABLE;
- _thread_initial->canceltype = PTHREAD_CANCEL_DEFERRED;
+ _thread_initial->cancelflags = PTHREAD_CANCEL_ENABLE |
+ PTHREAD_CANCEL_DEFERRED;
/* Default the priority of the initial thread: */
_thread_initial->base_priority = PTHREAD_DEFAULT_PRIORITY;
diff --git a/lib/libc_r/uthread/uthread_kern.c b/lib/libc_r/uthread/uthread_kern.c
index 7522b57b33b..d9a6108397b 100644
--- a/lib/libc_r/uthread/uthread_kern.c
+++ b/lib/libc_r/uthread/uthread_kern.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: uthread_kern.c,v 1.16 2001/09/04 22:17:45 fgsch Exp $ */
+/* $OpenBSD: uthread_kern.c,v 1.17 2001/12/08 14:51:36 fgsch Exp $ */
/*
* Copyright (c) 1995-1998 John Birrell <jb@cimlogic.com.au>
* All rights reserved.
@@ -60,18 +60,6 @@ dequeue_signals(void);
static inline void
thread_run_switch_hook(pthread_t thread_out, pthread_t thread_in);
-static void
-_thread_check_cancel()
-{
- if (!(_thread_run->flags & PTHREAD_FLAGS_CANCELPT) &&
- (_thread_run->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS))
- /*
- * Check if an async-cancellable thread
- * has been cancelled.
- */
- _thread_cancellation_point();
-}
-
void
_thread_kern_sched(struct sigcontext * scp)
{
@@ -551,7 +539,13 @@ _thread_kern_sched(struct sigcontext * scp)
thread_run_switch_hook(_last_user_thread,
_thread_run);
}
- _thread_check_cancel();
+
+ if (((curthread->cancelflags &
+ PTHREAD_AT_CANCEL_POINT) == 0) &&
+ ((curthread->cancelflags &
+ PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
+ pthread_testcancel();
+
_thread_sys_sigreturn(&_thread_run->saved_sigcontext);
} else {
/*
@@ -565,7 +559,11 @@ _thread_kern_sched(struct sigcontext * scp)
_thread_run);
}
- _thread_check_cancel();
+ if (((curthread->cancelflags &
+ PTHREAD_AT_CANCEL_POINT) == 0) &&
+ ((curthread->cancelflags &
+ PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
+ pthread_testcancel();
return;
}
@@ -1064,6 +1062,14 @@ _thread_kern_sig_undefer(void)
curthread->sig_defer_count = 0;
}
+ /*
+ * Check for asynchronous cancellation before delivering any
+ * pending signals:
+ */
+ if (((curthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) &&
+ ((curthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
+ pthread_testcancel();
+
/* Yield the CPU if necessary: */
if (need_resched || curthread->yield_on_sig_undefer != 0) {
curthread->yield_on_sig_undefer = 0;