summaryrefslogtreecommitdiffstats
path: root/lib/libthr/thread/thr_init.c
diff options
context:
space:
mode:
authorjdp <jdp@FreeBSD.org>2003-06-29 15:55:44 +0000
committerjdp <jdp@FreeBSD.org>2003-06-29 15:55:44 +0000
commit536016ad69db3ca3302cc7996846b12dbc8d5cf8 (patch)
tree7cca05bdbddd83b9e8f9d07ab187f59490dda694 /lib/libthr/thread/thr_init.c
parentf7d7f36d14ab77dae9c50dba93e92f21f3a5854d (diff)
downloadFreeBSD-src-536016ad69db3ca3302cc7996846b12dbc8d5cf8.zip
FreeBSD-src-536016ad69db3ca3302cc7996846b12dbc8d5cf8.tar.gz
Make _thread_suspend work with both the old broken sigtimedwait
implementation and the new improved one. We now precompute the signal set passed to sigtimedwait, using an inverted set when necessary for compatibility with older kernels.
Diffstat (limited to 'lib/libthr/thread/thr_init.c')
-rw-r--r--lib/libthr/thread/thr_init.c26
1 files changed, 26 insertions, 0 deletions
diff --git a/lib/libthr/thread/thr_init.c b/lib/libthr/thread/thr_init.c
index c404651..671bd6f 100644
--- a/lib/libthr/thread/thr_init.c
+++ b/lib/libthr/thread/thr_init.c
@@ -66,6 +66,14 @@
#include "thr_private.h"
+/*
+ * Early implementations of sigtimedwait interpreted the signal
+ * set incorrectly.
+ */
+#define SIGTIMEDWAIT_SET_IS_INVERTED(osreldate) \
+ ((500100 <= (osreldate) && (osreldate) <= 500113) || \
+ (osreldate) == 501000 || (osreldate) == 501100)
+
extern void _thread_init_hack(void);
/*
@@ -168,6 +176,7 @@ _thread_init(void)
size_t len;
int mib[2];
sigset_t set;
+ int osreldate;
int error;
struct clockinfo clockinfo;
@@ -324,6 +333,23 @@ _thread_init(void)
SIGADDSET(set, SIGTHR);
__sys_sigprocmask(SIG_BLOCK, &set, 0);
+ /*
+ * Precompute the signal set used by _thread_suspend to wait
+ * for SIGTHR.
+ */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELDATE;
+ len = sizeof(osreldate);
+ if (sysctl(mib, 2, &osreldate, &len, NULL, 0) == 0 &&
+ SIGTIMEDWAIT_SET_IS_INVERTED(osreldate)) {
+ /* Kernel bug requires an inverted signal set. */
+ SIGFILLSET(_thread_suspend_sigset);
+ SIGDELSET(_thread_suspend_sigset, SIGTHR);
+ } else {
+ SIGEMPTYSET(_thread_suspend_sigset);
+ SIGADDSET(_thread_suspend_sigset, SIGTHR);
+ }
+
/* Get the kernel clockrate: */
mib[0] = CTL_KERN;
mib[1] = KERN_CLOCKRATE;
OpenPOWER on IntegriCloud