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.
This commit is contained in:
parent
602c788942
commit
7c916264aa
@ -66,6 +66,14 @@
|
|||||||
|
|
||||||
#include "thr_private.h"
|
#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);
|
extern void _thread_init_hack(void);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -168,6 +176,7 @@ _thread_init(void)
|
|||||||
size_t len;
|
size_t len;
|
||||||
int mib[2];
|
int mib[2];
|
||||||
sigset_t set;
|
sigset_t set;
|
||||||
|
int osreldate;
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
struct clockinfo clockinfo;
|
struct clockinfo clockinfo;
|
||||||
@ -324,6 +333,23 @@ _thread_init(void)
|
|||||||
SIGADDSET(set, SIGTHR);
|
SIGADDSET(set, SIGTHR);
|
||||||
__sys_sigprocmask(SIG_BLOCK, &set, 0);
|
__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: */
|
/* Get the kernel clockrate: */
|
||||||
mib[0] = CTL_KERN;
|
mib[0] = CTL_KERN;
|
||||||
mib[1] = KERN_CLOCKRATE;
|
mib[1] = KERN_CLOCKRATE;
|
||||||
|
@ -179,15 +179,8 @@ _thread_suspend(pthread_t pthread, struct timespec *abstime)
|
|||||||
struct timespec remaining;
|
struct timespec remaining;
|
||||||
struct timespec *ts;
|
struct timespec *ts;
|
||||||
siginfo_t info;
|
siginfo_t info;
|
||||||
sigset_t set;
|
|
||||||
int error;
|
int error;
|
||||||
|
|
||||||
/*
|
|
||||||
* Catch SIGTHR.
|
|
||||||
*/
|
|
||||||
SIGFILLSET(set);
|
|
||||||
SIGDELSET(set, SIGTHR);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Compute the remainder of the run time.
|
* Compute the remainder of the run time.
|
||||||
*/
|
*/
|
||||||
@ -204,9 +197,7 @@ _thread_suspend(pthread_t pthread, struct timespec *abstime)
|
|||||||
} else
|
} else
|
||||||
ts = NULL;
|
ts = NULL;
|
||||||
|
|
||||||
error = sigtimedwait(&set, &info, ts);
|
error = sigtimedwait(&_thread_suspend_sigset, &info, ts);
|
||||||
if (error == -1)
|
error = (error == -1) ? errno : 0;
|
||||||
error = errno;
|
|
||||||
|
|
||||||
return (error);
|
return (error);
|
||||||
}
|
}
|
||||||
|
@ -692,6 +692,9 @@ SCLASS pthread_cond_t _gc_cond
|
|||||||
*/
|
*/
|
||||||
SCLASS struct sigaction _thread_sigact[NSIG];
|
SCLASS struct sigaction _thread_sigact[NSIG];
|
||||||
|
|
||||||
|
/* Precomputed signal set for _thread_suspend. */
|
||||||
|
SCLASS sigset_t _thread_suspend_sigset;
|
||||||
|
|
||||||
/* Tracks the number of threads blocked while waiting for a spinlock. */
|
/* Tracks the number of threads blocked while waiting for a spinlock. */
|
||||||
SCLASS volatile int _spinblock_count
|
SCLASS volatile int _spinblock_count
|
||||||
#ifdef GLOBAL_PTHREAD_PRIVATE
|
#ifdef GLOBAL_PTHREAD_PRIVATE
|
||||||
|
Loading…
Reference in New Issue
Block a user