svn commit: r213153 - in head/lib: libc libc/gen libc/include librt libthr libthr/thread

David Xu davidxu at FreeBSD.org
Sat Sep 25 01:57:47 UTC 2010


Author: davidxu
Date: Sat Sep 25 01:57:47 2010
New Revision: 213153
URL: http://svn.freebsd.org/changeset/base/213153

Log:
  To support stack unwinding for cancellation points, add -fexceptions flag
  for them, two functions _pthread_cancel_enter and _pthread_cancel_leave
  are added to let thread enter and leave a cancellation point, it also
  makes it possible that other functions can be cancellation points in
  libraries without having to be rewritten in libthr.

Modified:
  head/lib/libc/Makefile
  head/lib/libc/gen/Makefile.inc
  head/lib/libc/gen/Symbol.map
  head/lib/libc/gen/_pthread_stubs.c
  head/lib/libc/gen/sem.c
  head/lib/libc/gen/sem_new.c
  head/lib/libc/include/libc_private.h
  head/lib/librt/Makefile
  head/lib/librt/mq.c
  head/lib/libthr/Makefile
  head/lib/libthr/pthread.map
  head/lib/libthr/thread/thr_cancel.c
  head/lib/libthr/thread/thr_init.c
  head/lib/libthr/thread/thr_private.h

Modified: head/lib/libc/Makefile
==============================================================================
--- head/lib/libc/Makefile	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/Makefile	Sat Sep 25 01:57:47 2010	(r213153)
@@ -31,6 +31,11 @@ CLEANFILES+=tags
 INSTALL_PIC_ARCHIVE=
 PRECIOUSLIB=
 
+.ifndef NO_THREAD_STACK_UNWIND
+CANCELPOINTS_CFLAGS=-fexceptions
+CFLAGS+=${CANCELPOINTS_CFLAGS}
+.endif
+
 #
 # Only link with static libgcc.a (no libgcc_eh.a).
 #
@@ -145,3 +150,5 @@ CWARNFLAGS:=	${.IMPSRC:Ngdtoa_*.c:C/^.+$
 SSP_CFLAGS:=	${SSP_CFLAGS:S/^-fstack-protector-all$/-fstack-protector/}
 # Disable stack protection for SSP symbols.
 SSP_CFLAGS:=	${.IMPSRC:N*/stack_protector.c:C/^.+$/${SSP_CFLAGS}/}
+# Generate stack unwinding tables for cancellation points
+CANCELPOINTS_CFLAGS:=	${.IMPSRC:Mcancelpoints_*:C/^.+$/${CANCELPOINTS_CFLAGS}/:C/^$//}

Modified: head/lib/libc/gen/Makefile.inc
==============================================================================
--- head/lib/libc/gen/Makefile.inc	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/gen/Makefile.inc	Sat Sep 25 01:57:47 2010	(r213153)
@@ -25,7 +25,7 @@ SRCS+=  __getosreldate.c __xuname.c \
 	pause.c pmadvise.c popen.c posix_spawn.c \
 	psignal.c pututxline.c pw_scan.c pwcache.c \
 	raise.c readdir.c readpassphrase.c rewinddir.c \
-	scandir.c seed48.c seekdir.c sem.c sem_new.c semctl.c \
+	scandir.c seed48.c seekdir.c semctl.c \
 	setdomainname.c sethostname.c setjmperr.c setmode.c \
 	setproctitle.c setprogname.c siginterrupt.c siglist.c signal.c \
 	sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \
@@ -35,6 +35,14 @@ SRCS+=  __getosreldate.c __xuname.c \
 	usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
 	wordexp.c
 
+CANCELPOINTS_SRCS=sem.c sem_new.c
+.for src in ${CANCELPOINTS_SRCS}
+SRCS+=cancelpoints_${src}
+CLEANFILES+=cancelpoints_${src}
+cancelpoints_${src}:
+	ln -sf ${.CURDIR}/gen/${src} ${.TARGET}
+.endfor
+
 SYM_MAPS+=${.CURDIR}/gen/Symbol.map
 
 # machine-dependent gen sources

Modified: head/lib/libc/gen/Symbol.map
==============================================================================
--- head/lib/libc/gen/Symbol.map	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/gen/Symbol.map	Sat Sep 25 01:57:47 2010	(r213153)
@@ -403,6 +403,8 @@ FBSDprivate_1.0 {
 	_pthread_attr_setstackaddr;
 	_pthread_attr_setstacksize;
 	_pthread_cancel;
+	_pthread_cancel_enter;
+	_pthread_cancel_leave;
 	_pthread_cleanup_pop;
 	_pthread_cleanup_push;
 	_pthread_cond_broadcast;

Modified: head/lib/libc/gen/_pthread_stubs.c
==============================================================================
--- head/lib/libc/gen/_pthread_stubs.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/gen/_pthread_stubs.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -121,6 +121,8 @@ pthread_func_entry_t __thr_jtable[PJT_MA
 	{PJT_DUAL_ENTRY(stub_zero)},    /* PJT_TESTCANCEL */
 	{PJT_DUAL_ENTRY(stub_zero)},    /* PJT_CLEANUP_POP_IMP */
 	{PJT_DUAL_ENTRY(stub_zero)},    /* PJT_CLEANUP_PUSH_IMP */
+	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_CANCEL_ENTER */
+	{PJT_DUAL_ENTRY(stub_zero)},	/* PJT_CANCEL_LEAVE */
 };
 
 /*
@@ -269,6 +271,8 @@ STUB_FUNC2(pthread_setcanceltype, PJT_SE
 STUB_FUNC(pthread_testcancel, PJT_TESTCANCEL, void)
 STUB_FUNC1(__pthread_cleanup_pop_imp, PJT_CLEANUP_POP_IMP, int, int)
 STUB_FUNC2(__pthread_cleanup_push_imp, PJT_CLEANUP_PUSH_IMP, void, void*, void *);
+STUB_FUNC1(_pthread_cancel_enter, PJT_CANCEL_ENTER, int, int)
+STUB_FUNC1(_pthread_cancel_leave, PJT_CANCEL_LEAVE, int, int)
 
 static int
 stub_zero(void)

Modified: head/lib/libc/gen/sem.c
==============================================================================
--- head/lib/libc/gen/sem.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/gen/sem.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -312,21 +312,6 @@ _libc_sem_unlink_compat(const char *name
 }
 
 static int
-enable_async_cancel(void)
-{
-	int old;
-
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
-	return (old);
-}
-
-static void
-restore_async_cancel(int val)
-{
-	_pthread_setcanceltype(val, NULL);
-}
-
-static int
 _umtx_wait_uint(volatile unsigned *mtx, unsigned id, const struct timespec *timeout)
 {
 	if (timeout && (timeout->tv_sec < 0 || (timeout->tv_sec == 0 &&
@@ -371,15 +356,15 @@ _libc_sem_timedwait_compat(sem_t * __res
 	const struct timespec * __restrict abstime)
 {
 	struct timespec ts, ts2;
-	int val, retval, saved_cancel;
+	int val, retval;
 
 	if (sem_check_validity(sem) != 0)
 		return (-1);
 
 	if ((*sem)->syssem != 0) {
-		saved_cancel = enable_async_cancel();
-		retval = ksem_wait((*sem)->semid);
-		restore_async_cancel(saved_cancel);
+		_pthread_cancel_enter(1);
+		retval = ksem_wait((*sem)->semid); /* XXX no timeout */
+		_pthread_cancel_leave(retval == -1);
 		return (retval);
 	}
 
@@ -390,8 +375,10 @@ _libc_sem_timedwait_compat(sem_t * __res
 			if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1))
 				return (0);
 		}
-		if (retval)
+		if (retval) {
+			_pthread_testcancel();
 			break;
+		}
 		if (abstime) {
 			if (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0) {
 				errno = EINVAL;
@@ -402,9 +389,9 @@ _libc_sem_timedwait_compat(sem_t * __res
 		}
 		atomic_add_int(&(*sem)->nwaiters, 1);
 		pthread_cleanup_push(sem_cancel_handler, sem);
-		saved_cancel = enable_async_cancel();
+		_pthread_cancel_enter(1);
 		retval = _umtx_wait_uint(&(*sem)->count, 0, abstime ? &ts2 : NULL);
-		restore_async_cancel(saved_cancel);
+		_pthread_cancel_leave(0);
 		pthread_cleanup_pop(0);
 		atomic_add_int(&(*sem)->nwaiters, -1);
 	}

Modified: head/lib/libc/gen/sem_new.c
==============================================================================
--- head/lib/libc/gen/sem_new.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/gen/sem_new.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -47,6 +47,7 @@
 #include <semaphore.h>
 #include <unistd.h>
 #include "un-namespace.h"
+#include "libc_private.h"
 
 __weak_reference(_sem_close, sem_close);
 __weak_reference(_sem_destroy, sem_destroy);
@@ -364,15 +365,6 @@ _sem_trywait(sem_t *sem)
 	return (-1);
 }
 
-static void
-sem_cancel_handler(void *arg)
-{
-	sem_t *sem = arg;
-
-	if (sem->_kern._has_waiters && sem->_kern._count)
-		usem_wake(&sem->_kern);
-}
-
 #define TIMESPEC_SUB(dst, src, val)                             \
         do {                                                    \
                 (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec;  \
@@ -384,27 +376,12 @@ sem_cancel_handler(void *arg)
         } while (0)
 
 
-static __inline int
-enable_async_cancel(void)
-{
-	int old;
-
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
-	return (old);
-}
-
-static __inline void
-restore_async_cancel(int val)
-{
-	_pthread_setcanceltype(val, NULL);
-}
-
 int
 _sem_timedwait(sem_t * __restrict sem,
 	const struct timespec * __restrict abstime)
 {
 	struct timespec ts, ts2;
-	int val, retval, saved_cancel;
+	int val, retval;
 
 	if (sem_check_validity(sem) != 0)
 		return (-1);
@@ -416,8 +393,10 @@ _sem_timedwait(sem_t * __restrict sem,
 				return (0);
 		}
 
-		if (retval)
+		if (retval) {
+			_pthread_testcancel();
 			break;
+		}
 
 		/*
 		 * The timeout argument is only supposed to
@@ -431,11 +410,9 @@ _sem_timedwait(sem_t * __restrict sem,
 			clock_gettime(CLOCK_REALTIME, &ts);
 			TIMESPEC_SUB(&ts2, abstime, &ts);
 		}
-		pthread_cleanup_push(sem_cancel_handler, sem);
-		saved_cancel = enable_async_cancel();
+		_pthread_cancel_enter(1);
 		retval = usem_wait(&sem->_kern, abstime ? &ts2 : NULL);
-		restore_async_cancel(saved_cancel);
-		pthread_cleanup_pop(0);
+		_pthread_cancel_leave(0);
 	}
 	return (retval);
 }

Modified: head/lib/libc/include/libc_private.h
==============================================================================
--- head/lib/libc/include/libc_private.h	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libc/include/libc_private.h	Sat Sep 25 01:57:47 2010	(r213153)
@@ -129,6 +129,8 @@ typedef enum {
 	PJT_TESTCANCEL,
 	PJT_CLEANUP_POP_IMP,
 	PJT_CLEANUP_PUSH_IMP,
+	PJT_CANCEL_ENTER,
+	PJT_CANCEL_LEAVE,
 	PJT_MAX
 } pjt_index_t;
 
@@ -217,4 +219,7 @@ int _elf_aux_info(int aux, void *buf, in
 struct dl_phdr_info;
 int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
 
+void	_pthread_cancel_enter(int);
+void	_pthread_cancel_leave(int);
+
 #endif /* _LIBC_PRIVATE_H_ */

Modified: head/lib/librt/Makefile
==============================================================================
--- head/lib/librt/Makefile	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/librt/Makefile	Sat Sep 25 01:57:47 2010	(r213153)
@@ -3,14 +3,15 @@
 LIB=rt
 SHLIB_MAJOR= 1
 CFLAGS+=-I${.CURDIR}/../libc/include -I${.CURDIR}
+.ifndef NO_THREAD_STACK_UNWIND
+CFLAGS+=-fexceptions
+.endif
 CFLAGS+=-Winline -Wall -g
 DPADD=	${LIBPTHREAD}
 LDADD=	-lpthread
 
 WARNS?=	2
 
-#MAN=	libthr.3
-
 SRCS+= aio.c mq.c sigev_thread.c timer.c
 
 PRECIOUSLIB=

Modified: head/lib/librt/mq.c
==============================================================================
--- head/lib/librt/mq.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/librt/mq.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -39,6 +39,7 @@
 #include <signal.h>
 #include "sigev_thread.h"
 #include "un-namespace.h"
+#include "libc_private.h"
 
 extern int	__sys_kmq_notify(int, const struct sigevent *);
 extern int	__sys_kmq_open(const char *, int, mode_t,
@@ -200,12 +201,11 @@ ssize_t
 __mq_timedreceive_cancel(mqd_t mqd, char *buf, size_t len,
 	unsigned *prio, const struct timespec *timeout)
 {
-	int oldtype;
 	int ret;
 
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	_pthread_cancel_enter(1);
 	ret = __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, timeout);
-	_pthread_setcanceltype(oldtype, NULL);
+	_pthread_cancel_leave(ret == -1);
 	return (ret);
 }
 
@@ -219,12 +219,11 @@ __mq_receive(mqd_t mqd, char *buf, size_
 ssize_t
 __mq_receive_cancel(mqd_t mqd, char *buf, size_t len, unsigned *prio)
 {
-	int oldtype;
 	int ret;
 
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	_pthread_cancel_enter(1);
 	ret = __sys_kmq_timedreceive(mqd->oshandle, buf, len, prio, NULL);
-	_pthread_setcanceltype(oldtype, NULL);
+	_pthread_cancel_leave(ret == -1);
 	return (ret);
 }
 ssize_t
@@ -239,12 +238,11 @@ ssize_t
 __mq_timedsend_cancel(mqd_t mqd, char *buf, size_t len,
 	unsigned prio, const struct timespec *timeout)
 {
-	int oldtype;
 	int ret;
 
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	_pthread_cancel_enter(1);
 	ret = __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, timeout);
-	_pthread_setcanceltype(oldtype, NULL);
+	_pthread_cancel_leave(ret == -1);
 	return (ret);
 }
 
@@ -259,12 +257,11 @@ __mq_send(mqd_t mqd, char *buf, size_t l
 ssize_t
 __mq_send_cancel(mqd_t mqd, char *buf, size_t len, unsigned prio)
 {
-	int oldtype;
 	int ret;
 
-	_pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &oldtype);
+	_pthread_cancel_enter(1);
 	ret = __sys_kmq_timedsend(mqd->oshandle, buf, len, prio, NULL);
-	_pthread_setcanceltype(oldtype, NULL);
+	_pthread_cancel_leave(ret == -1);
 	return (ret);
 }
 

Modified: head/lib/libthr/Makefile
==============================================================================
--- head/lib/libthr/Makefile	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libthr/Makefile	Sat Sep 25 01:57:47 2010	(r213153)
@@ -26,9 +26,7 @@ CFLAGS+=-I${.CURDIR}/../../libexec/rtld-
 CFLAGS+=-I${.CURDIR}/../libthread_db
 CFLAGS+=-Winline
 
-LIBTHR_UNWIND_STACK=yes
-
-.ifdef LIBTHR_UNWIND_STACK
+.ifndef NO_THREAD_UNWIND_STACK
 CFLAGS+=-I${.CURDIR}/../../contrib/gcc -fexceptions 
 CFLAGS+=-D_PTHREAD_FORCED_UNWIND
 .endif

Modified: head/lib/libthr/pthread.map
==============================================================================
--- head/lib/libthr/pthread.map	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libthr/pthread.map	Sat Sep 25 01:57:47 2010	(r213153)
@@ -246,6 +246,8 @@ FBSDprivate_1.0 {
 	_pthread_attr_setstackaddr;
 	_pthread_attr_setstacksize;
 	_pthread_cancel;
+	_pthread_cancel_enter;
+	_pthread_cancel_leave;
 	_pthread_cleanup_pop;
 	_pthread_cleanup_push;
 	_pthread_cond_broadcast;

Modified: head/lib/libthr/thread/thr_cancel.c
==============================================================================
--- head/lib/libthr/thread/thr_cancel.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libthr/thread/thr_cancel.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -162,3 +162,15 @@ _thr_cancel_leave(struct pthread *curthr
 	    !THR_IN_CRITICAL(curthread) && maycancel))
 		_pthread_exit(PTHREAD_CANCELED);
 }
+
+void
+_pthread_cancel_enter(int maycancel)
+{
+	_thr_cancel_enter2(_get_curthread(), maycancel);
+}
+
+void
+_pthread_cancel_leave(int maycancel)
+{
+	_thr_cancel_leave(_get_curthread(), maycancel);
+}

Modified: head/lib/libthr/thread/thr_init.c
==============================================================================
--- head/lib/libthr/thread/thr_init.c	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libthr/thread/thr_init.c	Sat Sep 25 01:57:47 2010	(r213153)
@@ -248,7 +248,9 @@ static pthread_func_t jmp_table[][2] = {
 	{DUAL_ENTRY(_pthread_sigmask)},		/* PJT_SIGMASK */
 	{DUAL_ENTRY(_pthread_testcancel)},	/* PJT_TESTCANCEL */
 	{DUAL_ENTRY(__pthread_cleanup_pop_imp)},/* PJT_CLEANUP_POP_IMP */
-	{DUAL_ENTRY(__pthread_cleanup_push_imp)}/* PJT_CLEANUP_PUSH_IMP */
+	{DUAL_ENTRY(__pthread_cleanup_push_imp)},/* PJT_CLEANUP_PUSH_IMP */
+	{DUAL_ENTRY(_pthread_cancel_enter)},	/* PJT_CANCEL_ENTER */
+	{DUAL_ENTRY(_pthread_cancel_leave)}		/* PJT_CANCEL_LEAVE */
 };
 
 static int init_once = 0;

Modified: head/lib/libthr/thread/thr_private.h
==============================================================================
--- head/lib/libthr/thread/thr_private.h	Sat Sep 25 01:25:48 2010	(r213152)
+++ head/lib/libthr/thread/thr_private.h	Sat Sep 25 01:57:47 2010	(r213153)
@@ -716,7 +716,8 @@ int	_sched_yield(void);
 void	_pthread_cleanup_push(void (*)(void *), void *);
 void	_pthread_cleanup_pop(int);
 void	_pthread_exit_mask(void *status, sigset_t *mask) __dead2 __hidden;
-
+void	_pthread_cancel_enter(int maycancel);
+void 	_pthread_cancel_leave(int maycancel);
 
 /* #include <fcntl.h> */
 #ifdef  _SYS_FCNTL_H_


More information about the svn-src-head mailing list