Skip site navigation (1)Skip section navigation (2)
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-java" 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>