Subject: pthread_{suspend,resume}_np
To: None <tech-kern@netbsd.org>
From: Christos Zoulas <christos@zoulas.com>
List: tech-kern
Date: 08/10/2003 19:44:01
Hello,
I need pthread_{suspend,resume}_np for java. I took a stab at their
implementation, but I am missing something because sometimes I get
an assertion failure in pthread__sched_bulk() where qhead == head of
runq. Any ideas?
christos
Index: pthread.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread.c,v
retrieving revision 1.28
diff -u -u -r1.28 pthread.c
--- pthread.c 2003/07/21 22:24:09 1.28
+++ pthread.c 2003/08/10 23:39:42
@@ -70,6 +70,8 @@
pthread_spin_t pthread__deadqueue_lock;
struct pthread_queue_t pthread__deadqueue;
struct pthread_queue_t pthread__reidlequeue;
+pthread_spin_t pthread__suspqueue_lock;
+struct pthread_queue_t pthread__suspqueue;
static int nthreads;
static int nextthread;
@@ -354,8 +356,11 @@
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__suspend(self, newthread);
+ else
+ pthread__sched(self, newthread);
*thread = newthread;
@@ -376,6 +381,57 @@
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;
+ }
+ 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:
+ break;
+ 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();
+ pthread_spinlock(self, &thread->pt_statelock);
+ if (thread->pt_state == PT_STATE_SUSPENDED) {
+ pthread_spinlock(self, &pthread__suspqueue_lock);
+ PTQ_REMOVE(&pthread__suspqueue, thread, pt_runq);
+ pthread_spinunlock(self, &pthread__suspqueue_lock);
+ pthread__sched(self, thread);
+ }
+ pthread_spinunlock(self, &thread->pt_statelock);
+ return 0;
+}
+
/*
* Other threads will switch to the idle thread so that they
Index: pthread.h
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread.h,v
retrieving revision 1.14
diff -u -u -r1.14 pthread.h
--- pthread.h 2003/07/18 22:01:47 1.14
+++ pthread.h 2003/08/10 23:39:42
@@ -119,6 +119,10 @@
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];
};
Index: pthread_int.h
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_int.h,v
retrieving revision 1.17
diff -u -u -r1.17 pthread_int.h
--- pthread_int.h 2003/07/21 22:21:07 1.17
+++ pthread_int.h 2003/08/10 23:39:42
@@ -177,6 +177,7 @@
#define PT_THREAD_IDLE 3
/* Thread states */
+#define PT_STATE_NEWBORN 0
#define PT_STATE_RUNNING 1
#define PT_STATE_RUNNABLE 2
#define PT_STATE_BLOCKED_SYS 3
@@ -184,6 +185,7 @@
#define PT_STATE_ZOMBIE 5
#define PT_STATE_DEAD 6
#define PT_STATE_RECYCLABLE 7
+#define PT_STATE_SUSPENDED 8
/* Flag values */
@@ -195,6 +197,7 @@
#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
@@ -229,6 +232,8 @@
/* 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);
Index: pthread_run.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_run.c,v
retrieving revision 1.11
diff -u -u -r1.11 pthread_run.c
--- pthread_run.c 2003/06/26 01:26:39 1.11
+++ pthread_run.c 2003/08/10 23:39:42
@@ -54,6 +54,9 @@
extern struct pthread_queue_t pthread__runqueue;
extern struct pthread_queue_t pthread__idlequeue;
+extern pthread_spin_t pthread__suspqueue_lock;
+extern struct pthread_queue_t pthread__suspqueue;
+
extern pthread_spin_t pthread__deadqueue_lock;
extern struct pthread_queue_t pthread__reidlequeue;
@@ -128,6 +131,20 @@
return next;
}
+
+/* Put a thread on the suspended queue */
+void
+pthread__suspend(pthread_t self, pthread_t thread)
+{
+
+ SDPRINTF(("(sched %p) suspending %p\n", self, thread));
+ pthread__assert(thread->pt_type == PT_THREAD_NORMAL);
+ pthread__assert(thread->pt_spinlocks == 0);
+ pthread_spinlock(self, &pthread__suspqueue_lock);
+ thread->pt_state = PT_STATE_SUSPENDED;
+ PTQ_INSERT_TAIL(&pthread__suspqueue, thread, pt_runq);
+ pthread_spinunlock(self, &pthread__suspqueue_lock);
+}
/* Put a thread back on the run queue */
void
Index: pthread_sig.c
===================================================================
RCS file: /cvsroot/src/lib/libpthread/pthread_sig.c,v
retrieving revision 1.16
diff -u -u -r1.16 pthread_sig.c
--- pthread_sig.c 2003/07/21 22:24:09 1.16
+++ pthread_sig.c 2003/08/10 23:39:43
@@ -72,6 +72,9 @@
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];
@@ -762,6 +765,11 @@
*/
pthread_spinlock(self, &target->pt_statelock);
switch (target->pt_state) {
+ case PT_STATE_SUSPENDED:
+ pthread_spinlock(self, &pthread__suspqueue_lock);
+ PTQ_REMOVE(&pthread__suspqueue, target, pt_runq);
+ pthread_spinunlock(self, &pthread__suspqueue_lock);
+ break;
case PT_STATE_RUNNABLE:
pthread_spinlock(self, &pthread__runqueue_lock);
PTQ_REMOVE(&pthread__runqueue, target, pt_runq);