Date: Mon, 21 Oct 2002 00:15:14 +0700 From: Max Khon <fjoe@iclub.nsu.ru> To: freebsd-stable@freebsd.org, freebsd-java@freebsd.org Subject: libc_r MFC Message-ID: <20021021001514.A38080@iclub.nsu.ru>
next in thread | raw e-mail | index | archive | help
--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: inline
hi, there!
Please test attached patch. It contains MFC of signal handling,
thread suspension and a couple of bug fixes.
I have succesfully run Java2D demo and JBuilder 7 with hotspot (compiler2)
built from ports/java/jdk13 with these patches.
/fjoe
--UlVJffcvxoiEqYs2
Content-Type: text/plain; charset=us-ascii
Content-Disposition: attachment; filename=current-diffs
Index: include/pthread_np.h
===================================================================
RCS file: /home/ncvs/src/include/pthread_np.h,v
retrieving revision 1.7.2.2
diff -u -p -r1.7.2.2 pthread_np.h
--- include/pthread_np.h 15 Oct 2002 16:52:04 -0000 1.7.2.2
+++ include/pthread_np.h 20 Oct 2002 15:50:46 -0000
@@ -46,8 +46,10 @@ __BEGIN_DECLS
int pthread_attr_setcreatesuspend_np __P((pthread_attr_t *));
int pthread_main_np __P((void));
int pthread_multi_np __P((void));
+void pthread_resume_all_np __P((void));
int pthread_resume_np __P((pthread_t));
int pthread_single_np __P((void));
+void pthread_suspend_all_np __P((void));
int pthread_suspend_np __P((pthread_t));
int pthread_mutexattr_getkind_np __P((pthread_mutexattr_t));
int pthread_mutexattr_setkind_np __P((pthread_mutexattr_t *, int));
Index: lib/libc_r/uthread/pthread_private.h
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/pthread_private.h,v
retrieving revision 1.36.2.20
diff -u -p -r1.36.2.20 pthread_private.h
--- lib/libc_r/uthread/pthread_private.h 17 Oct 2002 19:37:33 -0000 1.36.2.20
+++ lib/libc_r/uthread/pthread_private.h 20 Oct 2002 14:44:06 -0000
@@ -188,14 +188,15 @@
if ((thrd)->state != newstate) { \
if ((thrd)->state == PS_RUNNING) { \
PTHREAD_PRIOQ_REMOVE(thrd); \
+ PTHREAD_SET_STATE(thrd, newstate); \
PTHREAD_WAITQ_INSERT(thrd); \
} else if (newstate == PS_RUNNING) { \
PTHREAD_WAITQ_REMOVE(thrd); \
+ PTHREAD_SET_STATE(thrd, newstate); \
PTHREAD_PRIOQ_INSERT_TAIL(thrd); \
} \
} \
_thread_kern_new_state = 0; \
- PTHREAD_SET_STATE(thrd, newstate); \
} while (0)
#else
#define PTHREAD_ASSERT(cond, msg)
@@ -395,18 +396,6 @@ struct pthread_attr {
#define PTHREAD_CREATE_SUSPENDED 1
/*
- * Additional state for a thread suspended with pthread_suspend_np().
- */
-enum pthread_susp {
- SUSP_NO, /* Not suspended. */
- SUSP_YES, /* Suspended. */
- SUSP_JOIN, /* Suspended, joining. */
- SUSP_NOWAIT, /* Suspended, was in a mutex or condition queue. */
- SUSP_MUTEX_WAIT,/* Suspended, still in a mutex queue. */
- SUSP_COND_WAIT /* Suspended, still in a condition queue. */
-};
-
-/*
* Miscellaneous definitions.
*/
#define PTHREAD_STACK_DEFAULT 65536
@@ -604,33 +593,8 @@ struct join_status {
};
/*
- * Normally thread contexts are stored as jmp_bufs via _setjmp()/_longjmp(),
- * but they may also be sigjmp_buf and ucontext_t. When a thread is
- * interrupted by a signal, it's context is saved as a ucontext_t. An
- * application is also free to use [_]longjmp()/[_]siglongjmp() to jump
- * between contexts within the same thread. Future support will also
- * include setcontext()/getcontext().
- *
- * Define an enumerated type that can identify the 4 different context
- * types.
- */
-typedef enum {
- CTX_JB_NOSIG, /* context is jmp_buf without saved sigset */
- CTX_JB, /* context is jmp_buf (with saved sigset) */
- CTX_SJB, /* context is sigjmp_buf (with saved sigset) */
- CTX_UC /* context is ucontext_t (with saved sigset) */
-} thread_context_t;
-
-/*
- * There are 2 basic contexts that a frame may contain at any
- * one time:
- *
- * o ctx - The context that the thread should return to after normal
- * completion of the signal handler.
- * o sig_jb - The context just before the signal handler is invoked.
- * Attempts at abnormal returns from user supplied signal handlers
- * will return back to the signal context to perform any necessary
- * cleanup.
+ * The frame that is added to the top of a threads stack when setting up
+ * up the thread to run a signal handler.
*/
struct pthread_signal_frame {
/*
@@ -639,19 +603,12 @@ struct pthread_signal_frame {
struct pthread_state_data saved_state;
/*
- * Threads return context; ctxtype identifies the type of context.
- * For signal frame 0, these point to the context storage area
- * within the pthread structure. When handling signals (frame > 0),
- * these point to a context storage area that is allocated off the
- * threads stack.
+ * Threads return context; we use only jmp_buf's for now.
*/
union {
jmp_buf jb;
- sigjmp_buf sigjb;
ucontext_t uc;
} ctx;
- thread_context_t ctxtype;
- int longjmp_val;
int signo; /* signal, arg 1 to sighandler */
int sig_has_args; /* use signal args if true */
ucontext_t uc;
@@ -692,15 +649,12 @@ struct pthread {
struct pthread_attr attr;
/*
- * Threads return context; ctxtype identifies the type of context.
+ * Threads return context; we use only jmp_buf's for now.
*/
union {
jmp_buf jb;
- sigjmp_buf sigjb;
ucontext_t uc;
} ctx;
- thread_context_t ctxtype;
- int longjmp_val;
/*
* Used for tracking delivery of signal handlers.
@@ -716,8 +670,6 @@ struct pthread {
#define PTHREAD_CANCEL_NEEDED 0x0010
int cancelflags;
- enum pthread_susp suspended;
-
thread_continuation_t continuation;
/*
@@ -759,7 +711,7 @@ struct pthread {
int error;
/*
- * THe joiner is the thread that is joining to this thread. The
+ * The joiner is the thread that is joining to this thread. The
* join status keeps track of a join operation to another thread.
*/
struct pthread *joiner;
@@ -834,7 +786,8 @@ struct pthread {
#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_SUSPENDED 0x0200 /* thread is suspended */
+#define PTHREAD_FLAGS_TRACE 0x0400 /* for debugging purposes */
#define PTHREAD_FLAGS_IN_SYNCQ \
(PTHREAD_FLAGS_IN_CONDQ | PTHREAD_FLAGS_IN_MUTEXQ)
@@ -917,17 +870,6 @@ SCLASS struct pthread * volatile _last
;
#endif
-/*
- * Ptr to the thread running in single-threaded mode or NULL if
- * running multi-threaded (default POSIX behaviour).
- */
-SCLASS struct pthread * volatile _thread_single
-#ifdef GLOBAL_PTHREAD_PRIVATE
-= NULL;
-#else
-;
-#endif
-
/* List of all threads: */
SCLASS TAILQ_HEAD(, pthread) _thread_list
#ifdef GLOBAL_PTHREAD_PRIVATE
@@ -1145,9 +1087,6 @@ SCLASS volatile int _sigq_check_reqd
#endif
;
-/* The signal stack. */
-SCLASS struct sigaltstack _thread_sigstack;
-
/* Thread switch hook. */
SCLASS pthread_switch_routine_t _sched_switch_hook
#ifdef GLOBAL_PTHREAD_PRIVATE
@@ -1284,9 +1223,15 @@ void _thread_enter_cancellation_point(vo
void _thread_leave_cancellation_point(void);
void _thread_cancellation_point(void);
+/* #include <aio.h> */
+#ifdef _SYS_AIO_H_
+int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *);
+#endif
+
/* #include <sys/event.h> */
#ifdef _SYS_EVENT_H_
-int __sys_kevent(int, const struct kevent *, int, struct kevent *, int, const struct timespec *);
+int __sys_kevent(int, const struct kevent *, int, struct kevent *,
+ int, const struct timespec *);
#endif
/* #include <sys/ioctl.h> */
@@ -1340,11 +1285,6 @@ ssize_t __sys_writev(int, const struct i
/* #include <sys/wait.h> */
#ifdef WNOHANG
pid_t __sys_wait4(pid_t, int *, int, struct rusage *);
-#endif
-
-/* #include <aio.h> */
-#ifdef _SYS_AIO_H_
-int __sys_aio_suspend(const struct aiocb * const[], int, const struct timespec *);
#endif
/* #include <dirent.h> */
Index: lib/libc_r/uthread/uthread_cancel.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_cancel.c,v
retrieving revision 1.3.2.8
diff -u -p -r1.3.2.8 uthread_cancel.c
--- lib/libc_r/uthread/uthread_cancel.c 17 Oct 2002 19:37:33 -0000 1.3.2.8
+++ lib/libc_r/uthread/uthread_cancel.c 20 Oct 2002 14:43:55 -0000
@@ -61,8 +61,7 @@ pthread_cancel(pthread_t pthread)
case PS_JOIN:
/*
- * Disconnect the thread from the joinee and
- * detach:
+ * Disconnect the thread from the joinee:
*/
if (pthread->join_status.thread != NULL) {
pthread->join_status.thread->joiner
@@ -74,20 +73,6 @@ pthread_cancel(pthread_t pthread)
break;
case PS_SUSPENDED:
- if (pthread->suspended == SUSP_NO ||
- pthread->suspended == SUSP_YES ||
- pthread->suspended == SUSP_JOIN ||
- pthread->suspended == SUSP_NOWAIT) {
- /*
- * This thread isn't in any scheduling
- * queues; just change it's state:
- */
- pthread->cancelflags |=
- PTHREAD_CANCELLING;
- PTHREAD_SET_STATE(pthread, PS_RUNNING);
- break;
- }
- /* FALLTHROUGH */
case PS_MUTEX_WAIT:
case PS_COND_WAIT:
case PS_FDLR_WAIT:
@@ -105,7 +90,7 @@ pthread_cancel(pthread_t pthread)
*/
pthread->interrupted = 1;
pthread->cancelflags |= PTHREAD_CANCEL_NEEDED;
- PTHREAD_NEW_STATE(pthread,PS_RUNNING);
+ PTHREAD_NEW_STATE(pthread, PS_RUNNING);
pthread->continuation = finish_cancellation;
break;
Index: lib/libc_r/uthread/uthread_cond.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_cond.c,v
retrieving revision 1.22.2.7
diff -u -p -r1.22.2.7 uthread_cond.c
--- lib/libc_r/uthread/uthread_cond.c 17 Oct 2002 19:37:33 -0000 1.22.2.7
+++ lib/libc_r/uthread/uthread_cond.c 20 Oct 2002 14:43:55 -0000
@@ -516,15 +516,9 @@ pthread_cond_signal(pthread_cond_t * con
if ((pthread = cond_queue_deq(*cond)) != NULL) {
/*
- * Unless the thread is currently suspended,
- * allow it to run. If the thread is suspended,
- * make a note that the thread isn't in a wait
- * queue any more.
+ * Wake up the signaled thread:
*/
- if (pthread->state != PS_SUSPENDED)
- PTHREAD_NEW_STATE(pthread,PS_RUNNING);
- else
- pthread->suspended = SUSP_NOWAIT;
+ PTHREAD_NEW_STATE(pthread, PS_RUNNING);
}
/* Check for no more waiters: */
@@ -588,15 +582,9 @@ pthread_cond_broadcast(pthread_cond_t *
*/
while ((pthread = cond_queue_deq(*cond)) != NULL) {
/*
- * Unless the thread is currently suspended,
- * allow it to run. If the thread is suspended,
- * make a note that the thread isn't in a wait
- * queue any more.
+ * Wake up the signaled thread:
*/
- if (pthread->state != PS_SUSPENDED)
- PTHREAD_NEW_STATE(pthread,PS_RUNNING);
- else
- pthread->suspended = SUSP_NOWAIT;
+ PTHREAD_NEW_STATE(pthread, PS_RUNNING);
}
/* There are no more waiting threads: */
Index: lib/libc_r/uthread/uthread_create.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_create.c,v
retrieving revision 1.24.2.4
diff -u -p -r1.24.2.4 uthread_create.c
--- lib/libc_r/uthread/uthread_create.c 17 Oct 2002 19:37:35 -0000 1.24.2.4
+++ lib/libc_r/uthread/uthread_create.c 20 Oct 2002 14:44:06 -0000
@@ -53,16 +53,11 @@ int _thread_next_offset = OFF(tle.tqe_
int _thread_uniqueid_offset = OFF(uniqueid);
int _thread_state_offset = OFF(state);
int _thread_name_offset = OFF(name);
-int _thread_ctxtype_offset = OFF(ctxtype);
int _thread_ctx_offset = OFF(ctx);
#undef OFF
int _thread_PS_RUNNING_value = PS_RUNNING;
int _thread_PS_DEAD_value = PS_DEAD;
-int _thread_CTX_JB_NOSIG_value = CTX_JB_NOSIG;
-int _thread_CTX_JB_value = CTX_JB;
-int _thread_CTX_SJB_value = CTX_SJB;
-int _thread_CTX_UC_value = CTX_UC;
int
pthread_create(pthread_t * thread, const pthread_attr_t * attr,
@@ -202,9 +197,6 @@ pthread_create(pthread_t * thread, const
(long)new_thread->stack + pattr->stacksize_attr
- sizeof(double));
- /* Initialize the rest of the frame: */
- new_thread->ctxtype = CTX_JB_NOSIG;
-
/* Copy the thread attributes: */
memcpy(&new_thread->attr, pattr, sizeof(struct pthread_attr));
@@ -269,9 +261,10 @@ pthread_create(pthread_t * thread, const
/* Add the thread to the linked list of all threads: */
TAILQ_INSERT_HEAD(&_thread_list, new_thread, tle);
- if (pattr->suspend == PTHREAD_CREATE_SUSPENDED)
+ if (pattr->suspend == PTHREAD_CREATE_SUSPENDED) {
+ new_thread->flags |= PTHREAD_FLAGS_SUSPENDED;
new_thread->state = PS_SUSPENDED;
- else {
+ } else {
new_thread->state = PS_RUNNING;
PTHREAD_PRIOQ_INSERT_TAIL(new_thread);
}
Index: lib/libc_r/uthread/uthread_exit.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_exit.c,v
retrieving revision 1.16.2.7
diff -u -p -r1.16.2.7 uthread_exit.c
--- lib/libc_r/uthread/uthread_exit.c 17 Oct 2002 19:37:35 -0000 1.16.2.7
+++ lib/libc_r/uthread/uthread_exit.c 20 Oct 2002 14:43:55 -0000
@@ -210,22 +210,8 @@ pthread_exit(void *status)
pthread = curthread->joiner;
curthread->joiner = NULL;
- switch (pthread->suspended) {
- case SUSP_JOIN:
- /*
- * The joining thread is suspended. Change the
- * suspension state to make the thread runnable when it
- * is resumed:
- */
- pthread->suspended = SUSP_NO;
- break;
- case SUSP_NO:
- /* Make the joining thread runnable: */
- PTHREAD_NEW_STATE(pthread, PS_RUNNING);
- break;
- default:
- PANIC("Unreachable code reached");
- }
+ /* Make the joining thread runnable: */
+ PTHREAD_NEW_STATE(pthread, PS_RUNNING);
/* Set the return value for the joining thread: */
pthread->join_status.ret = curthread->ret;
Index: lib/libc_r/uthread/uthread_gc.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_gc.c,v
retrieving revision 1.11.2.4
diff -u -p -r1.11.2.4 uthread_gc.c
--- lib/libc_r/uthread/uthread_gc.c 17 Oct 2002 19:44:38 -0000 1.11.2.4
+++ lib/libc_r/uthread/uthread_gc.c 20 Oct 2002 14:43:55 -0000
@@ -123,13 +123,13 @@ _thread_gc(pthread_addr_t arg)
* Check if this thread has detached:
*/
else if ((pthread->attr.flags &
- PTHREAD_DETACHED) != 0) {
+ PTHREAD_DETACHED) != 0) {
/* Remove this thread from the dead list: */
TAILQ_REMOVE(&_dead_list, pthread, dle);
/*
* Check if the stack was not specified by
- * the caller to pthread_create and has not
+ * the caller to pthread_create() and has not
* been destroyed yet:
*/
if (pthread->attr.stackaddr_attr == NULL &&
@@ -170,7 +170,7 @@ _thread_gc(pthread_addr_t arg)
* not destroy it.
*
* Check if the stack was not specified by
- * the caller to pthread_create and has not
+ * the caller to pthread_create() and has not
* been destroyed yet:
*/
if (pthread->attr.stackaddr_attr == NULL &&
Index: lib/libc_r/uthread/uthread_init.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_init.c,v
retrieving revision 1.23.2.9
diff -u -p -r1.23.2.9 uthread_init.c
--- lib/libc_r/uthread/uthread_init.c 17 Oct 2002 19:37:36 -0000 1.23.2.9
+++ lib/libc_r/uthread/uthread_init.c 20 Oct 2002 15:12:33 -0000
@@ -147,20 +147,21 @@ _thread_init(void)
PANIC("Can't open console");
if (setlogin("root") == -1)
PANIC("Can't set login to root");
- if (__sys_ioctl(fd,TIOCSCTTY, (char *) NULL) == -1)
+ if (__sys_ioctl(fd, TIOCSCTTY, (char *) NULL) == -1)
PANIC("Can't set controlling terminal");
- if (__sys_dup2(fd,0) == -1 ||
- __sys_dup2(fd,1) == -1 ||
- __sys_dup2(fd,2) == -1)
+ if (__sys_dup2(fd, 0) == -1 ||
+ __sys_dup2(fd, 1) == -1 ||
+ __sys_dup2(fd, 2) == -1)
PANIC("Can't dup2");
}
/* Get the standard I/O flags before messing with them : */
- for (i = 0; i < 3; i++)
+ for (i = 0; i < 3; i++) {
if (((_pthread_stdio_flags[i] =
- __sys_fcntl(i,F_GETFL, NULL)) == -1) &&
+ __sys_fcntl(i, F_GETFL, NULL)) == -1) &&
(errno != EBADF))
PANIC("Cannot get stdio flags");
+ }
/*
* Create a pipe that is written to by the signal handler to prevent
@@ -170,8 +171,21 @@ _thread_init(void)
/* Cannot create pipe, so abort: */
PANIC("Cannot create kernel pipe");
}
+
+ /*
+ * Make sure the pipe does not get in the way of stdio:
+ */
+ for (i = 0; i < 2; i++) {
+ if (_thread_kern_pipe[i] < 3) {
+ fd = __sys_fcntl(_thread_kern_pipe[i], F_DUPFD, 3);
+ if (fd == -1)
+ PANIC("Cannot create kernel pipe");
+ __sys_close(_thread_kern_pipe[i]);
+ _thread_kern_pipe[i] = fd;
+ }
+ }
/* Get the flags for the read pipe: */
- else if ((flags = __sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
+ if ((flags = __sys_fcntl(_thread_kern_pipe[0], F_GETFL, NULL)) == -1) {
/* Abort this application: */
PANIC("Cannot get kernel read pipe flags");
}
@@ -231,7 +245,7 @@ _thread_init(void)
mib[1] = KERN_USRSTACK;
len = sizeof (int);
if (sysctl(mib, 2, &_usrstack, &len, NULL, 0) == -1)
- _usrstack = USRSTACK;
+ _usrstack = (void *)USRSTACK;
/*
* Create a red zone below the main stack. All other stacks are
* constrained to a maximum size by the paramters passed to
@@ -291,7 +305,6 @@ _thread_init(void)
/* Initialize the initial context: */
_thread_initial->curframe = NULL;
- _thread_initial->ctxtype = CTX_JB_NOSIG;
/* Initialise the rest of the fields: */
_thread_initial->poll_data.nfds = 0;
@@ -316,17 +329,6 @@ _thread_init(void)
/* Clear the signal queue: */
memset(_thread_sigq, 0, sizeof(_thread_sigq));
-
- /*
- * Create and install an alternate signal stack of
- * the recommended size:
- */
- _thread_sigstack.ss_sp = malloc(SIGSTKSZ);
- _thread_sigstack.ss_size = SIGSTKSZ;
- _thread_sigstack.ss_flags = 0;
- if ((_thread_sigstack.ss_sp == NULL) ||
- (__sys_sigaltstack(&_thread_sigstack, NULL) != 0))
- PANIC("Unable to install alternate signal stack");
/* Enter a loop to get the existing signal status: */
for (i = 1; i < NSIG; i++) {
Index: lib/libc_r/uthread/uthread_kern.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_kern.c,v
retrieving revision 1.28.2.12
diff -u -p -r1.28.2.12 uthread_kern.c
--- lib/libc_r/uthread/uthread_kern.c 17 Oct 2002 20:09:23 -0000 1.28.2.12
+++ lib/libc_r/uthread/uthread_kern.c 20 Oct 2002 16:04:03 -0000
@@ -101,7 +101,7 @@ _thread_kern_sched_frame(struct pthread_
void
-_thread_kern_sched(ucontext_t *scp)
+_thread_kern_sched(ucontext_t *ucp)
{
struct pthread *curthread = _get_curthread();
@@ -113,50 +113,61 @@ _thread_kern_sched(ucontext_t *scp)
_thread_kern_in_sched = 1;
/* Check if this function was called from the signal handler: */
- if (scp != NULL) {
+ if (ucp != NULL) {
+ /* XXX - Save FP registers? */
+ FP_SAVE_UC(ucp);
called_from_handler = 1;
DBG_MSG("Entering scheduler due to signal\n");
- } else {
- /* Save the state of the current thread: */
- if (_setjmp(curthread->ctx.jb) == 0) {
- /* Flag the jump buffer was the last state saved: */
- curthread->ctxtype = CTX_JB_NOSIG;
- curthread->longjmp_val = 1;
- } else {
- DBG_MSG("Returned from ___longjmp, thread %p\n",
- curthread);
- /*
- * This point is reached when a longjmp() is called
- * to restore the state of a thread.
- *
- * This is the normal way out of the scheduler.
- */
- _thread_kern_in_sched = 0;
+ }
- if (curthread->sig_defer_count == 0) {
- if (((curthread->cancelflags &
- PTHREAD_AT_CANCEL_POINT) == 0) &&
- ((curthread->cancelflags &
- PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
- /*
- * Cancellations override signals.
- *
- * Stick a cancellation point at the
- * start of each async-cancellable
- * thread's resumption.
- *
- * We allow threads woken at cancel
- * points to do their own checks.
- */
- pthread_testcancel();
- }
+ /* Save the state of the current thread: */
+ if (_setjmp(curthread->ctx.jb) != 0) {
+ DBG_MSG("Returned from ___longjmp, thread %p\n",
+ curthread);
+ /*
+ * This point is reached when a longjmp() is called
+ * to restore the state of a thread.
+ *
+ * This is the normal way out of the scheduler.
+ */
+ _thread_kern_in_sched = 0;
- if (_sched_switch_hook != NULL) {
- /* Run the installed switch hook: */
- thread_run_switch_hook(_last_user_thread,
- curthread);
- }
+ if (curthread->sig_defer_count == 0) {
+ if (((curthread->cancelflags &
+ PTHREAD_AT_CANCEL_POINT) == 0) &&
+ ((curthread->cancelflags &
+ PTHREAD_CANCEL_ASYNCHRONOUS) != 0))
+ /*
+ * Cancellations override signals.
+ *
+ * Stick a cancellation point at the
+ * start of each async-cancellable
+ * thread's resumption.
+ *
+ * We allow threads woken at cancel
+ * points to do their own checks.
+ */
+ pthread_testcancel();
+ }
+
+ if (_sched_switch_hook != NULL) {
+ /* Run the installed switch hook: */
+ thread_run_switch_hook(_last_user_thread, curthread);
+ }
+ if (ucp == NULL)
return;
+ else {
+ /* XXX - Restore FP registers? */
+ FP_RESTORE_UC(ucp);
+
+ /*
+ * Set the process signal mask in the context; it
+ * could have changed by the handler.
+ */
+ ucp->uc_sigmask = _process_sigmask;
+
+ /* Resume the interrupted thread: */
+ sigreturn(ucp);
}
}
/* Switch to the thread scheduler: */
@@ -191,20 +202,12 @@ _thread_kern_scheduler(void)
called_from_handler = 0;
/*
- * The signal handler should have saved the state of
- * the current thread. Restore the process signal
- * mask.
+ * We were called from a signal handler; restore the process
+ * signal mask.
*/
if (__sys_sigprocmask(SIG_SETMASK,
&_process_sigmask, NULL) != 0)
PANIC("Unable to restore process mask after signal");
-
- /*
- * Since the signal handler didn't return normally, we
- * have to tell the kernel to reuse the signal stack.
- */
- if (__sys_sigaltstack(&_thread_sigstack, NULL) != 0)
- PANIC("Unable to restore alternate signal stack");
}
/*
@@ -582,42 +585,11 @@ _thread_kern_scheduler(void)
/*
* Continue the thread at its current frame:
*/
- switch(curthread->ctxtype) {
- case CTX_JB_NOSIG:
- ___longjmp(curthread->ctx.jb,
- curthread->longjmp_val);
- break;
- case CTX_JB:
- __longjmp(curthread->ctx.jb,
- curthread->longjmp_val);
- break;
- case CTX_SJB:
- __siglongjmp(curthread->ctx.sigjb,
- curthread->longjmp_val);
- break;
- case CTX_UC:
- /* XXX - Restore FP regsisters? */
- FP_RESTORE_UC(&curthread->ctx.uc);
-
- /*
- * Do a sigreturn to restart the thread that
- * was interrupted by a signal:
- */
- _thread_kern_in_sched = 0;
-
#if NOT_YET
- _setcontext(&curthread->ctx.uc);
+ _setcontext(&curthread->ctx.uc);
#else
- /*
- * Ensure the process signal mask is set
- * correctly:
- */
- curthread->ctx.uc.uc_sigmask =
- _process_sigmask;
- sigreturn(&curthread->ctx.uc);
+ ___longjmp(curthread->ctx.jb, 1);
#endif
- break;
- }
/* This point should not be reached. */
PANIC("Thread has returned from sigreturn or longjmp");
}
Index: lib/libc_r/uthread/uthread_multi_np.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_multi_np.c,v
retrieving revision 1.4
diff -u -p -r1.4 uthread_multi_np.c
--- lib/libc_r/uthread/uthread_multi_np.c 12 Jan 2000 09:28:46 -0000 1.4
+++ lib/libc_r/uthread/uthread_multi_np.c 20 Oct 2002 14:43:55 -0000
@@ -34,13 +34,18 @@
#include <string.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
-#include "pthread_private.h"
+#include <pthread_np.h>
int
pthread_multi_np()
{
+
/* Return to multi-threaded scheduling mode: */
- _thread_single = NULL;
- return(0);
+ /*
+ * XXX - Do we want to do this?
+ * __is_threaded = 1;
+ */
+ pthread_resume_all_np();
+ return (0);
}
#endif
Index: lib/libc_r/uthread/uthread_mutex.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_mutex.c,v
retrieving revision 1.20.2.7
diff -u -p -r1.20.2.7 uthread_mutex.c
--- lib/libc_r/uthread/uthread_mutex.c 17 Oct 2002 19:37:37 -0000 1.20.2.7
+++ lib/libc_r/uthread/uthread_mutex.c 20 Oct 2002 16:25:48 -0000
@@ -793,21 +793,9 @@ mutex_unlock_common(pthread_mutex_t * mu
*/
if (((*mutex)->m_owner =
mutex_queue_deq(*mutex)) != NULL) {
- /*
- * Unless the new owner of the mutex is
- * currently suspended, allow the owner
- * to run. If the thread is suspended,
- * make a note that the thread isn't in
- * a wait queue any more.
- */
- if (((*mutex)->m_owner->state !=
- PS_SUSPENDED)) {
- PTHREAD_NEW_STATE((*mutex)->m_owner,
- PS_RUNNING);
- } else {
- (*mutex)->m_owner->suspended =
- SUSP_NOWAIT;
- }
+ /* Make the new owner runnable: */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,
+ PS_RUNNING);
/*
* Add the mutex to the threads list of
@@ -925,20 +913,10 @@ mutex_unlock_common(pthread_mutex_t * mu
(*mutex)->m_prio;
/*
- * Unless the new owner of the mutex is
- * currently suspended, allow the owner
- * to run. If the thread is suspended,
- * make a note that the thread isn't in
- * a wait queue any more.
- */
- if (((*mutex)->m_owner->state !=
- PS_SUSPENDED)) {
- PTHREAD_NEW_STATE((*mutex)->m_owner,
- PS_RUNNING);
- } else {
- (*mutex)->m_owner->suspended =
- SUSP_NOWAIT;
- }
+ * Make the new owner runnable:
+ */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,
+ PS_RUNNING);
}
}
break;
@@ -1054,20 +1032,10 @@ mutex_unlock_common(pthread_mutex_t * mu
(*mutex)->m_prio;
/*
- * Unless the new owner of the mutex is
- * currently suspended, allow the owner
- * to run. If the thread is suspended,
- * make a note that the thread isn't in
- * a wait queue any more.
- */
- if (((*mutex)->m_owner->state !=
- PS_SUSPENDED)) {
- PTHREAD_NEW_STATE((*mutex)->m_owner,
- PS_RUNNING);
- } else {
- (*mutex)->m_owner->suspended =
- SUSP_NOWAIT;
- }
+ * Make the new owner runnable:
+ */
+ PTHREAD_NEW_STATE((*mutex)->m_owner,
+ PS_RUNNING);
}
}
break;
Index: lib/libc_r/uthread/uthread_priority_queue.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_priority_queue.c,v
retrieving revision 1.5.2.2
diff -u -p -r1.5.2.2 uthread_priority_queue.c
--- lib/libc_r/uthread/uthread_priority_queue.c 17 Oct 2002 19:37:38 -0000 1.5.2.2
+++ lib/libc_r/uthread/uthread_priority_queue.c 20 Oct 2002 14:43:55 -0000
@@ -165,52 +165,74 @@ _pq_remove(pq_queue_t *pq, pthread_t pth
void
_pq_insert_head(pq_queue_t *pq, pthread_t pthread)
{
- int prio = pthread->active_priority;
+ int prio;
/*
- * Make some assertions when debugging is enabled:
+ * Don't insert suspended threads into the priority queue.
+ * The caller is responsible for setting the threads state.
*/
- _PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active");
- _PQ_SET_ACTIVE();
- _PQ_ASSERT_NOT_QUEUED(pthread,
- "_pq_insert_head: Already in priority queue");
- _PQ_ASSERT_PROTECTED("_pq_insert_head: prioq not protected!");
-
- TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe);
- if (pq->pq_lists[prio].pl_queued == 0)
- /* Insert the list into the priority queue: */
- pq_insert_prio_list(pq, prio);
+ if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) {
+ /* Make sure the threads state is suspended. */
+ if (pthread->state != PS_SUSPENDED)
+ PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
+ } else {
+ /*
+ * Make some assertions when debugging is enabled:
+ */
+ _PQ_ASSERT_INACTIVE("_pq_insert_head: pq_active");
+ _PQ_SET_ACTIVE();
+ _PQ_ASSERT_NOT_QUEUED(pthread,
+ "_pq_insert_head: Already in priority queue");
+ _PQ_ASSERT_PROTECTED("_pq_insert_head: prioq not protected!");
+
+ prio = pthread->active_priority;
+ TAILQ_INSERT_HEAD(&pq->pq_lists[prio].pl_head, pthread, pqe);
+ if (pq->pq_lists[prio].pl_queued == 0)
+ /* Insert the list into the priority queue: */
+ pq_insert_prio_list(pq, prio);
- /* Mark this thread as being in the priority queue. */
- pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
+ /* Mark this thread as being in the priority queue. */
+ pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
- _PQ_CLEAR_ACTIVE();
+ _PQ_CLEAR_ACTIVE();
+ }
}
void
_pq_insert_tail(pq_queue_t *pq, pthread_t pthread)
{
- int prio = pthread->active_priority;
+ int prio;
/*
- * Make some assertions when debugging is enabled:
+ * Don't insert suspended threads into the priority queue.
+ * The caller is responsible for setting the threads state.
*/
- _PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active");
- _PQ_SET_ACTIVE();
- _PQ_ASSERT_NOT_QUEUED(pthread,
- "_pq_insert_tail: Already in priority queue");
- _PQ_ASSERT_PROTECTED("_pq_insert_tail: prioq not protected!");
-
- TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe);
- if (pq->pq_lists[prio].pl_queued == 0)
- /* Insert the list into the priority queue: */
- pq_insert_prio_list(pq, prio);
+ if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) {
+ /* Make sure the threads state is suspended. */
+ if (pthread->state != PS_SUSPENDED)
+ PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
+ } else {
+ /*
+ * Make some assertions when debugging is enabled:
+ */
+ _PQ_ASSERT_INACTIVE("_pq_insert_tail: pq_active");
+ _PQ_SET_ACTIVE();
+ _PQ_ASSERT_NOT_QUEUED(pthread,
+ "_pq_insert_tail: Already in priority queue");
+ _PQ_ASSERT_PROTECTED("_pq_insert_tail: prioq not protected!");
+
+ prio = pthread->active_priority;
+ TAILQ_INSERT_TAIL(&pq->pq_lists[prio].pl_head, pthread, pqe);
+ if (pq->pq_lists[prio].pl_queued == 0)
+ /* Insert the list into the priority queue: */
+ pq_insert_prio_list(pq, prio);
- /* Mark this thread as being in the priority queue. */
- pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
+ /* Mark this thread as being in the priority queue. */
+ pthread->flags |= PTHREAD_FLAGS_IN_PRIOQ;
- _PQ_CLEAR_ACTIVE();
+ _PQ_CLEAR_ACTIVE();
+ }
}
@@ -238,6 +260,17 @@ _pq_first(pq_queue_t *pq)
/* Mark the list as not being in the queue: */
pql->pl_queued = 0;
+ } else if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0) {
+ /*
+ * This thread is suspended; remove it from the
+ * list and ensure its state is suspended.
+ */
+ TAILQ_REMOVE(&pql->pl_head, pthread, pqe);
+ PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
+
+ /* This thread is now longer in the priority queue. */
+ pthread->flags &= ~PTHREAD_FLAGS_IN_PRIOQ;
+ pthread = NULL;
}
}
Index: lib/libc_r/uthread/uthread_resume_np.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_resume_np.c,v
retrieving revision 1.7.2.3
diff -u -p -r1.7.2.3 uthread_resume_np.c
--- lib/libc_r/uthread/uthread_resume_np.c 23 Jun 2001 00:47:05 -0000 1.7.2.3
+++ lib/libc_r/uthread/uthread_resume_np.c 20 Oct 2002 14:43:55 -0000
@@ -36,61 +36,75 @@
#include <pthread.h>
#include "pthread_private.h"
+static void resume_common(struct pthread *);
+
/* Resume a thread: */
int
pthread_resume_np(pthread_t thread)
{
- int ret;
- enum pthread_susp old_suspended;
+ int ret;
/* Find the thread in the list of active threads: */
if ((ret = _find_thread(thread)) == 0) {
- /* Cancel any pending suspensions: */
- old_suspended = thread->suspended;
- thread->suspended = SUSP_NO;
-
- /* Is it currently suspended? */
- if (thread->state == PS_SUSPENDED) {
- /*
- * Defer signals to protect the scheduling queues
- * from access by the signal handler:
- */
- _thread_kern_sig_defer();
-
- switch (old_suspended) {
- case SUSP_MUTEX_WAIT:
- /* Set the thread's state back. */
- PTHREAD_SET_STATE(thread,PS_MUTEX_WAIT);
- break;
- case SUSP_COND_WAIT:
- /* Set the thread's state back. */
- PTHREAD_SET_STATE(thread,PS_COND_WAIT);
- break;
- case SUSP_JOIN:
- /* Set the thread's state back. */
- PTHREAD_SET_STATE(thread,PS_JOIN);
- break;
- case SUSP_NOWAIT:
- /* Allow the thread to run. */
- PTHREAD_SET_STATE(thread,PS_RUNNING);
- PTHREAD_WAITQ_REMOVE(thread);
- PTHREAD_PRIOQ_INSERT_TAIL(thread);
- break;
- case SUSP_NO:
- case SUSP_YES:
- /* Allow the thread to run. */
- PTHREAD_SET_STATE(thread,PS_RUNNING);
- PTHREAD_PRIOQ_INSERT_TAIL(thread);
- break;
- }
-
- /*
- * Undefer and handle pending signals, yielding if
- * necessary:
- */
- _thread_kern_sig_undefer();
- }
+ /*
+ * Defer signals to protect the scheduling queues
+ * from access by the signal handler:
+ */
+ _thread_kern_sig_defer();
+
+ if ((thread->flags & PTHREAD_FLAGS_SUSPENDED) != 0)
+ resume_common(thread);
+
+ /*
+ * Undefer and handle pending signals, yielding if
+ * necessary:
+ */
+ _thread_kern_sig_undefer();
+ }
+ return (ret);
+}
+
+void
+pthread_resume_all_np(void)
+{
+ struct pthread *curthread = _get_curthread();
+ struct pthread *thread;
+
+ /*
+ * Defer signals to protect the scheduling queues from access
+ * by the signal handler:
+ */
+ _thread_kern_sig_defer();
+
+ TAILQ_FOREACH(thread, &_thread_list, tle) {
+ if ((thread != curthread) &&
+ ((thread->flags & PTHREAD_FLAGS_SUSPENDED) != 0))
+ resume_common(thread);
+ }
+
+ /*
+ * Undefer and handle pending signals, yielding if necessary:
+ */
+ _thread_kern_sig_undefer();
+}
+
+static void
+resume_common(struct pthread *thread)
+{
+ /* Clear the suspend flag: */
+ thread->flags &= ~PTHREAD_FLAGS_SUSPENDED;
+
+ /*
+ * If the thread's state is suspended, that means it is
+ * now runnable but not in any scheduling queue. Set the
+ * state to running and insert it into the run queue.
+ */
+ if (thread->state == PS_SUSPENDED) {
+ PTHREAD_SET_STATE(thread, PS_RUNNING);
+ if (thread->priority_mutex_count > 0)
+ PTHREAD_PRIOQ_INSERT_HEAD(thread);
+ else
+ PTHREAD_PRIOQ_INSERT_TAIL(thread);
}
- return(ret);
}
#endif
Index: lib/libc_r/uthread/uthread_select.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_select.c,v
retrieving revision 1.16.2.4
diff -u -p -r1.16.2.4 uthread_select.c
--- lib/libc_r/uthread/uthread_select.c 17 Oct 2002 19:37:38 -0000 1.16.2.4
+++ lib/libc_r/uthread/uthread_select.c 20 Oct 2002 16:53:00 -0000
@@ -51,7 +51,7 @@ _select(int numfds, fd_set * readfds, fd
struct pthread *curthread = _get_curthread();
struct timespec ts;
int i, ret = 0, f_wait = 1;
- int pfd_index, got_one = 0, fd_count = 0;
+ int pfd_index, got_events = 0, fd_count = 0;
struct pthread_poll_data data;
if (numfds > _thread_dtablesize) {
@@ -165,13 +165,23 @@ _select(int numfds, fd_set * readfds, fd
* this file descriptor from the fdset if
* the requested event wasn't ready.
*/
- got_one = 0;
+
+ /*
+ * First check for invalid descriptor.
+ * If found, set errno and return -1.
+ */
+ if (data.fds[i].revents & POLLNVAL) {
+ errno = EBADF;
+ return -1;
+ }
+
+ got_events = 0;
if (readfds != NULL) {
if (FD_ISSET(data.fds[i].fd, readfds)) {
if ((data.fds[i].revents & (POLLIN
| POLLRDNORM | POLLERR
| POLLHUP | POLLNVAL)) != 0)
- got_one = 1;
+ got_events++;
else
FD_CLR(data.fds[i].fd, readfds);
}
@@ -181,7 +191,7 @@ _select(int numfds, fd_set * readfds, fd
if ((data.fds[i].revents & (POLLOUT
| POLLWRNORM | POLLWRBAND | POLLERR
| POLLHUP | POLLNVAL)) != 0)
- got_one = 1;
+ got_events++;
else
FD_CLR(data.fds[i].fd,
writefds);
@@ -190,16 +200,15 @@ _select(int numfds, fd_set * readfds, fd
if (exceptfds != NULL) {
if (FD_ISSET(data.fds[i].fd, exceptfds)) {
if (data.fds[i].revents & (POLLRDBAND |
- POLLPRI | POLLHUP | POLLERR |
- POLLNVAL))
- got_one = 1;
+ POLLPRI))
+ got_events++;
else
FD_CLR(data.fds[i].fd,
exceptfds);
}
}
- if (got_one)
- numfds++;
+ if (got_events != 0)
+ numfds+=got_events;
}
ret = numfds;
}
Index: lib/libc_r/uthread/uthread_sig.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sig.c,v
retrieving revision 1.25.2.12
diff -u -p -r1.25.2.12 uthread_sig.c
--- lib/libc_r/uthread/uthread_sig.c 17 Oct 2002 19:37:38 -0000 1.25.2.12
+++ lib/libc_r/uthread/uthread_sig.c 20 Oct 2002 16:10:05 -0000
@@ -48,11 +48,12 @@ static void thread_sig_add(struct pthrea
static void thread_sig_check_state(struct pthread *pthread, int sig);
static struct pthread *thread_sig_find(int sig);
static void thread_sig_handle_special(int sig);
-static void thread_sig_savecontext(struct pthread *pthread, ucontext_t *ucp);
static void thread_sigframe_add(struct pthread *thread, int sig,
int has_args);
static void thread_sigframe_save(struct pthread *thread,
struct pthread_signal_frame *psf);
+static void thread_sig_invoke_handler(int sig, siginfo_t *info,
+ ucontext_t *ucp);
/* #define DEBUG_SIGNAL */
#ifdef DEBUG_SIGNAL
@@ -74,22 +75,13 @@ _thread_sig_handler(int sig, siginfo_t *
{
struct pthread *curthread = _get_curthread();
struct pthread *pthread, *pthread_h;
- void *stackp;
- int in_sched = 0;
+ int in_sched = _thread_kern_in_sched;
char c;
if (ucp == NULL)
PANIC("Thread signal handler received null context");
DBG_MSG("Got signal %d, current thread %p\n", sig, curthread);
- if (_thread_kern_in_sched != 0)
- in_sched = 1;
- else {
- stackp = (void *)GET_STACK_UC(ucp);
- if ((stackp >= _thread_kern_sched_stack) &&
- (stackp <= _thread_kern_sched_stack + SCHED_STACK_SIZE))
- in_sched = 1;
- }
/* Check if an interval timer signal: */
if (sig == _SCHED_SIGNAL) {
/* Update the scheduling clock: */
@@ -110,16 +102,7 @@ _thread_sig_handler(int sig, siginfo_t *
else if (curthread->sig_defer_count > 0)
curthread->yield_on_sig_undefer = 1;
else {
- /*
- * Save the context of the currently running thread:
- */
- thread_sig_savecontext(curthread, ucp);
-
- /*
- * Schedule the next thread. This function is not
- * expected to return because it will do a longjmp
- * instead.
- */
+ /* Schedule the next thread: */
_thread_kern_sched(ucp);
/*
@@ -213,18 +196,30 @@ _thread_sig_handler(int sig, siginfo_t *
thread_sig_handle_special(sig);
pthread_h = NULL;
- if ((pthread = thread_sig_find(sig)) != NULL) {
- DBG_MSG("Got signal %d, adding frame to thread %p\n",
- sig, pthread);
+ if ((pthread = thread_sig_find(sig)) == NULL)
+ DBG_MSG("No thread to handle signal %d\n", sig);
+ else if (pthread == curthread) {
/*
- * A thread was found that can handle the signal.
- * Save the context of the currently running thread
- * so that we can switch to another thread without
- * losing track of where the current thread left off.
- * This also applies if the current thread is the
- * thread to be signaled.
+ * Unblock the signal and restore the process signal
+ * mask in case we don't return from the handler:
*/
- thread_sig_savecontext(curthread, ucp);
+ _thread_sigq[sig - 1].blocked = 0;
+ __sys_sigprocmask(SIG_SETMASK, &_process_sigmask, NULL);
+
+ /* Call the signal handler for the current thread: */
+ thread_sig_invoke_handler(sig, info, ucp);
+
+ /*
+ * Set the process signal mask in the context; it
+ * could have changed by the handler.
+ */
+ ucp->uc_sigmask = _process_sigmask;
+
+ /* Resume the interrupted thread: */
+ sigreturn(ucp);
+ } else {
+ DBG_MSG("Got signal %d, adding frame to thread %p\n",
+ sig, pthread);
/* Setup the target thread to receive the signal: */
thread_sig_add(pthread, sig, /*has_args*/ 1);
@@ -234,8 +229,6 @@ _thread_sig_handler(int sig, siginfo_t *
DBG_MSG("Finished adding frame, head of prio list %p\n",
pthread_h);
}
- else
- DBG_MSG("No thread to handle signal %d\n", sig);
SIG_SET_INACTIVE();
/*
@@ -244,8 +237,8 @@ _thread_sig_handler(int sig, siginfo_t *
* signal and the currently running thread is not in a
* signal handler.
*/
- if ((pthread == curthread) || ((pthread_h != NULL) &&
- (pthread_h->active_priority > curthread->active_priority))) {
+ if ((pthread_h != NULL) &&
+ (pthread_h->active_priority > curthread->active_priority)) {
/* Enter the kernel scheduler: */
_thread_kern_sched(ucp);
}
@@ -258,15 +251,45 @@ _thread_sig_handler(int sig, siginfo_t *
}
static void
-thread_sig_savecontext(struct pthread *pthread, ucontext_t *ucp)
-{
- memcpy(&pthread->ctx.uc, ucp, sizeof(*ucp));
+thread_sig_invoke_handler(int sig, siginfo_t *info, ucontext_t *ucp)
+ {
+ struct pthread *curthread = _get_curthread();
+ void (*sigfunc)(int, siginfo_t *, void *);
+ int saved_seqno;
+ sigset_t saved_sigmask;
- /* XXX - Save FP registers too? */
- FP_SAVE_UC(&pthread->ctx.uc);
+ /* Invoke the signal handler without going through the scheduler:
+ */
+ DBG_MSG("Got signal %d, calling handler for current thread %p\n",
+ sig, curthread);
- /* Mark the context saved as a ucontext: */
- pthread->ctxtype = CTX_UC;
+ /* Save the threads signal mask: */
+ saved_sigmask = curthread->sigmask;
+ saved_seqno = curthread->sigmask_seqno;
+
+ /* Setup the threads signal mask: */
+ SIGSETOR(curthread->sigmask, _thread_sigact[sig - 1].sa_mask);
+ sigaddset(&curthread->sigmask, sig);
+
+ /*
+ * Check that a custom handler is installed and if
+ * the signal is not blocked:
+ */
+ sigfunc = _thread_sigact[sig - 1].sa_sigaction;
+ if (((__sighandler_t *)sigfunc != SIG_DFL) &&
+ ((__sighandler_t *)sigfunc != SIG_IGN)) {
+ if (((_thread_sigact[sig - 1].sa_flags & SA_SIGINFO) != 0) ||
+ (info == NULL))
+ (*(sigfunc))(sig, info, ucp);
+ else
+ (*(sigfunc))(sig, (siginfo_t *)info->si_code, ucp);
+ }
+ /*
+ * Only restore the signal mask if it hasn't been changed by the
+ * application during invocation of the signal handler:
+ */
+ if (curthread->sigmask_seqno == saved_seqno)
+ curthread->sigmask = saved_sigmask;
}
/*
@@ -353,7 +376,8 @@ thread_sig_find(int sig)
return (NULL);
}
else if ((handler_installed != 0) &&
- !sigismember(&pthread->sigmask, sig)) {
+ !sigismember(&pthread->sigmask, sig) &&
+ ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) == 0)) {
if (pthread->state == PS_SIGSUSPEND) {
if (suspended_thread == NULL)
suspended_thread = pthread;
@@ -769,10 +793,17 @@ thread_sig_add(struct pthread *pthread,
/*
* The thread should be removed from all scheduling
* queues at this point. Raise the priority and place
- * the thread in the run queue.
+ * the thread in the run queue. It is also possible
+ * for a signal to be sent to a suspended thread,
+ * mostly via pthread_kill(). If a thread is suspended,
+ * don't insert it into the priority queue; just set
+ * its state to suspended and it will run the signal
+ * handler when it is resumed.
*/
pthread->active_priority |= PTHREAD_SIGNAL_PRIORITY;
- if (thread_is_active == 0)
+ if ((pthread->flags & PTHREAD_FLAGS_SUSPENDED) != 0)
+ PTHREAD_SET_STATE(pthread, PS_SUSPENDED);
+ else if (thread_is_active == 0)
PTHREAD_PRIOQ_INSERT_TAIL(pthread);
}
}
@@ -901,17 +932,13 @@ _thread_sig_send(struct pthread *pthread
/* Return the signal number: */
pthread->signo = sig;
- } else if (pthread == curthread) {
+ } else if (sigismember(&pthread->sigmask, sig))
/* Add the signal to the pending set: */
sigaddset(&pthread->sigpend, sig);
- if (!sigismember(&pthread->sigmask, sig)) {
- /*
- * Call the kernel scheduler which will safely
- * install a signal frame for this thread:
- */
- _thread_kern_sched_sig();
- }
- } else if (!sigismember(&pthread->sigmask, sig)) {
+ else if (pthread == curthread)
+ /* Call the signal handler for the current thread: */
+ thread_sig_invoke_handler(sig, NULL, NULL);
+ else {
/* Protect the scheduling queues: */
_thread_kern_sig_defer();
/*
@@ -921,9 +948,6 @@ _thread_sig_send(struct pthread *pthread
thread_sig_add(pthread, sig, /* has args */ 0);
/* Unprotect the scheduling queues: */
_thread_kern_sig_undefer();
- } else {
- /* Increment the pending signal count. */
- sigaddset(&pthread->sigpend,sig);
}
}
}
@@ -936,7 +960,6 @@ _thread_sig_send(struct pthread *pthread
void
_thread_sig_wrapper(void)
{
- void (*sigfunc)(int, siginfo_t *, void *);
struct pthread_signal_frame *psf;
struct pthread *thread = _get_curthread();
@@ -1002,27 +1025,13 @@ _thread_sig_wrapper(void)
thread->sig_defer_count = 0;
/*
- * Check that a custom handler is installed and if the signal
- * is not blocked:
+ * Dispatch the signal via the custom signal handler:
*/
- sigfunc = _thread_sigact[psf->signo - 1].sa_sigaction;
- if (((__sighandler_t *)sigfunc != SIG_DFL) &&
- ((__sighandler_t *)sigfunc != SIG_IGN)) {
- DBG_MSG("_thread_sig_wrapper: Calling signal handler for "
- "thread 0x%p\n", thread);
- /*
- * Dispatch the signal via the custom signal
- * handler:
- */
- if (psf->sig_has_args == 0)
- (*(sigfunc))(psf->signo, NULL, NULL);
- else if ((_thread_sigact[psf->signo - 1].sa_flags &
- SA_SIGINFO) != 0)
- (*(sigfunc))(psf->signo, &psf->siginfo, &psf->uc);
- else
- (*(sigfunc))(psf->signo,
- (siginfo_t *)psf->siginfo.si_code, &psf->uc);
- }
+ if (psf->sig_has_args == 0)
+ thread_sig_invoke_handler(psf->signo, NULL, NULL);
+ else
+ thread_sig_invoke_handler(psf->signo, &psf->siginfo, &psf->uc);
+
/*
* Call the kernel scheduler to safely restore the frame and
* schedule the next thread:
@@ -1034,24 +1043,10 @@ static void
thread_sigframe_add(struct pthread *thread, int sig, int has_args)
{
struct pthread_signal_frame *psf = NULL;
- unsigned long stackp = 0;
+ unsigned long stackp;
- /* Get the top of the threads stack: */
- switch (thread->ctxtype) {
- case CTX_JB:
- case CTX_JB_NOSIG:
- stackp = GET_STACK_JB(thread->ctx.jb);
- break;
- case CTX_SJB:
- stackp = GET_STACK_SJB(thread->ctx.sigjb);
- break;
- case CTX_UC:
- stackp = GET_STACK_UC(&thread->ctx.uc);
- break;
- default:
- PANIC("Invalid thread context type");
- break;
- }
+ /* Get the top of the threads stack: */
+ stackp = GET_STACK_JB(thread->ctx.jb);
/*
* Leave a little space on the stack and round down to the
@@ -1085,8 +1080,6 @@ thread_sigframe_add(struct pthread *thre
/* Set up the new frame: */
thread->curframe = psf;
- thread->ctxtype = CTX_JB_NOSIG;
- thread->longjmp_val = 1;
thread->flags &= PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE |
PTHREAD_FLAGS_IN_SYNCQ;
/*
@@ -1102,8 +1095,7 @@ void
_thread_sigframe_restore(struct pthread *thread,
struct pthread_signal_frame *psf)
{
- thread->ctxtype = psf->ctxtype;
- memcpy(&thread->ctx.uc, &psf->ctx.uc, sizeof(thread->ctx.uc));
+ memcpy(&thread->ctx, &psf->ctx, sizeof(thread->ctx));
/*
* Only restore the signal mask if it hasn't been changed
* by the application during invocation of the signal handler:
@@ -1116,7 +1108,6 @@ _thread_sigframe_restore(struct pthread
thread->state = psf->saved_state.psd_state;
thread->flags = psf->saved_state.psd_flags;
thread->interrupted = psf->saved_state.psd_interrupted;
- thread->longjmp_val = psf->saved_state.psd_longjmp_val;
thread->signo = psf->saved_state.psd_signo;
thread->sig_defer_count = psf->saved_state.psd_sig_defer_count;
}
@@ -1124,8 +1115,7 @@ _thread_sigframe_restore(struct pthread
static void
thread_sigframe_save(struct pthread *thread, struct pthread_signal_frame *psf)
{
- psf->ctxtype = thread->ctxtype;
- memcpy(&psf->ctx.uc, &thread->ctx.uc, sizeof(thread->ctx.uc));
+ memcpy(&psf->ctx, &thread->ctx, sizeof(thread->ctx));
psf->saved_state.psd_sigmask = thread->sigmask;
psf->saved_state.psd_curframe = thread->curframe;
psf->saved_state.psd_wakeup_time = thread->wakeup_time;
@@ -1134,7 +1124,6 @@ thread_sigframe_save(struct pthread *thr
psf->saved_state.psd_flags = thread->flags &
(PTHREAD_FLAGS_PRIVATE | PTHREAD_FLAGS_TRACE);
psf->saved_state.psd_interrupted = thread->interrupted;
- psf->saved_state.psd_longjmp_val = thread->longjmp_val;
psf->saved_state.psd_sigmask_seqno = thread->sigmask_seqno;
psf->saved_state.psd_signo = thread->signo;
psf->saved_state.psd_sig_defer_count = thread->sig_defer_count;
Index: lib/libc_r/uthread/uthread_sigpending.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sigpending.c,v
retrieving revision 1.6.2.1
diff -u -p -r1.6.2.1 uthread_sigpending.c
--- lib/libc_r/uthread/uthread_sigpending.c 17 Oct 2002 19:37:39 -0000 1.6.2.1
+++ lib/libc_r/uthread/uthread_sigpending.c 20 Oct 2002 16:12:30 -0000
@@ -31,6 +31,9 @@
*
* $FreeBSD: src/lib/libc_r/uthread/uthread_sigpending.c,v 1.6.2.1 2002/10/17 19:37:39 fjoe Exp $
*/
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/signalvar.h>
#include <signal.h>
#include <errno.h>
#ifdef _THREAD_SAFE
@@ -38,7 +41,7 @@
#include "pthread_private.h"
int
-_sigpending(sigset_t * set)
+_sigpending(sigset_t *set)
{
struct pthread *curthread = _get_curthread();
int ret = 0;
@@ -50,6 +53,7 @@ _sigpending(sigset_t * set)
}
else {
*set = curthread->sigpend;
+ SIGSETOR(*set, _process_sigpending);
}
/* Return the completion status: */
return (ret);
Index: lib/libc_r/uthread/uthread_sigsuspend.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_sigsuspend.c,v
retrieving revision 1.9.2.1
diff -u -p -r1.9.2.1 uthread_sigsuspend.c
--- lib/libc_r/uthread/uthread_sigsuspend.c 17 Oct 2002 19:37:39 -0000 1.9.2.1
+++ lib/libc_r/uthread/uthread_sigsuspend.c 20 Oct 2002 16:10:05 -0000
@@ -32,6 +32,8 @@
* $FreeBSD: src/lib/libc_r/uthread/uthread_sigsuspend.c,v 1.9.2.1 2002/10/17 19:37:39 fjoe Exp $
*/
#include <signal.h>
+#include <sys/param.h>
+#include <sys/signalvar.h>
#include <errno.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
@@ -42,7 +44,7 @@ _sigsuspend(const sigset_t * set)
{
struct pthread *curthread = _get_curthread();
int ret = -1;
- sigset_t oset;
+ sigset_t oset, sigset;
/* Check if a new signal set was provided by the caller: */
if (set != NULL) {
@@ -52,8 +54,24 @@ _sigsuspend(const sigset_t * set)
/* Change the caller's mask: */
curthread->sigmask = *set;
- /* Wait for a signal: */
- _thread_kern_sched_state(PS_SIGSUSPEND, __FILE__, __LINE__);
+ /*
+ * Check if there are pending signals for the running
+ * thread or process that aren't blocked:
+ */
+ sigset = curthread->sigpend;
+ SIGSETOR(sigset, _process_sigpending);
+ SIGSETNAND(sigset, curthread->sigmask);
+ if (SIGNOTEMPTY(sigset)) {
+ /*
+ * Call the kernel scheduler which will safely
+ * install a signal frame for the running thread:
+ */
+ _thread_kern_sched_sig();
+ } else {
+ /* Wait for a signal: */
+ _thread_kern_sched_state(PS_SIGSUSPEND,
+ __FILE__, __LINE__);
+ }
/* Always return an interrupted error: */
errno = EINTR;
Index: lib/libc_r/uthread/uthread_single_np.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_single_np.c,v
retrieving revision 1.3.2.1
diff -u -p -r1.3.2.1 uthread_single_np.c
--- lib/libc_r/uthread/uthread_single_np.c 17 Oct 2002 19:37:39 -0000 1.3.2.1
+++ lib/libc_r/uthread/uthread_single_np.c 20 Oct 2002 14:43:55 -0000
@@ -34,12 +34,17 @@
#include <string.h>
#ifdef _THREAD_SAFE
#include <pthread.h>
-#include "pthread_private.h"
+#include <pthread_np.h>
int pthread_single_np()
{
+
/* Enter single-threaded (non-POSIX) scheduling mode: */
- _thread_single = _get_curthread();
- return(0);
+ pthread_suspend_all_np();
+ /*
+ * XXX - Do we want to do this?
+ * __is_threaded = 0;
+ */
+ return (0);
}
#endif
Index: lib/libc_r/uthread/uthread_suspend_np.c
===================================================================
RCS file: /home/ncvs/src/lib/libc_r/uthread/uthread_suspend_np.c,v
retrieving revision 1.7.2.5
diff -u -p -r1.7.2.5 uthread_suspend_np.c
--- lib/libc_r/uthread/uthread_suspend_np.c 17 Oct 2002 19:37:39 -0000 1.7.2.5
+++ lib/libc_r/uthread/uthread_suspend_np.c 20 Oct 2002 14:43:55 -0000
@@ -36,7 +36,7 @@
#include <pthread.h>
#include "pthread_private.h"
-static void finish_suspension(void *arg);
+static void suspend_common(struct pthread *thread);
/* Suspend a thread: */
int
@@ -44,100 +44,19 @@ pthread_suspend_np(pthread_t thread)
{
int ret;
+ /* Suspending the current thread doesn't make sense. */
+ if (thread == _get_curthread())
+ ret = EDEADLK;
+
/* Find the thread in the list of active threads: */
- if ((ret = _find_thread(thread)) == 0) {
+ else if ((ret = _find_thread(thread)) == 0) {
/*
* Defer signals to protect the scheduling queues from
* access by the signal handler:
*/
_thread_kern_sig_defer();
- switch (thread->state) {
- case PS_RUNNING:
- /*
- * Remove the thread from the priority queue and
- * set the state to suspended:
- */
- PTHREAD_PRIOQ_REMOVE(thread);
- PTHREAD_SET_STATE(thread, PS_SUSPENDED);
- break;
-
- case PS_SPINBLOCK:
- case PS_FDR_WAIT:
- case PS_FDW_WAIT:
- case PS_POLL_WAIT:
- case PS_SELECT_WAIT:
- /*
- * Remove these threads from the work queue
- * and mark the operation as interrupted:
- */
- if ((thread->flags & PTHREAD_FLAGS_IN_WORKQ) != 0)
- PTHREAD_WORKQ_REMOVE(thread);
- _thread_seterrno(thread,EINTR);
-
- /* FALLTHROUGH */
- case PS_SLEEP_WAIT:
- thread->interrupted = 1;
-
- /* FALLTHROUGH */
- case PS_SIGTHREAD:
- case PS_WAIT_WAIT:
- case PS_SIGSUSPEND:
- case PS_SIGWAIT:
- /*
- * Remove these threads from the waiting queue and
- * set their state to suspended:
- */
- PTHREAD_WAITQ_REMOVE(thread);
- PTHREAD_SET_STATE(thread, PS_SUSPENDED);
- break;
-
- case PS_MUTEX_WAIT:
- /* Mark the thread as suspended and still in a queue. */
- thread->suspended = SUSP_MUTEX_WAIT;
-
- PTHREAD_SET_STATE(thread, PS_SUSPENDED);
- break;
- case PS_COND_WAIT:
- /* Mark the thread as suspended and still in a queue. */
- thread->suspended = SUSP_COND_WAIT;
-
- PTHREAD_SET_STATE(thread, PS_SUSPENDED);
- break;
- case PS_JOIN:
- /* Mark the thread as suspended and joining: */
- thread->suspended = SUSP_JOIN;
-
- PTHREAD_NEW_STATE(thread, PS_SUSPENDED);
- break;
- case PS_FDLR_WAIT:
- case PS_FDLW_WAIT:
- case PS_FILE_WAIT:
- /* Mark the thread as suspended: */
- thread->suspended = SUSP_YES;
-
- /*
- * Threads in these states may be in queues.
- * In order to preserve queue integrity, the
- * cancelled thread must remove itself from the
- * queue. Mark the thread as interrupted and
- * set the state to running. When the thread
- * resumes, it will remove itself from the queue
- * and call the suspension completion routine.
- */
- thread->interrupted = 1;
- _thread_seterrno(thread, EINTR);
- PTHREAD_NEW_STATE(thread, PS_RUNNING);
- thread->continuation = finish_suspension;
- break;
-
- case PS_DEAD:
- case PS_DEADLOCK:
- case PS_STATE_MAX:
- case PS_SUSPENDED:
- /* Nothing needs to be done: */
- break;
- }
+ suspend_common(thread);
/*
* Undefer and handle pending signals, yielding if
@@ -145,17 +64,40 @@ pthread_suspend_np(pthread_t thread)
*/
_thread_kern_sig_undefer();
}
- return(ret);
+ return (ret);
}
-static void
-finish_suspension(void *arg)
+void
+pthread_suspend_all_np(void)
{
struct pthread *curthread = _get_curthread();
+ struct pthread *thread;
- if (curthread->suspended != SUSP_NO)
- _thread_kern_sched_state(PS_SUSPENDED, __FILE__, __LINE__);
-}
+ /*
+ * Defer signals to protect the scheduling queues from
+ * access by the signal handler:
+ */
+ _thread_kern_sig_defer();
+
+ TAILQ_FOREACH(thread, &_thread_list, tle) {
+ if (thread != curthread)
+ suspend_common(thread);
+ }
+ /*
+ * Undefer and handle pending signals, yielding if
+ * necessary:
+ */
+ _thread_kern_sig_undefer();
+}
+void
+suspend_common(struct pthread *thread)
+{
+ thread->flags |= PTHREAD_FLAGS_SUSPENDED;
+ if (thread->flags & PTHREAD_FLAGS_IN_PRIOQ) {
+ PTHREAD_PRIOQ_REMOVE(thread);
+ PTHREAD_SET_STATE(thread, PS_SUSPENDED);
+ }
+}
#endif
--UlVJffcvxoiEqYs2--
To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20021021001514.A38080>
