Fix suspend and resume.

Submitted (in part) by:	Kazuaki Oda <kaakun@highway.ne.jp>
This commit is contained in:
Daniel Eischen 2003-05-04 16:17:01 +00:00
parent 452855111a
commit 40791d9d15
12 changed files with 94 additions and 86 deletions

View File

@ -259,8 +259,10 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->flags = 0;
new_thread->continuation = NULL;
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
new_thread->state = PS_SUSPENDED;
new_thread->flags = THR_FLAGS_SUSPENDED;
}
else
new_thread->state = PS_RUNNING;

View File

@ -913,10 +913,6 @@ kse_sched_multi(struct kse *curkse)
if ((curframe == NULL) && (curthread->check_pending != 0))
signalcontext(&curthread->tmbx.tm_context, 0,
(__sighandler_t *)thr_resume_wrapper);
#endif
#ifdef GS_HACK
/* XXX - The kernel sometimes forgets to restore %gs properly. */
_ksd_setprivate(&curkse->k_ksd);
#endif
/*
* Continue the thread at its current frame:
@ -1259,8 +1255,12 @@ kse_check_completed(struct kse *kse)
thread,
(thread->name == NULL) ? "none" : thread->name);
thread->blocked = 0;
if (thread != kse->k_curthread)
KSE_RUNQ_INSERT_TAIL(kse, thread);
if (thread != kse->k_curthread) {
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else
KSE_RUNQ_INSERT_TAIL(kse, thread);
}
completed = completed->tm_next;
}
}
@ -1293,8 +1293,12 @@ kse_check_waitq(struct kse *kse)
pthread->timeout = 1;
/* Add the thread to the priority queue: */
THR_SET_STATE(pthread, PS_RUNNING);
KSE_RUNQ_INSERT_TAIL(kse, pthread);
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(pthread, PS_SUSPENDED);
else {
THR_SET_STATE(pthread, PS_RUNNING);
KSE_RUNQ_INSERT_TAIL(kse, pthread);
}
}
}
@ -1390,7 +1394,8 @@ kse_switchout_thread(struct kse *kse, struct pthread *thread)
break;
case PS_RUNNING:
/* Nothing to do here. */
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
break;
case PS_COND_WAIT:
@ -1662,16 +1667,23 @@ _thr_setrunnable(struct pthread *curthread, struct pthread *thread)
void
_thr_setrunnable_unlocked(struct pthread *thread)
{
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0)
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0) {
/* No silly queues for these threads. */
THR_SET_STATE(thread, PS_RUNNING);
else if (thread->state != PS_RUNNING) {
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else
THR_SET_STATE(thread, PS_RUNNING);
}else if (thread->state != PS_RUNNING) {
if ((thread->flags & THR_FLAGS_IN_WAITQ) != 0)
KSE_WAITQ_REMOVE(thread->kse, thread);
THR_SET_STATE(thread, PS_RUNNING);
if ((thread->blocked == 0) &&
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(thread);
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else {
THR_SET_STATE(thread, PS_RUNNING);
if ((thread->blocked == 0) &&
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(thread);
}
}
/*
* XXX - Threads are not yet assigned to specific KSEs; they are

View File

@ -953,6 +953,11 @@ do { \
((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd))
#define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
#define THR_IS_SUSPENDED(thrd) \
(((thrd)->state == PS_SUSPENDED) || \
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
/*
* Global variables for the pthread kernel.

View File

@ -50,19 +50,10 @@ _pthread_resume_np(pthread_t thread)
/* Add a reference to the thread: */
if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) {
/* Is it currently suspended? */
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0) {
/* Lock the threads scheduling queue: */
THR_SCHED_LOCK(curthread, thread);
if ((curthread->state != PS_DEAD) &&
(curthread->state != PS_DEADLOCK) &&
((curthread->flags & THR_FLAGS_EXITING) != 0))
resume_common(thread);
/* Unlock the threads scheduling queue: */
THR_SCHED_UNLOCK(curthread, thread);
}
/* Lock the threads scheduling queue: */
THR_SCHED_LOCK(curthread, thread);
resume_common(thread);
THR_SCHED_UNLOCK(curthread, thread);
_thr_ref_delete(curthread, thread);
}
return (ret);
@ -80,11 +71,7 @@ _pthread_resume_all_np(void)
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock);
TAILQ_FOREACH(thread, &_thread_list, tle) {
if ((thread != curthread) &&
((thread->flags & THR_FLAGS_SUSPENDED) != 0) &&
(thread->state != PS_DEAD) &&
(thread->state != PS_DEADLOCK) &&
((thread->flags & THR_FLAGS_EXITING) == 0)) {
if (thread != curthread) {
THR_SCHED_LOCK(curthread, thread);
resume_common(thread);
THR_SCHED_UNLOCK(curthread, thread);

View File

@ -316,11 +316,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
}
else if ((pthread->state == PS_DEAD) ||
(pthread->state == PS_DEADLOCK) ||
((pthread->flags & THR_FLAGS_EXITING) != 0))
THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
; /* Skip this thread. */
else if ((handler_installed != 0) &&
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig) &&
((pthread->flags & THR_FLAGS_SUSPENDED) == 0)) {
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
if (pthread->state == PS_SIGSUSPEND) {
if (suspended_thread == NULL)
suspended_thread = pthread;
@ -710,9 +709,7 @@ thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
* will run the signal handler when it is resumed.
*/
pthread->active_priority |= THR_SIGNAL_PRIORITY;
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(pthread, PS_SUSPENDED);
else if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(pthread);
}
}

View File

@ -97,9 +97,10 @@ suspend_common(struct pthread *thread)
(thread->state != PS_DEADLOCK) &&
((thread->flags & THR_FLAGS_EXITING) == 0)) {
thread->flags |= THR_FLAGS_SUSPENDED;
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0)
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0) {
THR_RUNQ_REMOVE(thread);
THR_SET_STATE(thread, PS_SUSPENDED);
THR_SET_STATE(thread, PS_SUSPENDED);
}
#ifdef NOT_YET
if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0)
/* ??? */

View File

@ -259,8 +259,10 @@ _pthread_create(pthread_t * thread, const pthread_attr_t * attr,
new_thread->flags = 0;
new_thread->continuation = NULL;
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED)
if (new_thread->attr.suspend == THR_CREATE_SUSPENDED) {
new_thread->state = PS_SUSPENDED;
new_thread->flags = THR_FLAGS_SUSPENDED;
}
else
new_thread->state = PS_RUNNING;

View File

@ -913,10 +913,6 @@ kse_sched_multi(struct kse *curkse)
if ((curframe == NULL) && (curthread->check_pending != 0))
signalcontext(&curthread->tmbx.tm_context, 0,
(__sighandler_t *)thr_resume_wrapper);
#endif
#ifdef GS_HACK
/* XXX - The kernel sometimes forgets to restore %gs properly. */
_ksd_setprivate(&curkse->k_ksd);
#endif
/*
* Continue the thread at its current frame:
@ -1259,8 +1255,12 @@ kse_check_completed(struct kse *kse)
thread,
(thread->name == NULL) ? "none" : thread->name);
thread->blocked = 0;
if (thread != kse->k_curthread)
KSE_RUNQ_INSERT_TAIL(kse, thread);
if (thread != kse->k_curthread) {
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else
KSE_RUNQ_INSERT_TAIL(kse, thread);
}
completed = completed->tm_next;
}
}
@ -1293,8 +1293,12 @@ kse_check_waitq(struct kse *kse)
pthread->timeout = 1;
/* Add the thread to the priority queue: */
THR_SET_STATE(pthread, PS_RUNNING);
KSE_RUNQ_INSERT_TAIL(kse, pthread);
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(pthread, PS_SUSPENDED);
else {
THR_SET_STATE(pthread, PS_RUNNING);
KSE_RUNQ_INSERT_TAIL(kse, pthread);
}
}
}
@ -1390,7 +1394,8 @@ kse_switchout_thread(struct kse *kse, struct pthread *thread)
break;
case PS_RUNNING:
/* Nothing to do here. */
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
break;
case PS_COND_WAIT:
@ -1662,16 +1667,23 @@ _thr_setrunnable(struct pthread *curthread, struct pthread *thread)
void
_thr_setrunnable_unlocked(struct pthread *thread)
{
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0)
if ((thread->kseg->kg_flags & KGF_SINGLE_THREAD) != 0) {
/* No silly queues for these threads. */
THR_SET_STATE(thread, PS_RUNNING);
else if (thread->state != PS_RUNNING) {
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else
THR_SET_STATE(thread, PS_RUNNING);
}else if (thread->state != PS_RUNNING) {
if ((thread->flags & THR_FLAGS_IN_WAITQ) != 0)
KSE_WAITQ_REMOVE(thread->kse, thread);
THR_SET_STATE(thread, PS_RUNNING);
if ((thread->blocked == 0) &&
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(thread);
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(thread, PS_SUSPENDED);
else {
THR_SET_STATE(thread, PS_RUNNING);
if ((thread->blocked == 0) &&
(thread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(thread);
}
}
/*
* XXX - Threads are not yet assigned to specific KSEs; they are

View File

@ -953,6 +953,11 @@ do { \
((thrd)->kse != NULL) && ((thrd)->kse->k_curthread == (thrd))
#define THR_IN_SYNCQ(thrd) (((thrd)->sflags & THR_FLAGS_IN_SYNCQ) != 0)
#define THR_IS_SUSPENDED(thrd) \
(((thrd)->state == PS_SUSPENDED) || \
(((thrd)->flags & THR_FLAGS_SUSPENDED) != 0))
#define THR_IS_EXITING(thrd) (((thrd)->flags & THR_FLAGS_EXITING) != 0)
/*
* Global variables for the pthread kernel.

View File

@ -50,19 +50,10 @@ _pthread_resume_np(pthread_t thread)
/* Add a reference to the thread: */
if ((ret = _thr_ref_add(curthread, thread, /*include dead*/0)) == 0) {
/* Is it currently suspended? */
if ((thread->flags & THR_FLAGS_SUSPENDED) != 0) {
/* Lock the threads scheduling queue: */
THR_SCHED_LOCK(curthread, thread);
if ((curthread->state != PS_DEAD) &&
(curthread->state != PS_DEADLOCK) &&
((curthread->flags & THR_FLAGS_EXITING) != 0))
resume_common(thread);
/* Unlock the threads scheduling queue: */
THR_SCHED_UNLOCK(curthread, thread);
}
/* Lock the threads scheduling queue: */
THR_SCHED_LOCK(curthread, thread);
resume_common(thread);
THR_SCHED_UNLOCK(curthread, thread);
_thr_ref_delete(curthread, thread);
}
return (ret);
@ -80,11 +71,7 @@ _pthread_resume_all_np(void)
KSE_LOCK_ACQUIRE(curthread->kse, &_thread_list_lock);
TAILQ_FOREACH(thread, &_thread_list, tle) {
if ((thread != curthread) &&
((thread->flags & THR_FLAGS_SUSPENDED) != 0) &&
(thread->state != PS_DEAD) &&
(thread->state != PS_DEADLOCK) &&
((thread->flags & THR_FLAGS_EXITING) == 0)) {
if (thread != curthread) {
THR_SCHED_LOCK(curthread, thread);
resume_common(thread);
THR_SCHED_UNLOCK(curthread, thread);

View File

@ -316,11 +316,10 @@ thr_sig_find(struct kse *curkse, int sig, siginfo_t *info)
}
else if ((pthread->state == PS_DEAD) ||
(pthread->state == PS_DEADLOCK) ||
((pthread->flags & THR_FLAGS_EXITING) != 0))
THR_IS_EXITING(pthread) || THR_IS_SUSPENDED(pthread))
; /* Skip this thread. */
else if ((handler_installed != 0) &&
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig) &&
((pthread->flags & THR_FLAGS_SUSPENDED) == 0)) {
!sigismember(&pthread->tmbx.tm_context.uc_sigmask, sig)) {
if (pthread->state == PS_SIGSUSPEND) {
if (suspended_thread == NULL)
suspended_thread = pthread;
@ -710,9 +709,7 @@ thr_sig_add(struct pthread *pthread, int sig, siginfo_t *info)
* will run the signal handler when it is resumed.
*/
pthread->active_priority |= THR_SIGNAL_PRIORITY;
if ((pthread->flags & THR_FLAGS_SUSPENDED) != 0)
THR_SET_STATE(pthread, PS_SUSPENDED);
else if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
if ((pthread->flags & THR_FLAGS_IN_RUNQ) == 0)
THR_RUNQ_INSERT_TAIL(pthread);
}
}

View File

@ -97,9 +97,10 @@ suspend_common(struct pthread *thread)
(thread->state != PS_DEADLOCK) &&
((thread->flags & THR_FLAGS_EXITING) == 0)) {
thread->flags |= THR_FLAGS_SUSPENDED;
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0)
if ((thread->flags & THR_FLAGS_IN_RUNQ) != 0) {
THR_RUNQ_REMOVE(thread);
THR_SET_STATE(thread, PS_SUSPENDED);
THR_SET_STATE(thread, PS_SUSPENDED);
}
#ifdef NOT_YET
if ((thread->attr.flags & PTHREAD_SCOPE_SYSTEM) != 0)
/* ??? */