Fix problems with cancellation while in critical regions.

o Cancellation flags were not getting properly set/cleared.
  o Loops waiting for internal locks were not being exited
    correctly by a cancelled thread.
  o Minor spelling (cancelation -> cancellation) and formatting
    corrections (missing tab).

Found by:	tg
Reviewed by:	jasone
This commit is contained in:
deischen 1999-12-17 00:57:54 +00:00
parent 5cb0438d6f
commit 7e691e1eb4
20 changed files with 95 additions and 40 deletions

View File

@ -20,8 +20,16 @@ pthread_cancel(pthread_t pthread)
/* Protect the scheduling queues: */
_thread_kern_sig_defer();
/* Check if we need to kick it back into the run queue: */
if ((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0)
if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) ||
(((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) &&
((pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0)))
/* Just mark it for cancellation: */
pthread->cancelflags |= PTHREAD_CANCELLING;
else {
/*
* Check if we need to kick it back into the
* run queue:
*/
switch (pthread->state) {
case PS_RUNNING:
/* No need to resume: */
@ -33,7 +41,7 @@ pthread_cancel(pthread_t pthread)
case PS_FDW_WAIT:
case PS_POLL_WAIT:
case PS_SELECT_WAIT:
/* Remove these threads from the work queue: */
/* Remove these threads from the work queue: */
if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
!= 0)
PTHREAD_WORKQ_REMOVE(pthread);
@ -75,7 +83,9 @@ pthread_cancel(pthread_t pthread)
case PS_STATE_MAX:
/* Ignore - only here to silence -Wall: */
break;
}
}
/* Unprotect the scheduling queues: */
_thread_kern_sig_undefer();
@ -96,7 +106,7 @@ pthread_setcancelstate(int state, int *oldstate)
case PTHREAD_CANCEL_ENABLE:
if (oldstate != NULL)
*oldstate = ostate;
_thread_run->cancelflags &= PTHREAD_CANCEL_ENABLE;
_thread_run->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
if ((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
pthread_testcancel();
ret = 0;
@ -145,7 +155,6 @@ pthread_setcanceltype(int type, int *oldtype)
void
pthread_testcancel(void)
{
if (((_thread_run->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCELLING) != 0)) {
/*

View File

@ -274,6 +274,7 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}
@ -431,6 +432,7 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -398,12 +398,13 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
}
/* Check the file descriptor and lock types: */
if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
if (_thread_run->interrupted == 0 &&
(lock_type == FD_WRITE || lock_type == FD_RDWR)) {
/*
* Enter a loop to wait for the file descriptor to be
* locked for write for the current thread:
* Wait for the file descriptor to be locked
* for write for the current thread:
*/
while (_thread_fd_table[fd]->w_owner != _thread_run) {
if (_thread_fd_table[fd]->w_owner != _thread_run) {
/*
* Check if the file descriptor is locked by
* another thread:
@ -483,6 +484,7 @@ _thread_fd_lock(int fd, int lock_type, struct timespec * timeout)
ret = -1;
errno = EINTR;
} else {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}
@ -639,10 +641,10 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
/* Check the file descriptor and lock types: */
if (lock_type == FD_READ || lock_type == FD_RDWR) {
/*
* Enter a loop to wait for the file descriptor to be
* locked for read for the current thread:
* Wait for the file descriptor to be locked
* for read for the current thread:
*/
while (_thread_fd_table[fd]->r_owner != _thread_run) {
if (_thread_fd_table[fd]->r_owner != _thread_run) {
/*
* Check if the file descriptor is locked by
* another thread:
@ -691,6 +693,10 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
*/
_SPINLOCK(&_thread_fd_table[fd]->lock);
if (_thread_run->interrupted != 0) {
FDQ_REMOVE(&_thread_fd_table[fd]->r_queue,
_thread_run);
}
} else {
/*
* The running thread now owns the
@ -713,17 +719,19 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
}
}
/* Increment the read lock count: */
_thread_fd_table[fd]->r_lockcount++;
if (_thread_fd_table[fd]->r_owner == _thread_run)
/* Increment the read lock count: */
_thread_fd_table[fd]->r_lockcount++;
}
/* Check the file descriptor and lock types: */
if (lock_type == FD_WRITE || lock_type == FD_RDWR) {
if (_thread_run->interrupted == 0 &&
(lock_type == FD_WRITE || lock_type == FD_RDWR)) {
/*
* Enter a loop to wait for the file descriptor to be
* locked for write for the current thread:
* Wait for the file descriptor to be locked
* for write for the current thread:
*/
while (_thread_fd_table[fd]->w_owner != _thread_run) {
if (_thread_fd_table[fd]->w_owner != _thread_run) {
/*
* Check if the file descriptor is locked by
* another thread:
@ -771,6 +779,11 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
* table entry again:
*/
_SPINLOCK(&_thread_fd_table[fd]->lock);
if (_thread_run->interrupted != 0) {
FDQ_REMOVE(&_thread_fd_table[fd]->w_queue,
_thread_run);
}
} else {
/*
* The running thread now owns the
@ -794,8 +807,9 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
}
}
/* Increment the write lock count: */
_thread_fd_table[fd]->w_lockcount++;
if (_thread_fd_table[fd]->w_owner == _thread_run)
/* Increment the write lock count: */
_thread_fd_table[fd]->w_lockcount++;
}
/* Unlock the file descriptor table entry: */
@ -806,6 +820,7 @@ _thread_fd_lock_debug(int fd, int lock_type, struct timespec * timeout,
ret = -1;
errno = EINTR;
} else {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -256,7 +256,8 @@ _flockfile_debug(FILE * fp, char *fname, int lineno)
_thread_kern_sig_undefer();
if (((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) &&
(_thread_run->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) {
(_thread_run->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -98,6 +98,7 @@ pthread_join(pthread_t pthread, void **thread_return)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -111,7 +111,7 @@ __asm__("fnsave %0": :"m"(*fdata));
if (((_thread_run->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) {
/*
* Cancelations override signals.
* Cancellations override signals.
*
* Stick a cancellation point at the start of
* each async-cancellable thread's resumption.

View File

@ -623,6 +623,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -67,8 +67,8 @@ write(int fd, const void *buf, size_t nbytes)
/* File is not open for write: */
errno = EBADF;
_FD_UNLOCK(fd, FD_WRITE);
_thread_leave_cancellation_point();
return (-1);
_thread_leave_cancellation_point();
return (-1);
}
/* Check if file operations are to block */

View File

@ -20,8 +20,16 @@ pthread_cancel(pthread_t pthread)
/* Protect the scheduling queues: */
_thread_kern_sig_defer();
/* Check if we need to kick it back into the run queue: */
if ((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0)
if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) ||
(((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) &&
((pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0)))
/* Just mark it for cancellation: */
pthread->cancelflags |= PTHREAD_CANCELLING;
else {
/*
* Check if we need to kick it back into the
* run queue:
*/
switch (pthread->state) {
case PS_RUNNING:
/* No need to resume: */
@ -33,7 +41,7 @@ pthread_cancel(pthread_t pthread)
case PS_FDW_WAIT:
case PS_POLL_WAIT:
case PS_SELECT_WAIT:
/* Remove these threads from the work queue: */
/* Remove these threads from the work queue: */
if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
!= 0)
PTHREAD_WORKQ_REMOVE(pthread);
@ -75,7 +83,9 @@ pthread_cancel(pthread_t pthread)
case PS_STATE_MAX:
/* Ignore - only here to silence -Wall: */
break;
}
}
/* Unprotect the scheduling queues: */
_thread_kern_sig_undefer();
@ -96,7 +106,7 @@ pthread_setcancelstate(int state, int *oldstate)
case PTHREAD_CANCEL_ENABLE:
if (oldstate != NULL)
*oldstate = ostate;
_thread_run->cancelflags &= PTHREAD_CANCEL_ENABLE;
_thread_run->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
if ((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
pthread_testcancel();
ret = 0;
@ -145,7 +155,6 @@ pthread_setcanceltype(int type, int *oldtype)
void
pthread_testcancel(void)
{
if (((_thread_run->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCELLING) != 0)) {
/*

View File

@ -274,6 +274,7 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}
@ -431,6 +432,7 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -98,6 +98,7 @@ pthread_join(pthread_t pthread, void **thread_return)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -111,7 +111,7 @@ __asm__("fnsave %0": :"m"(*fdata));
if (((_thread_run->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) {
/*
* Cancelations override signals.
* Cancellations override signals.
*
* Stick a cancellation point at the start of
* each async-cancellable thread's resumption.

View File

@ -623,6 +623,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -67,8 +67,8 @@ write(int fd, const void *buf, size_t nbytes)
/* File is not open for write: */
errno = EBADF;
_FD_UNLOCK(fd, FD_WRITE);
_thread_leave_cancellation_point();
return (-1);
_thread_leave_cancellation_point();
return (-1);
}
/* Check if file operations are to block */

View File

@ -20,8 +20,16 @@ pthread_cancel(pthread_t pthread)
/* Protect the scheduling queues: */
_thread_kern_sig_defer();
/* Check if we need to kick it back into the run queue: */
if ((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) == 0)
if (((pthread->cancelflags & PTHREAD_CANCEL_DISABLE) != 0) ||
(((pthread->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) == 0) &&
((pthread->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0)))
/* Just mark it for cancellation: */
pthread->cancelflags |= PTHREAD_CANCELLING;
else {
/*
* Check if we need to kick it back into the
* run queue:
*/
switch (pthread->state) {
case PS_RUNNING:
/* No need to resume: */
@ -33,7 +41,7 @@ pthread_cancel(pthread_t pthread)
case PS_FDW_WAIT:
case PS_POLL_WAIT:
case PS_SELECT_WAIT:
/* Remove these threads from the work queue: */
/* Remove these threads from the work queue: */
if ((pthread->flags & PTHREAD_FLAGS_IN_WORKQ)
!= 0)
PTHREAD_WORKQ_REMOVE(pthread);
@ -75,7 +83,9 @@ pthread_cancel(pthread_t pthread)
case PS_STATE_MAX:
/* Ignore - only here to silence -Wall: */
break;
}
}
/* Unprotect the scheduling queues: */
_thread_kern_sig_undefer();
@ -96,7 +106,7 @@ pthread_setcancelstate(int state, int *oldstate)
case PTHREAD_CANCEL_ENABLE:
if (oldstate != NULL)
*oldstate = ostate;
_thread_run->cancelflags &= PTHREAD_CANCEL_ENABLE;
_thread_run->cancelflags &= ~PTHREAD_CANCEL_DISABLE;
if ((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)
pthread_testcancel();
ret = 0;
@ -145,7 +155,6 @@ pthread_setcanceltype(int type, int *oldtype)
void
pthread_testcancel(void)
{
if (((_thread_run->cancelflags & PTHREAD_CANCEL_DISABLE) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCELLING) != 0)) {
/*

View File

@ -274,6 +274,7 @@ pthread_cond_wait(pthread_cond_t * cond, pthread_mutex_t * mutex)
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}
@ -431,6 +432,7 @@ pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
}
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -98,6 +98,7 @@ pthread_join(pthread_t pthread, void **thread_return)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -111,7 +111,7 @@ __asm__("fnsave %0": :"m"(*fdata));
if (((_thread_run->cancelflags & PTHREAD_AT_CANCEL_POINT) == 0) &&
((_thread_run->cancelflags & PTHREAD_CANCEL_ASYNCHRONOUS) != 0)) {
/*
* Cancelations override signals.
* Cancellations override signals.
*
* Stick a cancellation point at the start of
* each async-cancellable thread's resumption.

View File

@ -623,6 +623,7 @@ pthread_mutex_lock(pthread_mutex_t * mutex)
_thread_kern_sig_undefer();
if ((_thread_run->cancelflags & PTHREAD_CANCEL_NEEDED) != 0) {
_thread_run->cancelflags &= ~PTHREAD_CANCEL_NEEDED;
_thread_exit_cleanup();
pthread_exit(PTHREAD_CANCELED);
}

View File

@ -67,8 +67,8 @@ write(int fd, const void *buf, size_t nbytes)
/* File is not open for write: */
errno = EBADF;
_FD_UNLOCK(fd, FD_WRITE);
_thread_leave_cancellation_point();
return (-1);
_thread_leave_cancellation_point();
return (-1);
}
/* Check if file operations are to block */