From 38b1c6f405309b401590f880ea669e8b68f59990 Mon Sep 17 00:00:00 2001 From: christos Date: Sun, 9 Nov 2003 18:56:48 +0000 Subject: [PATCH] Add: int pthread_attr_setcreatesuspend_np(pthread_attr_t *); int pthread_suspend_np(pthread_t); int pthread_resume_np(pthread_t); needed for java. Approved and fixed by cl. --- lib/libpthread/pthread.c | 75 +++++++++++++++++++++++++++++++++-- lib/libpthread/pthread.h | 6 ++- lib/libpthread/pthread_attr.c | 11 ++++- lib/libpthread/pthread_int.h | 6 ++- lib/libpthread/pthread_run.c | 27 +++++++++++-- lib/libpthread/pthread_sig.c | 12 +++++- 6 files changed, 124 insertions(+), 13 deletions(-) diff --git a/lib/libpthread/pthread.c b/lib/libpthread/pthread.c index 1f38d914409e..2879f36c0cf4 100644 --- a/lib/libpthread/pthread.c +++ b/lib/libpthread/pthread.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread.c,v 1.29 2003/08/13 18:52:01 nathanw Exp $ */ +/* $NetBSD: pthread.c,v 1.30 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__RCSID("$NetBSD: pthread.c,v 1.29 2003/08/13 18:52:01 nathanw Exp $"); +__RCSID("$NetBSD: pthread.c,v 1.30 2003/11/09 18:56:48 christos Exp $"); #include #include @@ -87,6 +87,7 @@ static int pthread__diagassert = DIAGASSERT_ABORT | DIAGASSERT_STDERR; pthread_spin_t pthread__runqueue_lock; struct pthread_queue_t pthread__runqueue; struct pthread_queue_t pthread__idlequeue; +struct pthread_queue_t pthread__suspqueue; __strong_alias(__libc_thr_self,pthread_self) __strong_alias(__libc_thr_create,pthread_create) @@ -355,8 +356,13 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, pthread_spinunlock(self, &pthread__allqueue_lock); SDPRINTF(("(pthread_create %p) Created new thread %p (name pointer %p).\n", self, newthread, newthread->pt_name)); - /* 6. Put on run queue. */ - pthread__sched(self, newthread); + /* 6. Put on appropriate queue. */ + if (newthread->pt_flags & PT_FLAG_SUSPENDED) { + pthread_spinlock(self, &newthread->pt_statelock); + pthread__suspend(self, newthread); + pthread_spinunlock(self, &newthread->pt_statelock); + } else + pthread__sched(self, newthread); *thread = newthread; @@ -377,6 +383,67 @@ pthread__create_tramp(void *(*start)(void *), void *arg) pthread__abort(); } +int +pthread_suspend_np(pthread_t thread) +{ + pthread_t self = pthread__self(); + if (self == thread) { + fprintf(stderr, "suspend_np: can't suspend self\n"); + return EDEADLK; + } + SDPRINTF(("(pthread_suspend_np %p) Suspend thread %p (state %d).\n", + self, thread, thread->pt_state)); + pthread_spinlock(self, &thread->pt_statelock); + switch (thread->pt_state) { + case PT_STATE_RUNNING: + pthread__abort(); /* XXX */ + break; + case PT_STATE_SUSPENDED: + pthread_spinunlock(self, &thread->pt_statelock); + return 0; + case PT_STATE_RUNNABLE: + pthread_spinlock(self, &pthread__runqueue_lock); + PTQ_REMOVE(&pthread__runqueue, thread, pt_runq); + pthread_spinunlock(self, &pthread__runqueue_lock); + break; + case PT_STATE_BLOCKED_QUEUE: + pthread_spinlock(self, thread->pt_sleeplock); + PTQ_REMOVE(thread->pt_sleepq, thread, pt_sleep); + pthread_spinunlock(self, thread->pt_sleeplock); + break; + case PT_STATE_BLOCKED_SYS: + /* XXX flaglock? */ + thread->pt_flags |= PT_FLAG_SUSPENDED; + pthread_spinunlock(self, &thread->pt_statelock); + return 0; + default: + break; /* XXX */ + } + pthread__suspend(self, thread); + pthread_spinunlock(self, &thread->pt_statelock); + return 0; +} + +int +pthread_resume_np(pthread_t thread) +{ + + pthread_t self = pthread__self(); + SDPRINTF(("(pthread_resume_np %p) Resume thread %p (state %d).\n", + self, thread, thread->pt_state)); + pthread_spinlock(self, &thread->pt_statelock); + /* XXX flaglock? */ + thread->pt_flags &= ~PT_FLAG_SUSPENDED; + if (thread->pt_state == PT_STATE_SUSPENDED) { + pthread_spinlock(self, &pthread__runqueue_lock); + PTQ_REMOVE(&pthread__suspqueue, thread, pt_runq); + pthread_spinunlock(self, &pthread__runqueue_lock); + pthread__sched(self, thread); + } + pthread_spinunlock(self, &thread->pt_statelock); + return 0; +} + /* * Other threads will switch to the idle thread so that they diff --git a/lib/libpthread/pthread.h b/lib/libpthread/pthread.h index c02c8a8cdb05..a5449675c99d 100644 --- a/lib/libpthread/pthread.h +++ b/lib/libpthread/pthread.h @@ -1,4 +1,4 @@ -/* $NetBSD: pthread.h,v 1.14 2003/07/18 22:01:47 nathanw Exp $ */ +/* $NetBSD: pthread.h,v 1.15 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -119,6 +119,10 @@ void pthread_testcancel(void); int pthread_getname_np(pthread_t, char *, size_t); int pthread_setname_np(pthread_t, const char *, void *); +int pthread_attr_setcreatesuspend_np(pthread_attr_t *); +int pthread_suspend_np(pthread_t); +int pthread_resume_np(pthread_t); + struct pthread_cleanup_store { void *pad[4]; }; diff --git a/lib/libpthread/pthread_attr.c b/lib/libpthread/pthread_attr.c index 9d9571153013..acb22e78b3c5 100644 --- a/lib/libpthread/pthread_attr.c +++ b/lib/libpthread/pthread_attr.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_attr.c,v 1.2 2003/09/11 21:51:57 christos Exp $ */ +/* $NetBSD: pthread_attr.c,v 1.3 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__RCSID("$NetBSD: pthread_attr.c,v 1.2 2003/09/11 21:51:57 christos Exp $"); +__RCSID("$NetBSD: pthread_attr.c,v 1.3 2003/11/09 18:56:48 christos Exp $"); #include #include @@ -397,3 +397,10 @@ pthread_attr_setname_np(pthread_attr_t *attr, const char *name, void *arg) return 0; } + +int +pthread_attr_setcreatesuspend_np(pthread_attr_t *attr) +{ + attr->pta_flags |= PT_FLAG_SUSPENDED; + return 0; +} diff --git a/lib/libpthread/pthread_int.h b/lib/libpthread/pthread_int.h index e03072c07b9d..13b679fef083 100644 --- a/lib/libpthread/pthread_int.h +++ b/lib/libpthread/pthread_int.h @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_int.h,v 1.19 2003/09/12 00:37:17 christos Exp $ */ +/* $NetBSD: pthread_int.h,v 1.20 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc. @@ -183,6 +183,7 @@ struct pthread_lock_ops { #define PT_STATE_BLOCKED_QUEUE 4 #define PT_STATE_ZOMBIE 5 #define PT_STATE_DEAD 6 +#define PT_STATE_SUSPENDED 7 /* Flag values */ @@ -194,6 +195,7 @@ struct pthread_lock_ops { #define PT_FLAG_SIGDEFERRED 0x0020 /* There are signals to take */ #define PT_FLAG_SCOPE_SYSTEM 0x0040 #define PT_FLAG_EXPLICIT_SCHED 0x0080 +#define PT_FLAG_SUSPENDED 0x0100 /* In the suspended queue */ #define PT_MAGIC 0x11110001 #define PT_DEAD 0xDEAD0001 @@ -228,6 +230,8 @@ void pthread__initthread(pthread_t self, pthread_t t); /* Go do something else. Don't go back on the run queue */ void pthread__block(pthread_t self, pthread_spin_t* queuelock); +/* Put a thread back on the suspended queue */ +void pthread__suspend(pthread_t self, pthread_t thread); /* Put a thread back on the run queue */ void pthread__sched(pthread_t self, pthread_t thread); void pthread__sched_sleepers(pthread_t self, struct pthread_queue_t *threadq); diff --git a/lib/libpthread/pthread_run.c b/lib/libpthread/pthread_run.c index 1cadb3c1c99c..42661d8c02f9 100644 --- a/lib/libpthread/pthread_run.c +++ b/lib/libpthread/pthread_run.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_run.c,v 1.12 2003/09/16 13:51:35 cl Exp $ */ +/* $NetBSD: pthread_run.c,v 1.13 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__RCSID("$NetBSD: pthread_run.c,v 1.12 2003/09/16 13:51:35 cl Exp $"); +__RCSID("$NetBSD: pthread_run.c,v 1.13 2003/11/09 18:56:48 christos Exp $"); #include @@ -53,6 +53,7 @@ __RCSID("$NetBSD: pthread_run.c,v 1.12 2003/09/16 13:51:35 cl Exp $"); extern pthread_spin_t pthread__runqueue_lock; extern struct pthread_queue_t pthread__runqueue; extern struct pthread_queue_t pthread__idlequeue; +extern struct pthread_queue_t pthread__suspqueue; extern pthread_spin_t pthread__deadqueue_lock; extern struct pthread_queue_t pthread__reidlequeue; @@ -129,6 +130,22 @@ pthread__next(pthread_t self) } +/* Put a thread on the suspended queue */ +void +pthread__suspend(pthread_t self, pthread_t thread) +{ + + SDPRINTF(("(sched %p) suspending %p\n", self, thread)); + thread->pt_state = PT_STATE_SUSPENDED; + pthread__assert(thread->pt_type == PT_THREAD_NORMAL); + pthread__assert(thread->pt_spinlocks == 0); + pthread_spinlock(self, &pthread__runqueue_lock); + PTQ_INSERT_TAIL(&pthread__suspqueue, thread, pt_runq); + pthread_spinunlock(self, &pthread__runqueue_lock); + /* XXX flaglock? */ + thread->pt_flags &= ~PT_FLAG_SUSPENDED; +} + /* Put a thread back on the run queue */ void pthread__sched(pthread_t self, pthread_t thread) @@ -240,7 +257,11 @@ pthread__sched_bulk(pthread_t self, pthread_t qhead) SDPRINTF(("(bulk %p) scheduling %p\n", self, qhead)); pthread__assert(PTQ_LAST(&pthread__runqueue, pthread_queue_t) != qhead); pthread__assert(PTQ_FIRST(&pthread__runqueue) != qhead); - PTQ_INSERT_TAIL(&pthread__runqueue, qhead, pt_runq); + if (qhead->pt_flags & PT_FLAG_SUSPENDED) { + qhead->pt_state = PT_STATE_SUSPENDED; + PTQ_INSERT_TAIL(&pthread__suspqueue, qhead, pt_runq); + } else + PTQ_INSERT_TAIL(&pthread__runqueue, qhead, pt_runq); } else if (qhead->pt_type == PT_THREAD_IDLE) { qhead->pt_state = PT_STATE_RUNNABLE; qhead->pt_flags &= ~PT_FLAG_IDLED; diff --git a/lib/libpthread/pthread_sig.c b/lib/libpthread/pthread_sig.c index 71abff471d4a..795e7aca13c5 100644 --- a/lib/libpthread/pthread_sig.c +++ b/lib/libpthread/pthread_sig.c @@ -1,4 +1,4 @@ -/* $NetBSD: pthread_sig.c,v 1.23 2003/10/16 13:38:28 yamt Exp $ */ +/* $NetBSD: pthread_sig.c,v 1.24 2003/11/09 18:56:48 christos Exp $ */ /*- * Copyright (c) 2001 The NetBSD Foundation, Inc. @@ -37,7 +37,7 @@ */ #include -__RCSID("$NetBSD: pthread_sig.c,v 1.23 2003/10/16 13:38:28 yamt Exp $"); +__RCSID("$NetBSD: pthread_sig.c,v 1.24 2003/11/09 18:56:48 christos Exp $"); /* We're interposing a specific version of the signal interface. */ #define __LIBC12_SOURCE__ @@ -72,6 +72,9 @@ extern struct pthread_queue_t pthread__runqueue; extern pthread_spin_t pthread__allqueue_lock; extern struct pthread_queue_t pthread__allqueue; +extern pthread_spin_t pthread__suspqueue_lock; +extern struct pthread_queue_t pthread__suspqueue; + static pthread_spin_t pt_sigacts_lock; static struct sigaction pt_sigacts[_NSIG]; @@ -792,6 +795,11 @@ pthread__kill(pthread_t self, pthread_t target, siginfo_t *si) */ pthread_spinlock(self, &target->pt_statelock); switch (target->pt_state) { + case PT_STATE_SUSPENDED: + pthread_spinlock(self, &pthread__runqueue_lock); + PTQ_REMOVE(&pthread__suspqueue, target, pt_runq); + pthread_spinunlock(self, &pthread__runqueue_lock); + break; case PT_STATE_RUNNABLE: pthread_spinlock(self, &pthread__runqueue_lock); PTQ_REMOVE(&pthread__runqueue, target, pt_runq);