Rename _thr_enter_cancellation_point to _thr_cancel_enter, rename

_thr_leave_cancellation_point to _thr_cancel_leave, add a parameter
to _thr_cancel_leave to indicate whether cancellation point should be
checked, this gives us an option to not check cancallation point if
a syscall successfully returns to avoid any leaks, current I have
creat(), open() and fcntl(F_DUPFD) to not check cancellation point
after they sucessfully returned.

Replace some members in structure kse with bit flags to same some
memory.

Conditionally compile THR_ASSERT to nothing if _PTHREAD_INVARIANTS is
not defined.

Inline some small functions in thr_cancel.c.

Use __predict_false in thr_kern.c for some executed only once code.

Reviewd by: deischen
This commit is contained in:
David Xu 2003-12-09 02:20:56 +00:00
parent ef7af95abd
commit 71679e629d
60 changed files with 296 additions and 272 deletions

View File

@ -42,9 +42,9 @@ _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_aio_suspend(iocbs, niocb, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -11,8 +11,35 @@ __weak_reference(_pthread_setcancelstate, pthread_setcancelstate);
__weak_reference(_pthread_setcanceltype, pthread_setcanceltype);
__weak_reference(_pthread_testcancel, pthread_testcancel);
static int checkcancel(struct pthread *curthread);
static void testcancel(struct pthread *curthread);
static inline int
checkcancel(struct pthread *curthread)
{
if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((curthread->cancelflags & THR_CANCELLING) != 0)) {
/*
* It is possible for this thread to be swapped out
* while performing cancellation; do not allow it
* to be cancelled again.
*/
curthread->cancelflags &= ~THR_CANCELLING;
return (1);
}
else
return (0);
}
static inline void
testcancel(struct pthread *curthread)
{
if (checkcancel(curthread) != 0) {
/* Unlock before exiting: */
THR_THREAD_UNLOCK(curthread, curthread);
_thr_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
PANIC("cancel");
}
}
int
_pthread_cancel(pthread_t pthread)
@ -217,37 +244,6 @@ _pthread_setcanceltype(int type, int *oldtype)
return (ret);
}
static int
checkcancel(struct pthread *curthread)
{
if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((curthread->cancelflags & THR_CANCELLING) != 0)) {
/*
* It is possible for this thread to be swapped out
* while performing cancellation; do not allow it
* to be cancelled again.
*/
curthread->cancelflags &= ~THR_CANCELLING;
return (1);
}
else
return (0);
}
static void
testcancel(struct pthread *curthread)
{
if (checkcancel(curthread) != 0) {
/* Unlock before exiting: */
THR_THREAD_UNLOCK(curthread, curthread);
_thr_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
PANIC("cancel");
}
}
void
_pthread_testcancel(void)
{
@ -259,10 +255,8 @@ _pthread_testcancel(void)
}
void
_thr_enter_cancellation_point(struct pthread *thread)
_thr_cancel_enter(struct pthread *thread)
{
if (!_kse_isthreaded())
return;
/* Look for a cancellation before we block: */
THR_THREAD_LOCK(thread, thread);
testcancel(thread);
@ -271,14 +265,13 @@ _thr_enter_cancellation_point(struct pthread *thread)
}
void
_thr_leave_cancellation_point(struct pthread *thread)
_thr_cancel_leave(struct pthread *thread, int check)
{
if (!_kse_isthreaded())
return;
THR_THREAD_LOCK(thread, thread);
thread->cancelflags &= ~THR_AT_CANCEL_POINT;
/* Look for a cancellation after we unblock: */
testcancel(thread);
if (check)
testcancel(thread);
THR_THREAD_UNLOCK(thread, thread);
}

View File

@ -47,9 +47,9 @@ __close(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_close(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -365,9 +365,9 @@ __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _pthread_cond_wait(cond, mutex);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -571,9 +571,9 @@ __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _pthread_cond_timedwait(cond, mutex, abstime);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,13 @@ ___creat(const char *path, mode_t mode)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __creat(path, mode);
_thr_leave_cancellation_point(curthread);
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
_thr_cancel_leave(curthread, (ret == -1));
return ret;
}

View File

@ -44,14 +44,21 @@ int
__fcntl(int fd, int cmd,...)
{
struct pthread *curthread = _get_curthread();
int ret;
int ret, check = 1;
va_list ap;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
va_start(ap, cmd);
switch (cmd) {
case F_DUPFD:
ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
check = (ret == -1);
break;
case F_SETFD:
case F_SETFL:
ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
@ -65,7 +72,7 @@ __fcntl(int fd, int cmd,...)
}
va_end(ap);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, check);
return (ret);
}

View File

@ -43,9 +43,9 @@ __fsync(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_fsync(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -45,19 +45,19 @@ _pthread_join(pthread_t pthread, void **thread_return)
kse_critical_t crit;
int ret = 0;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
/* Check if the caller has specified an invalid thread: */
if (pthread == NULL || pthread->magic != THR_MAGIC) {
/* Invalid thread: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (EINVAL);
}
/* Check if the caller has specified itself: */
if (pthread == curthread) {
/* Avoid a deadlock condition: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (EDEADLK);
}
@ -67,7 +67,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
*/
if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/1)) != 0) {
/* Return an error: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ESRCH);
}
@ -155,7 +155,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
*thread_return = curthread->join_status.ret;
}
}
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
/* Return the completion status: */
return (ret);

View File

@ -389,12 +389,6 @@ _kse_init(void)
}
}
int
_kse_isthreaded(void)
{
return (__isthreaded != 0);
}
/*
* This is called when the first thread (other than the initial
* thread) is created.
@ -636,7 +630,7 @@ _thr_sched_switch_unlocked(struct pthread *curthread)
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
kse_sched_single(&curkse->k_kcb->kcb_kmbx);
else {
curkse->k_switch = 1;
KSE_SET_SWITCH(curkse);
_thread_enter_uts(curthread->tcb, curkse->k_kcb);
}
@ -696,7 +690,7 @@ kse_sched_single(struct kse_mailbox *kmbx)
curkse = (struct kse *)kmbx->km_udata;
curthread = curkse->k_curthread;
if ((curkse->k_flags & KF_INITIALIZED) == 0) {
if (__predict_false((curkse->k_flags & KF_INITIALIZED) == 0)) {
/* Setup this KSEs specific data. */
_kcb_set(curkse->k_kcb);
_tcb_set(curkse->k_kcb, curthread->tcb);
@ -914,7 +908,7 @@ kse_sched_multi(struct kse_mailbox *kmbx)
"Mailbox not null in kse_sched_multi");
/* Check for first time initialization: */
if ((curkse->k_flags & KF_INITIALIZED) == 0) {
if (__predict_false((curkse->k_flags & KF_INITIALIZED) == 0)) {
/* Setup this KSEs specific data. */
_kcb_set(curkse->k_kcb);
@ -929,9 +923,15 @@ kse_sched_multi(struct kse_mailbox *kmbx)
_tcb_set(curkse->k_kcb, NULL);
/* If this is an upcall; take the scheduler lock. */
if (curkse->k_switch == 0)
if (!KSE_IS_SWITCH(curkse))
KSE_SCHED_LOCK(curkse, curkse->k_kseg);
curkse->k_switch = 0;
else
KSE_CLEAR_SWITCH(curkse);
if (KSE_IS_IDLE(curkse)) {
KSE_CLEAR_IDLE(curkse);
curkse->k_kseg->kg_idle_kses--;
}
/*
* Now that the scheduler lock is held, get the current
@ -941,10 +941,6 @@ kse_sched_multi(struct kse_mailbox *kmbx)
*/
curthread = curkse->k_curthread;
if (KSE_IS_IDLE(curkse)) {
KSE_CLEAR_IDLE(curkse);
curkse->k_kseg->kg_idle_kses--;
}
/*
* If the current thread was completed in another KSE, then
* it will be in the run queue. Don't mark it as being blocked.
@ -2295,11 +2291,8 @@ kse_reinit(struct kse *kse, int sys_scope)
kse->k_schedq = 0;
kse->k_locklevel = 0;
kse->k_flags = 0;
kse->k_idle = 0;
kse->k_error = 0;
kse->k_cpu = 0;
kse->k_done = 0;
kse->k_switch = 0;
kse->k_sigseqno = 0;
}

View File

@ -25,9 +25,9 @@ __msync(void *addr, size_t len, int flags)
* write. The only real use of this wrapper is to guarantee
* a cancellation point, as per the standard. sigh.
*/
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_msync(addr, len, flags);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -121,9 +121,9 @@ __nanosleep(const struct timespec *time_to_sleep,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _nanosleep(time_to_sleep, time_remaining);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -50,7 +50,7 @@ __open(const char *path, int flags,...)
int mode = 0;
va_list ap;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
/* Check if the file is being created: */
if (flags & O_CREAT) {
@ -61,7 +61,11 @@ __open(const char *path, int flags,...)
}
ret = __sys_open(path, flags, mode);
_thr_leave_cancellation_point(curthread);
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
_thr_cancel_leave(curthread, (ret == -1));
return ret;
}

View File

@ -43,9 +43,9 @@ _pause(void)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __pause();
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -49,9 +49,9 @@ __poll(struct pollfd *fds, unsigned int nfds, int timeout)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_poll(fds, nfds, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -81,12 +81,14 @@
#define DBG_MUTEX 0x0001
#define DBG_SIG 0x0002
#ifdef _PTHREADS_INVARIANTS
#define THR_ASSERT(cond, msg) do { \
if (!(cond)) \
PANIC(msg); \
} while (0)
#else
#define THR_ASSERT(cond, msg)
#endif
/*
* State change macro without scheduling queue change:
@ -192,15 +194,21 @@ struct kse {
int k_flags;
#define KF_STARTED 0x0001 /* kernel kse created */
#define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */
#define KF_TERMINATED 0x0004
int k_idle; /* kse is idle */
#define KF_TERMINATED 0x0004 /* kse is terminated */
#define KF_IDLE 0x0008 /* kse is idle */
#define KF_SWITCH 0x0010 /* thread switch in UTS */
int k_error; /* syscall errno in critical */
int k_cpu; /* CPU ID when bound */
int k_done; /* this KSE is done */
int k_switch; /* thread switch in UTS */
int k_sigseqno; /* signal buffered count */
};
#define KSE_SET_IDLE(kse) ((kse)->k_flags |= KF_IDLE)
#define KSE_CLEAR_IDLE(kse) ((kse)->k_flags &= ~KF_IDLE)
#define KSE_IS_IDLE(kse) (((kse)->k_flags & KF_IDLE) != 0)
#define KSE_SET_SWITCH(kse) ((kse)->k_flags |= KF_SWITCH)
#define KSE_CLEAR_SWITCH(kse) ((kse)->k_flags &= ~KF_SWITCH)
#define KSE_IS_SWITCH(kse) (((kse)->k_flags & KF_SWITCH) != 0)
/*
* Each KSE group contains one or more KSEs in which threads can run.
* At least for now, there is one scheduling queue per KSE group; KSEs
@ -293,10 +301,6 @@ do { \
#define KSE_WAKEUP(kse) kse_wakeup(&(kse)->k_kcb->kcb_kmbx)
#define KSE_SET_IDLE(kse) ((kse)->k_idle = 1)
#define KSE_CLEAR_IDLE(kse) ((kse)->k_idle = 0)
#define KSE_IS_IDLE(kse) ((kse)->k_idle != 0)
/*
* TailQ initialization values.
*/
@ -659,7 +663,6 @@ struct pthread {
int active; /* thread running */
int blocked; /* thread blocked in kernel */
int need_switchout;
int need_wakeup;
/*
* Used for tracking delivery of signal handlers.
@ -984,7 +987,15 @@ do { \
(((thrd)->state == PS_SUSPENDED) || \
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
extern int __isthreaded;
static inline int
_kse_isthreaded(void)
{
return (__isthreaded != 0);
}
/*
* Global variables for the pthread kernel.
*/
@ -1149,8 +1160,8 @@ void _thr_sig_rundown(struct pthread *, ucontext_t *,
void _thr_sig_send(struct pthread *pthread, int sig);
void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf);
void _thr_spinlock_init(void);
void _thr_enter_cancellation_point(struct pthread *);
void _thr_leave_cancellation_point(struct pthread *);
void _thr_cancel_enter(struct pthread *);
void _thr_cancel_leave(struct pthread *, int);
int _thr_setconcurrency(int new_level);
int _thr_setmaxconcurrency(void);
void _thr_critical_enter(struct pthread *);

View File

@ -49,9 +49,9 @@ _pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __pselect(count, rfds, wfds, efds, timo, mask);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -48,9 +48,9 @@ __read(int fd, void *buf, size_t nbytes)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_read(fd, buf, nbytes);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -48,9 +48,9 @@ __readv(int fd, const struct iovec *iov, int iovcnt)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_readv(fd, iov, iovcnt);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -57,9 +57,9 @@ __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
TIMEVAL_TO_TIMESPEC(timeout, &ts);
return nanosleep(&ts, NULL);
} else {
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
}
return ret;
}

View File

@ -169,7 +169,7 @@ _sem_wait(sem_t *sem)
struct pthread *curthread = _get_curthread();
int retval;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
_SEM_CHECK_VALIDITY(sem);
@ -186,7 +186,7 @@ _sem_wait(sem_t *sem)
retval = 0;
RETURN:
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (retval);
}

View File

@ -95,9 +95,9 @@ __sigsuspend(const sigset_t * set)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _sigsuspend(set);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -137,9 +137,9 @@ __sigtimedwait(const sigset_t *set, siginfo_t *info,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, info, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -155,9 +155,9 @@ __sigwaitinfo(const sigset_t *set, siginfo_t *info)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, info, NULL);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -173,7 +173,7 @@ __sigwait(const sigset_t *set, int *sig)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, NULL, NULL);
if (ret > 0) {
*sig = ret;
@ -181,7 +181,7 @@ __sigwait(const sigset_t *set, int *sig)
}
else
ret = -1;
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,9 @@ _sleep(unsigned int seconds)
struct pthread *curthread = _get_curthread();
unsigned int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sleep(seconds);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,9 @@ _system(const char *string)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __system(string);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -43,9 +43,9 @@ _tcdrain(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __tcdrain(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -42,9 +42,9 @@ _wait(int *istat)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __wait(istat);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -49,9 +49,9 @@ __wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _wait4(pid, istat, options, rusage);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -44,9 +44,9 @@ _waitpid(pid_t wpid, int *status, int options)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __waitpid(wpid, status, options);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -48,9 +48,9 @@ __write(int fd, const void *buf, size_t nbytes)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_write(fd, buf, nbytes);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -50,9 +50,9 @@ __writev(int fd, const struct iovec *iov, int iovcnt)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_writev(fd, iov, iovcnt);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -42,9 +42,9 @@ _aio_suspend(const struct aiocb * const iocbs[], int niocb, const struct
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_aio_suspend(iocbs, niocb, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -11,8 +11,35 @@ __weak_reference(_pthread_setcancelstate, pthread_setcancelstate);
__weak_reference(_pthread_setcanceltype, pthread_setcanceltype);
__weak_reference(_pthread_testcancel, pthread_testcancel);
static int checkcancel(struct pthread *curthread);
static void testcancel(struct pthread *curthread);
static inline int
checkcancel(struct pthread *curthread)
{
if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((curthread->cancelflags & THR_CANCELLING) != 0)) {
/*
* It is possible for this thread to be swapped out
* while performing cancellation; do not allow it
* to be cancelled again.
*/
curthread->cancelflags &= ~THR_CANCELLING;
return (1);
}
else
return (0);
}
static inline void
testcancel(struct pthread *curthread)
{
if (checkcancel(curthread) != 0) {
/* Unlock before exiting: */
THR_THREAD_UNLOCK(curthread, curthread);
_thr_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
PANIC("cancel");
}
}
int
_pthread_cancel(pthread_t pthread)
@ -217,37 +244,6 @@ _pthread_setcanceltype(int type, int *oldtype)
return (ret);
}
static int
checkcancel(struct pthread *curthread)
{
if (((curthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((curthread->cancelflags & THR_CANCELLING) != 0)) {
/*
* It is possible for this thread to be swapped out
* while performing cancellation; do not allow it
* to be cancelled again.
*/
curthread->cancelflags &= ~THR_CANCELLING;
return (1);
}
else
return (0);
}
static void
testcancel(struct pthread *curthread)
{
if (checkcancel(curthread) != 0) {
/* Unlock before exiting: */
THR_THREAD_UNLOCK(curthread, curthread);
_thr_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
PANIC("cancel");
}
}
void
_pthread_testcancel(void)
{
@ -259,10 +255,8 @@ _pthread_testcancel(void)
}
void
_thr_enter_cancellation_point(struct pthread *thread)
_thr_cancel_enter(struct pthread *thread)
{
if (!_kse_isthreaded())
return;
/* Look for a cancellation before we block: */
THR_THREAD_LOCK(thread, thread);
testcancel(thread);
@ -271,14 +265,13 @@ _thr_enter_cancellation_point(struct pthread *thread)
}
void
_thr_leave_cancellation_point(struct pthread *thread)
_thr_cancel_leave(struct pthread *thread, int check)
{
if (!_kse_isthreaded())
return;
THR_THREAD_LOCK(thread, thread);
thread->cancelflags &= ~THR_AT_CANCEL_POINT;
/* Look for a cancellation after we unblock: */
testcancel(thread);
if (check)
testcancel(thread);
THR_THREAD_UNLOCK(thread, thread);
}

View File

@ -47,9 +47,9 @@ __close(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_close(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -365,9 +365,9 @@ __pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _pthread_cond_wait(cond, mutex);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -571,9 +571,9 @@ __pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _pthread_cond_timedwait(cond, mutex, abstime);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,13 @@ ___creat(const char *path, mode_t mode)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __creat(path, mode);
_thr_leave_cancellation_point(curthread);
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
_thr_cancel_leave(curthread, (ret == -1));
return ret;
}

View File

@ -44,14 +44,21 @@ int
__fcntl(int fd, int cmd,...)
{
struct pthread *curthread = _get_curthread();
int ret;
int ret, check = 1;
va_list ap;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
va_start(ap, cmd);
switch (cmd) {
case F_DUPFD:
ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
check = (ret == -1);
break;
case F_SETFD:
case F_SETFL:
ret = __sys_fcntl(fd, cmd, va_arg(ap, int));
@ -65,7 +72,7 @@ __fcntl(int fd, int cmd,...)
}
va_end(ap);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, check);
return (ret);
}

View File

@ -43,9 +43,9 @@ __fsync(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_fsync(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -45,19 +45,19 @@ _pthread_join(pthread_t pthread, void **thread_return)
kse_critical_t crit;
int ret = 0;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
/* Check if the caller has specified an invalid thread: */
if (pthread == NULL || pthread->magic != THR_MAGIC) {
/* Invalid thread: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (EINVAL);
}
/* Check if the caller has specified itself: */
if (pthread == curthread) {
/* Avoid a deadlock condition: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (EDEADLK);
}
@ -67,7 +67,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
*/
if ((ret = _thr_ref_add(curthread, pthread, /*include dead*/1)) != 0) {
/* Return an error: */
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ESRCH);
}
@ -155,7 +155,7 @@ _pthread_join(pthread_t pthread, void **thread_return)
*thread_return = curthread->join_status.ret;
}
}
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
/* Return the completion status: */
return (ret);

View File

@ -389,12 +389,6 @@ _kse_init(void)
}
}
int
_kse_isthreaded(void)
{
return (__isthreaded != 0);
}
/*
* This is called when the first thread (other than the initial
* thread) is created.
@ -636,7 +630,7 @@ _thr_sched_switch_unlocked(struct pthread *curthread)
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
kse_sched_single(&curkse->k_kcb->kcb_kmbx);
else {
curkse->k_switch = 1;
KSE_SET_SWITCH(curkse);
_thread_enter_uts(curthread->tcb, curkse->k_kcb);
}
@ -696,7 +690,7 @@ kse_sched_single(struct kse_mailbox *kmbx)
curkse = (struct kse *)kmbx->km_udata;
curthread = curkse->k_curthread;
if ((curkse->k_flags & KF_INITIALIZED) == 0) {
if (__predict_false((curkse->k_flags & KF_INITIALIZED) == 0)) {
/* Setup this KSEs specific data. */
_kcb_set(curkse->k_kcb);
_tcb_set(curkse->k_kcb, curthread->tcb);
@ -914,7 +908,7 @@ kse_sched_multi(struct kse_mailbox *kmbx)
"Mailbox not null in kse_sched_multi");
/* Check for first time initialization: */
if ((curkse->k_flags & KF_INITIALIZED) == 0) {
if (__predict_false((curkse->k_flags & KF_INITIALIZED) == 0)) {
/* Setup this KSEs specific data. */
_kcb_set(curkse->k_kcb);
@ -929,9 +923,15 @@ kse_sched_multi(struct kse_mailbox *kmbx)
_tcb_set(curkse->k_kcb, NULL);
/* If this is an upcall; take the scheduler lock. */
if (curkse->k_switch == 0)
if (!KSE_IS_SWITCH(curkse))
KSE_SCHED_LOCK(curkse, curkse->k_kseg);
curkse->k_switch = 0;
else
KSE_CLEAR_SWITCH(curkse);
if (KSE_IS_IDLE(curkse)) {
KSE_CLEAR_IDLE(curkse);
curkse->k_kseg->kg_idle_kses--;
}
/*
* Now that the scheduler lock is held, get the current
@ -941,10 +941,6 @@ kse_sched_multi(struct kse_mailbox *kmbx)
*/
curthread = curkse->k_curthread;
if (KSE_IS_IDLE(curkse)) {
KSE_CLEAR_IDLE(curkse);
curkse->k_kseg->kg_idle_kses--;
}
/*
* If the current thread was completed in another KSE, then
* it will be in the run queue. Don't mark it as being blocked.
@ -2295,11 +2291,8 @@ kse_reinit(struct kse *kse, int sys_scope)
kse->k_schedq = 0;
kse->k_locklevel = 0;
kse->k_flags = 0;
kse->k_idle = 0;
kse->k_error = 0;
kse->k_cpu = 0;
kse->k_done = 0;
kse->k_switch = 0;
kse->k_sigseqno = 0;
}

View File

@ -25,9 +25,9 @@ __msync(void *addr, size_t len, int flags)
* write. The only real use of this wrapper is to guarantee
* a cancellation point, as per the standard. sigh.
*/
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_msync(addr, len, flags);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -121,9 +121,9 @@ __nanosleep(const struct timespec *time_to_sleep,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _nanosleep(time_to_sleep, time_remaining);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -50,7 +50,7 @@ __open(const char *path, int flags,...)
int mode = 0;
va_list ap;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
/* Check if the file is being created: */
if (flags & O_CREAT) {
@ -61,7 +61,11 @@ __open(const char *path, int flags,...)
}
ret = __sys_open(path, flags, mode);
_thr_leave_cancellation_point(curthread);
/*
* To avoid possible file handle leak,
* only check cancellation point if it is failure
*/
_thr_cancel_leave(curthread, (ret == -1));
return ret;
}

View File

@ -43,9 +43,9 @@ _pause(void)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __pause();
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -49,9 +49,9 @@ __poll(struct pollfd *fds, unsigned int nfds, int timeout)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_poll(fds, nfds, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -81,12 +81,14 @@
#define DBG_MUTEX 0x0001
#define DBG_SIG 0x0002
#ifdef _PTHREADS_INVARIANTS
#define THR_ASSERT(cond, msg) do { \
if (!(cond)) \
PANIC(msg); \
} while (0)
#else
#define THR_ASSERT(cond, msg)
#endif
/*
* State change macro without scheduling queue change:
@ -192,15 +194,21 @@ struct kse {
int k_flags;
#define KF_STARTED 0x0001 /* kernel kse created */
#define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */
#define KF_TERMINATED 0x0004
int k_idle; /* kse is idle */
#define KF_TERMINATED 0x0004 /* kse is terminated */
#define KF_IDLE 0x0008 /* kse is idle */
#define KF_SWITCH 0x0010 /* thread switch in UTS */
int k_error; /* syscall errno in critical */
int k_cpu; /* CPU ID when bound */
int k_done; /* this KSE is done */
int k_switch; /* thread switch in UTS */
int k_sigseqno; /* signal buffered count */
};
#define KSE_SET_IDLE(kse) ((kse)->k_flags |= KF_IDLE)
#define KSE_CLEAR_IDLE(kse) ((kse)->k_flags &= ~KF_IDLE)
#define KSE_IS_IDLE(kse) (((kse)->k_flags & KF_IDLE) != 0)
#define KSE_SET_SWITCH(kse) ((kse)->k_flags |= KF_SWITCH)
#define KSE_CLEAR_SWITCH(kse) ((kse)->k_flags &= ~KF_SWITCH)
#define KSE_IS_SWITCH(kse) (((kse)->k_flags & KF_SWITCH) != 0)
/*
* Each KSE group contains one or more KSEs in which threads can run.
* At least for now, there is one scheduling queue per KSE group; KSEs
@ -293,10 +301,6 @@ do { \
#define KSE_WAKEUP(kse) kse_wakeup(&(kse)->k_kcb->kcb_kmbx)
#define KSE_SET_IDLE(kse) ((kse)->k_idle = 1)
#define KSE_CLEAR_IDLE(kse) ((kse)->k_idle = 0)
#define KSE_IS_IDLE(kse) ((kse)->k_idle != 0)
/*
* TailQ initialization values.
*/
@ -659,7 +663,6 @@ struct pthread {
int active; /* thread running */
int blocked; /* thread blocked in kernel */
int need_switchout;
int need_wakeup;
/*
* Used for tracking delivery of signal handlers.
@ -984,7 +987,15 @@ do { \
(((thrd)->state == PS_SUSPENDED) || \
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
extern int __isthreaded;
static inline int
_kse_isthreaded(void)
{
return (__isthreaded != 0);
}
/*
* Global variables for the pthread kernel.
*/
@ -1149,8 +1160,8 @@ void _thr_sig_rundown(struct pthread *, ucontext_t *,
void _thr_sig_send(struct pthread *pthread, int sig);
void _thr_sigframe_restore(struct pthread *thread, struct pthread_sigframe *psf);
void _thr_spinlock_init(void);
void _thr_enter_cancellation_point(struct pthread *);
void _thr_leave_cancellation_point(struct pthread *);
void _thr_cancel_enter(struct pthread *);
void _thr_cancel_leave(struct pthread *, int);
int _thr_setconcurrency(int new_level);
int _thr_setmaxconcurrency(void);
void _thr_critical_enter(struct pthread *);

View File

@ -49,9 +49,9 @@ _pselect(int count, fd_set *rfds, fd_set *wfds, fd_set *efds,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __pselect(count, rfds, wfds, efds, timo, mask);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -48,9 +48,9 @@ __read(int fd, void *buf, size_t nbytes)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_read(fd, buf, nbytes);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -48,9 +48,9 @@ __readv(int fd, const struct iovec *iov, int iovcnt)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_readv(fd, iov, iovcnt);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -57,9 +57,9 @@ __select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,
TIMEVAL_TO_TIMESPEC(timeout, &ts);
return nanosleep(&ts, NULL);
} else {
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_select(numfds, readfds, writefds, exceptfds, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
}
return ret;
}

View File

@ -169,7 +169,7 @@ _sem_wait(sem_t *sem)
struct pthread *curthread = _get_curthread();
int retval;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
_SEM_CHECK_VALIDITY(sem);
@ -186,7 +186,7 @@ _sem_wait(sem_t *sem)
retval = 0;
RETURN:
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (retval);
}

View File

@ -95,9 +95,9 @@ __sigsuspend(const sigset_t * set)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _sigsuspend(set);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -137,9 +137,9 @@ __sigtimedwait(const sigset_t *set, siginfo_t *info,
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, info, timeout);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -155,9 +155,9 @@ __sigwaitinfo(const sigset_t *set, siginfo_t *info)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, info, NULL);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}
@ -173,7 +173,7 @@ __sigwait(const sigset_t *set, int *sig)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = lib_sigtimedwait(set, NULL, NULL);
if (ret > 0) {
*sig = ret;
@ -181,7 +181,7 @@ __sigwait(const sigset_t *set, int *sig)
}
else
ret = -1;
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,9 @@ _sleep(unsigned int seconds)
struct pthread *curthread = _get_curthread();
unsigned int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sleep(seconds);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -43,9 +43,9 @@ _system(const char *string)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __system(string);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -43,9 +43,9 @@ _tcdrain(int fd)
struct pthread *curthread = _get_curthread();
int ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __tcdrain(fd);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return (ret);
}

View File

@ -42,9 +42,9 @@ _wait(int *istat)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __wait(istat);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -49,9 +49,9 @@ __wait4(pid_t pid, int *istat, int options, struct rusage *rusage)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = _wait4(pid, istat, options, rusage);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -44,9 +44,9 @@ _waitpid(pid_t wpid, int *status, int options)
struct pthread *curthread = _get_curthread();
pid_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __waitpid(wpid, status, options);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -48,9 +48,9 @@ __write(int fd, const void *buf, size_t nbytes)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_write(fd, buf, nbytes);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}

View File

@ -50,9 +50,9 @@ __writev(int fd, const struct iovec *iov, int iovcnt)
struct pthread *curthread = _get_curthread();
ssize_t ret;
_thr_enter_cancellation_point(curthread);
_thr_cancel_enter(curthread);
ret = __sys_writev(fd, iov, iovcnt);
_thr_leave_cancellation_point(curthread);
_thr_cancel_leave(curthread, 1);
return ret;
}