add libpthread part of concurrency support for SA on MP systems
- enable concurrency according to environment variable PTHREAD_CONCURRENCY - add idle VP wakeup if there are additional jobs and idle VPs - make reidlequeue per VP - enable spinning for locks - fix race condition in alarm processing - fix race condition in mutex locking - make debugging output line buffered and add VP prefix to debug lines
This commit is contained in:
parent
ea5ec0212d
commit
f2f106648c
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread.c,v 1.32 2003/12/31 16:45:48 cl Exp $ */
|
||||
/* $NetBSD: pthread.c,v 1.33 2004/03/14 01:19:41 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread.c,v 1.32 2003/12/31 16:45:48 cl Exp $");
|
||||
__RCSID("$NetBSD: pthread.c,v 1.33 2004/03/14 01:19:41 cl Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
|
@ -49,6 +49,8 @@ __RCSID("$NetBSD: pthread.c,v 1.32 2003/12/31 16:45:48 cl Exp $");
|
|||
#include <syslog.h>
|
||||
#include <ucontext.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <sched.h>
|
||||
#include "pthread.h"
|
||||
|
@ -69,7 +71,7 @@ struct pthread_queue_t pthread__allqueue;
|
|||
|
||||
pthread_spin_t pthread__deadqueue_lock;
|
||||
struct pthread_queue_t pthread__deadqueue;
|
||||
struct pthread_queue_t pthread__reidlequeue;
|
||||
struct pthread_queue_t *pthread__reidlequeue;
|
||||
|
||||
static int nthreads;
|
||||
static int nextthread;
|
||||
|
@ -89,6 +91,8 @@ struct pthread_queue_t pthread__runqueue;
|
|||
struct pthread_queue_t pthread__idlequeue;
|
||||
struct pthread_queue_t pthread__suspqueue;
|
||||
|
||||
int pthread__concurrency, pthread__maxconcurrency;
|
||||
|
||||
__strong_alias(__libc_thr_self,pthread_self)
|
||||
__strong_alias(__libc_thr_create,pthread_create)
|
||||
__strong_alias(__libc_thr_exit,pthread_exit)
|
||||
|
@ -126,18 +130,43 @@ pthread_init(void)
|
|||
{
|
||||
pthread_t first;
|
||||
char *p;
|
||||
int i, mib[2], ncpu;
|
||||
size_t len;
|
||||
extern int __isthreaded;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_NCPU;
|
||||
|
||||
len = sizeof(ncpu);
|
||||
sysctl(mib, 2, &ncpu, &len, NULL, 0);
|
||||
|
||||
/* Initialize locks first; they're needed elsewhere. */
|
||||
pthread__lockprim_init();
|
||||
pthread__lockprim_init(ncpu);
|
||||
|
||||
/* Find out requested/possible concurrency */
|
||||
pthread__maxconcurrency = 1;
|
||||
p = getenv("PTHREAD_CONCURRENCY");
|
||||
if (p)
|
||||
pthread__maxconcurrency = atoi(p);
|
||||
if (pthread__maxconcurrency < 1)
|
||||
pthread__maxconcurrency = 1;
|
||||
if (pthread__maxconcurrency > ncpu)
|
||||
pthread__maxconcurrency = ncpu;
|
||||
|
||||
/* Allocate data structures */
|
||||
pthread__reidlequeue = (struct pthread_queue_t *)malloc
|
||||
(pthread__maxconcurrency * sizeof(struct pthread_queue_t));
|
||||
if (pthread__reidlequeue == NULL)
|
||||
err(1, "Couldn't allocate memory for pthread__reidlequeue");
|
||||
|
||||
/* Basic data structure setup */
|
||||
pthread_attr_init(&pthread_default_attr);
|
||||
PTQ_INIT(&pthread__allqueue);
|
||||
PTQ_INIT(&pthread__deadqueue);
|
||||
PTQ_INIT(&pthread__reidlequeue);
|
||||
PTQ_INIT(&pthread__runqueue);
|
||||
PTQ_INIT(&pthread__idlequeue);
|
||||
for (i = 0; i < pthread__maxconcurrency; i++)
|
||||
PTQ_INIT(&pthread__reidlequeue[i]);
|
||||
nthreads = 1;
|
||||
|
||||
/* Create the thread structure corresponding to main() */
|
||||
|
@ -151,7 +180,7 @@ pthread_init(void)
|
|||
pthread__signal_init();
|
||||
PTHREAD_MD_INIT
|
||||
#ifdef PTHREAD__DEBUG
|
||||
pthread__debug_init();
|
||||
pthread__debug_init(ncpu);
|
||||
#endif
|
||||
|
||||
for (p = getenv("PTHREAD_DIAGASSERT"); p && *p; p++) {
|
||||
|
@ -215,7 +244,10 @@ pthread__start(void)
|
|||
|
||||
pthread_atfork(NULL, NULL, pthread__child_callback);
|
||||
|
||||
/* Create idle threads */
|
||||
/*
|
||||
* Create idle threads
|
||||
* XXX need to create more idle threads if concurrency > 3
|
||||
*/
|
||||
for (i = 0; i < NIDLETHREADS; i++) {
|
||||
ret = pthread__stackalloc(&idle);
|
||||
if (ret != 0)
|
||||
|
@ -468,7 +500,10 @@ pthread__idle(void)
|
|||
* a list somewhere for the thread system to know about us.
|
||||
*/
|
||||
pthread_spinlock(self, &pthread__deadqueue_lock);
|
||||
PTQ_INSERT_TAIL(&pthread__reidlequeue, self, pt_runq);
|
||||
PTQ_INSERT_TAIL(&pthread__reidlequeue[self->pt_vpid], self, pt_runq);
|
||||
pthread__concurrency--;
|
||||
SDPRINTF(("(yield %p concurrency) now %d\n", self,
|
||||
pthread__concurrency));
|
||||
/* Don't need a flag lock; nothing else has a handle on this thread */
|
||||
self->pt_flags |= PT_FLAG_IDLED;
|
||||
pthread_spinunlock(self, &pthread__deadqueue_lock);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_alarms.c,v 1.8 2003/04/07 19:41:22 nathanw Exp $ */
|
||||
/* $NetBSD: pthread_alarms.c,v 1.9 2004/03/14 01:19:41 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_alarms.c,v 1.8 2003/04/07 19:41:22 nathanw Exp $");
|
||||
__RCSID("$NetBSD: pthread_alarms.c,v 1.9 2004/03/14 01:19:41 cl Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <sys/time.h>
|
||||
|
@ -121,6 +121,7 @@ pthread__alarm_del(pthread_t self, struct pt_alarm_t *alarm)
|
|||
next = NULL;
|
||||
pthread_spinlock(self, &pthread_alarmqlock);
|
||||
pthread_spinlock(self, &alarm->pta_lock);
|
||||
SDPRINTF(("(del %p) alarm %p\n", self, alarm));
|
||||
if (alarm->pta_fired == 0) {
|
||||
if (alarm == PTQ_FIRST(&pthread_alarmqueue)) {
|
||||
next = PTQ_NEXT(alarm, pta_next);
|
||||
|
@ -178,8 +179,7 @@ pthread__alarm_process(pthread_t self, void *arg)
|
|||
next = PTQ_NEXT(iterator, pta_next);
|
||||
PTQ_REMOVE(&pthread_alarmqueue, iterator, pta_next);
|
||||
PTQ_INSERT_TAIL(&runq, iterator, pta_next);
|
||||
iterator = next;
|
||||
|
||||
SDPRINTF(("(pro %p) collect alarm %p\n", self, iterator));
|
||||
}
|
||||
|
||||
/* 2. Reset the timer for the next element in the queue. */
|
||||
|
@ -194,12 +194,14 @@ pthread__alarm_process(pthread_t self, void *arg)
|
|||
pthread_spinunlock(self, &pthread_alarmqlock);
|
||||
|
||||
/* 3. Call the functions for all passed alarms. */
|
||||
PTQ_FOREACH(iterator, &runq, pta_next) {
|
||||
for (iterator = next = PTQ_FIRST(&runq);
|
||||
iterator;
|
||||
iterator = next) {
|
||||
SDPRINTF(("(pro %p) calling function for alarm %p\n", self, iterator));
|
||||
(*iterator->pta_func)(iterator->pta_arg);
|
||||
iterator->pta_fired = 1;
|
||||
next = PTQ_NEXT(iterator, pta_next);
|
||||
pthread_spinunlock(self, &iterator->pta_lock);
|
||||
}
|
||||
SDPRINTF(("(pro %p) done\n", self, iterator));
|
||||
|
||||
SDPRINTF(("(pro %p) done\n", self, iterator));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_debug.c,v 1.7 2004/01/02 14:13:16 cl Exp $ */
|
||||
/* $NetBSD: pthread_debug.c,v 1.8 2004/03/14 01:19:41 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_debug.c,v 1.7 2004/01/02 14:13:16 cl Exp $");
|
||||
__RCSID("$NetBSD: pthread_debug.c,v 1.8 2004/03/14 01:19:41 cl Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
|
@ -59,15 +59,23 @@ int pthread__dbg;
|
|||
#ifdef PTHREAD__DEBUG
|
||||
|
||||
int pthread__debug_counters[PTHREADD_NCOUNTERS];
|
||||
int pthread__debug_newline;
|
||||
static struct pthread_msgbuf* debugbuf;
|
||||
static struct pthread_msgbuf *debugbuf;
|
||||
#define MAXLINELEN 1000
|
||||
struct linebuf {
|
||||
char buf[MAXLINELEN];
|
||||
int len;
|
||||
};
|
||||
static struct linebuf *linebuf;
|
||||
|
||||
static void pthread__debug_printcounters(void);
|
||||
static const char *pthread__counternames[] = PTHREADD_INITCOUNTERNAMES;
|
||||
|
||||
void pthread__debug_init(void)
|
||||
extern int pthread__maxconcurrency, pthread__started;
|
||||
|
||||
void pthread__debug_init(int ncpu)
|
||||
{
|
||||
time_t t;
|
||||
int i;
|
||||
|
||||
if (getenv("PTHREAD_DEBUGCOUNTERS") != NULL)
|
||||
atexit(pthread__debug_printcounters);
|
||||
|
@ -75,10 +83,15 @@ void pthread__debug_init(void)
|
|||
if (getenv("PTHREAD_DEBUGLOG") != NULL) {
|
||||
t = time(NULL);
|
||||
debugbuf = pthread__debuglog_init(0);
|
||||
linebuf = (struct linebuf *)
|
||||
malloc(ncpu * sizeof(struct linebuf));
|
||||
if (linebuf == NULL)
|
||||
err(1, "Couldn't allocate linebuf");
|
||||
for (i = 0; i < ncpu; i++)
|
||||
linebuf[i].len = 0;
|
||||
|
||||
DPRINTF(("Started debugging %s (pid %d) at %s\n",
|
||||
getprogname(), getpid(), ctime(&t)));
|
||||
|
||||
pthread__debug_newline = 1;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,25 +152,44 @@ pthread__debuglog_init(int force)
|
|||
void
|
||||
pthread__debuglog_printf(const char *fmt, ...)
|
||||
{
|
||||
char tmpbuf[200+6];
|
||||
char *tmpbuf;
|
||||
size_t len, cplen, r, w, s;
|
||||
long diff1, diff2;
|
||||
int vpid;
|
||||
va_list ap;
|
||||
|
||||
if (debugbuf == NULL)
|
||||
return;
|
||||
|
||||
if (pthread__maxconcurrency > 1) {
|
||||
vpid = pthread_self()->pt_vpid;
|
||||
} else
|
||||
vpid = 0;
|
||||
|
||||
tmpbuf = linebuf[vpid].buf;
|
||||
len = linebuf[vpid].len;
|
||||
|
||||
#if defined(PTHREAD_PID_DEBUG) || defined(PTHREAD_VP_DEBUG)
|
||||
if (len == 0) {
|
||||
#ifdef PTHREAD_PID_DEBUG
|
||||
if (pthread__debug_newline == 1)
|
||||
len = sprintf(tmpbuf, "%05d ", getpid());
|
||||
else
|
||||
len += sprintf(tmpbuf, "[%05d]", getpid());
|
||||
#endif
|
||||
len = 0;
|
||||
#ifdef PTHREAD_VP_DEBUG
|
||||
if (pthread__maxconcurrency > 1)
|
||||
len += sprintf(tmpbuf + len, "[%d]", vpid);
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
va_start(ap, fmt);
|
||||
len += vsnprintf(tmpbuf, 200, fmt, ap);
|
||||
len += vsnprintf(tmpbuf + len, (unsigned int)(MAXLINELEN - len),
|
||||
fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
pthread__debug_newline = (tmpbuf[len - 1] == '\n') ? 1 : 0;
|
||||
linebuf[vpid].len = len;
|
||||
|
||||
if (tmpbuf[len - 1] != '\n')
|
||||
return;
|
||||
|
||||
r = debugbuf->msg_bufr;
|
||||
w = debugbuf->msg_bufw;
|
||||
|
@ -190,6 +222,22 @@ pthread__debuglog_printf(const char *fmt, ...)
|
|||
debugbuf->msg_bufr = (w + 1) % s;
|
||||
}
|
||||
|
||||
linebuf[vpid].len = 0;
|
||||
}
|
||||
|
||||
int
|
||||
pthread__debuglog_newline(void)
|
||||
{
|
||||
int vpid;
|
||||
|
||||
if (debugbuf == NULL)
|
||||
return 1;
|
||||
|
||||
if (pthread__maxconcurrency > 1)
|
||||
vpid = pthread_self()->pt_vpid;
|
||||
else
|
||||
vpid = 0;
|
||||
|
||||
return (linebuf[vpid].len == 0);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_debug.h,v 1.7 2004/01/02 14:13:16 cl Exp $ */
|
||||
/* $NetBSD: pthread_debug.h,v 1.8 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -104,9 +104,10 @@ struct pthread_msgbuf {
|
|||
char msg_bufc[1];
|
||||
};
|
||||
|
||||
void pthread__debug_init(void);
|
||||
void pthread__debug_init(int ncpu);
|
||||
struct pthread_msgbuf* pthread__debuglog_init(int force);
|
||||
void pthread__debuglog_printf(const char *fmt, ...);
|
||||
int pthread__debuglog_newline(void);
|
||||
|
||||
#ifdef PTHREAD__DEBUG
|
||||
|
||||
|
@ -119,9 +120,9 @@ void pthread__debuglog_printf(const char *fmt, ...);
|
|||
#undef PTHREAD_SIG_DEBUG
|
||||
#define PTHREAD_SPIN_DEBUG
|
||||
#undef PTHREAD_SPIN_DEBUG_PRINT
|
||||
#undef PTHREAD_VP_DEBUG
|
||||
|
||||
extern int pthread__debug_counters[PTHREADD_NCOUNTERS];
|
||||
extern int pthread__debug_newline;
|
||||
|
||||
extern int pthread__dbg; /* Set by libpthread_dbg */
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_int.h,v 1.25 2004/02/02 20:36:18 nathanw Exp $ */
|
||||
/* $NetBSD: pthread_int.h,v 1.26 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
|
||||
|
@ -92,6 +92,7 @@ struct __pthread_st {
|
|||
int pt_cancel; /* Deferred cancellation */
|
||||
int pt_spinlocks; /* Number of spinlocks held. */
|
||||
int pt_blockedlwp; /* LWP/SA number when blocked */
|
||||
int pt_vpid; /* VP number */
|
||||
int pt_blockgen; /* SA_UPCALL_BLOCKED counter */
|
||||
int pt_unblockgen; /* SA_UPCALL_UNBLOCKED counter */
|
||||
|
||||
|
@ -275,6 +276,7 @@ void pthread__initmain(pthread_t *t);
|
|||
|
||||
void pthread__sa_start(void);
|
||||
void pthread__sa_recycle(pthread_t old, pthread_t new);
|
||||
void pthread__setconcurrency(int);
|
||||
|
||||
/* Alarm code */
|
||||
void pthread__alarm_init(void);
|
||||
|
@ -285,7 +287,7 @@ int pthread__alarm_fired(struct pt_alarm_t *);
|
|||
void pthread__alarm_process(pthread_t self, void *arg);
|
||||
|
||||
/* Internal locking primitives */
|
||||
void pthread__lockprim_init(void);
|
||||
void pthread__lockprim_init(int ncpu);
|
||||
void pthread_lockinit(pthread_spin_t *lock);
|
||||
void pthread_spinlock(pthread_t thread, pthread_spin_t *lock);
|
||||
int pthread_spintrylock(pthread_t thread, pthread_spin_t *lock);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_lock.c,v 1.10 2004/03/03 21:06:07 thorpej Exp $ */
|
||||
/* $NetBSD: pthread_lock.c,v 1.11 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,11 +37,10 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_lock.c,v 1.10 2004/03/03 21:06:07 thorpej Exp $");
|
||||
__RCSID("$NetBSD: pthread_lock.c,v 1.11 2004/03/14 01:19:42 cl Exp $");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/lock.h>
|
||||
#include <sys/ras.h>
|
||||
#include <sys/sysctl.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
|
@ -56,7 +55,7 @@ __RCSID("$NetBSD: pthread_lock.c,v 1.10 2004/03/03 21:06:07 thorpej Exp $");
|
|||
#endif
|
||||
|
||||
/* How many times to try before checking whether we've been continued. */
|
||||
#define NSPINS 1 /* no point in actually spinning until MP works */
|
||||
#define NSPINS 1000 /* no point in actually spinning until MP works */
|
||||
|
||||
static int nspins = NSPINS;
|
||||
|
||||
|
@ -136,18 +135,9 @@ const struct pthread_lock_ops *pthread__lock_ops = &pthread__lock_ops_ras;
|
|||
* we fall back onto machine-dependent atomic lock primitives.
|
||||
*/
|
||||
void
|
||||
pthread__lockprim_init(void)
|
||||
pthread__lockprim_init(int ncpu)
|
||||
{
|
||||
int mib[2];
|
||||
size_t len;
|
||||
int ncpu;
|
||||
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_NCPU;
|
||||
|
||||
len = sizeof(ncpu);
|
||||
sysctl(mib, 2, &ncpu, &len, NULL, 0);
|
||||
|
||||
if (ncpu == 1 && rasctl(RAS_ADDR(pthread__lock),
|
||||
RAS_SIZE(pthread__lock), RAS_INSTALL) == 0) {
|
||||
pthread__lock_ops = &pthread__lock_ops_ras;
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_mutex.c,v 1.17 2003/11/24 23:54:13 cl Exp $ */
|
||||
/* $NetBSD: pthread_mutex.c,v 1.18 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001, 2003 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_mutex.c,v 1.17 2003/11/24 23:54:13 cl Exp $");
|
||||
__RCSID("$NetBSD: pthread_mutex.c,v 1.18 2004/03/14 01:19:42 cl Exp $");
|
||||
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
|
@ -209,6 +209,7 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
|
|||
* sleep queue. If it's not held, we can try taking it
|
||||
* again.
|
||||
*/
|
||||
PTQ_INSERT_HEAD(&mutex->ptm_blocked, self, pt_sleep);
|
||||
if (mutex->ptm_lock == __SIMPLELOCK_LOCKED) {
|
||||
struct mutex_private *mp;
|
||||
|
||||
|
@ -217,6 +218,8 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
|
|||
if (pthread__id(mutex->ptm_owner) == self) {
|
||||
switch (mp->type) {
|
||||
case PTHREAD_MUTEX_ERRORCHECK:
|
||||
PTQ_REMOVE(&mutex->ptm_blocked, self,
|
||||
pt_sleep);
|
||||
pthread_spinunlock(self,
|
||||
&mutex->ptm_interlock);
|
||||
return EDEADLK;
|
||||
|
@ -228,6 +231,8 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
|
|||
* we only modify it if we know we
|
||||
* own the mutex.
|
||||
*/
|
||||
PTQ_REMOVE(&mutex->ptm_blocked, self,
|
||||
pt_sleep);
|
||||
pthread_spinunlock(self,
|
||||
&mutex->ptm_interlock);
|
||||
if (mp->recursecount == INT_MAX)
|
||||
|
@ -237,7 +242,6 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
|
|||
}
|
||||
}
|
||||
|
||||
PTQ_INSERT_HEAD(&mutex->ptm_blocked, self, pt_sleep);
|
||||
/*
|
||||
* Locking a mutex is not a cancellation
|
||||
* point, so we don't need to do the
|
||||
|
@ -256,6 +260,7 @@ pthread_mutex_lock_slow(pthread_mutex_t *mutex)
|
|||
pthread__block(self, &mutex->ptm_interlock);
|
||||
/* interlock is not held when we return */
|
||||
} else {
|
||||
PTQ_REMOVE(&mutex->ptm_blocked, self, pt_sleep);
|
||||
pthread_spinunlock(self, &mutex->ptm_interlock);
|
||||
}
|
||||
/* Go around for another try. */
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_run.c,v 1.16 2004/01/16 15:23:31 cl Exp $ */
|
||||
/* $NetBSD: pthread_run.c,v 1.17 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_run.c,v 1.16 2004/01/16 15:23:31 cl Exp $");
|
||||
__RCSID("$NetBSD: pthread_run.c,v 1.17 2004/03/14 01:19:42 cl Exp $");
|
||||
|
||||
#include <ucontext.h>
|
||||
#include <errno.h>
|
||||
|
@ -57,7 +57,9 @@ 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;
|
||||
extern struct pthread_queue_t *pthread__reidlequeue;
|
||||
|
||||
extern int pthread__concurrency, pthread__maxconcurrency;
|
||||
|
||||
__strong_alias(__libc_thr_yield,sched_yield)
|
||||
|
||||
|
@ -80,10 +82,11 @@ sched_yield(void)
|
|||
next = PTQ_FIRST(&pthread__runqueue);
|
||||
PTQ_REMOVE(&pthread__runqueue, next, pt_runq);
|
||||
next->pt_state = PT_STATE_RUNNING;
|
||||
if (next != self)
|
||||
if (next != self) {
|
||||
next->pt_vpid = self->pt_vpid;
|
||||
pthread__locked_switch(self, next,
|
||||
&pthread__runqueue_lock);
|
||||
else
|
||||
} else
|
||||
pthread_spinunlock(self, &pthread__runqueue_lock);
|
||||
}
|
||||
|
||||
|
@ -119,6 +122,9 @@ pthread__next(pthread_t self)
|
|||
pthread__assert(next->pt_type == PT_THREAD_NORMAL);
|
||||
PTQ_REMOVE(&pthread__runqueue, next, pt_runq);
|
||||
SDPRINTF(("(next %p) returning thread %p\n", self, next));
|
||||
if (pthread__maxconcurrency > pthread__concurrency &&
|
||||
PTQ_FIRST(&pthread__runqueue))
|
||||
pthread__setconcurrency(1);
|
||||
} else {
|
||||
next = PTQ_FIRST(&pthread__idlequeue);
|
||||
pthread__assert(next != 0);
|
||||
|
@ -126,6 +132,7 @@ pthread__next(pthread_t self)
|
|||
pthread__assert(next->pt_type == PT_THREAD_IDLE);
|
||||
SDPRINTF(("(next %p) returning idle thread %p\n", self, next));
|
||||
}
|
||||
next->pt_vpid = self->pt_vpid;
|
||||
pthread_spinunlock(self, &pthread__runqueue_lock);
|
||||
|
||||
return next;
|
||||
|
@ -214,19 +221,25 @@ pthread__sched_idle2(pthread_t self)
|
|||
{
|
||||
pthread_t idlethread, qhead, next;
|
||||
|
||||
/* XXXconcurrency: only reidle threads on same vp */
|
||||
|
||||
qhead = NULL;
|
||||
pthread_spinlock(self, &pthread__deadqueue_lock);
|
||||
idlethread = PTQ_FIRST(&pthread__reidlequeue);
|
||||
idlethread = PTQ_FIRST(&pthread__reidlequeue[self->pt_vpid]);
|
||||
while (idlethread != NULL) {
|
||||
SDPRINTF(("(sched_idle2 %p) reidling %p\n", self, idlethread));
|
||||
next = PTQ_NEXT(idlethread, pt_runq);
|
||||
if ((idlethread->pt_next == NULL) &&
|
||||
(idlethread->pt_blockgen == idlethread->pt_unblockgen)) {
|
||||
PTQ_REMOVE(&pthread__reidlequeue, idlethread, pt_runq);
|
||||
PTQ_REMOVE(&pthread__reidlequeue[self->pt_vpid],
|
||||
idlethread, pt_runq);
|
||||
idlethread->pt_next = qhead;
|
||||
qhead = idlethread;
|
||||
|
||||
pthread__concurrency++;
|
||||
SDPRINTF(("(sched_idle2 %p concurrency) now %d from %p\n",
|
||||
self, pthread__concurrency, idlethread));
|
||||
pthread__assert(pthread__concurrency <=
|
||||
pthread__maxconcurrency);
|
||||
|
||||
} else {
|
||||
SDPRINTF(("(sched_idle2 %p) %p is in a preemption loop\n", self, idlethread));
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/* $NetBSD: pthread_sa.c,v 1.29 2004/02/24 15:16:04 wiz Exp $ */
|
||||
/* $NetBSD: pthread_sa.c,v 1.30 2004/03/14 01:19:42 cl Exp $ */
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2001 The NetBSD Foundation, Inc.
|
||||
|
@ -37,7 +37,7 @@
|
|||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__RCSID("$NetBSD: pthread_sa.c,v 1.29 2004/02/24 15:16:04 wiz Exp $");
|
||||
__RCSID("$NetBSD: pthread_sa.c,v 1.30 2004/03/14 01:19:42 cl Exp $");
|
||||
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
|
@ -65,8 +65,7 @@ __RCSID("$NetBSD: pthread_sa.c,v 1.29 2004/02/24 15:16:04 wiz Exp $");
|
|||
#define PUC(t) ((t)->pt_trapuc ? 'T':'U') , UC(t)
|
||||
|
||||
extern struct pthread_queue_t pthread__allqueue;
|
||||
extern pthread_spin_t pthread__deadqueue_lock;
|
||||
extern struct pthread_queue_t pthread__reidlequeue;
|
||||
extern int pthread__concurrency, pthread__maxconcurrency;
|
||||
|
||||
#define PTHREAD_RRTIMER_INTERVAL_DEFAULT 100
|
||||
static pthread_mutex_t rrtimer_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
@ -101,6 +100,8 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg)
|
|||
if (sas[0]->sa_id > pthread__maxlwps)
|
||||
pthread__maxlwps = sas[0]->sa_id;
|
||||
|
||||
self->pt_vpid = sas[0]->sa_cpu;
|
||||
|
||||
SDPRINTF(("(up %p) type %d LWP %d ev %d intr %d\n", self,
|
||||
type, sas[0]->sa_id, ev, intr));
|
||||
|
||||
|
@ -128,6 +129,7 @@ pthread__upcall(int type, struct sa_t *sas[], int ev, int intr, void *arg)
|
|||
t = pthread__sa_id(sas[1]);
|
||||
SDPRINTF(("(up %p) blocker %d %p(%d)\n", self,
|
||||
sas[1]->sa_id, t, t->pt_type));
|
||||
pthread__assert(t->pt_vpid == sas[1]->sa_cpu);
|
||||
t->pt_blockuc = sas[1]->sa_context;
|
||||
t->pt_blockedlwp = sas[1]->sa_id;
|
||||
t->pt_blockgen += 2;
|
||||
|
@ -611,7 +613,7 @@ pthread__sa_recycle(pthread_t old, pthread_t new)
|
|||
old->pt_state = PT_STATE_RUNNABLE;
|
||||
|
||||
#ifdef PTHREAD__DEBUG
|
||||
if (pthread__debug_newline == 1)
|
||||
if (pthread__debuglog_newline())
|
||||
SDPRINTF(("(recycle %p) recycling %p\n", new, old));
|
||||
else
|
||||
SDPRINTF((" (recycling %p)", old));
|
||||
|
@ -733,6 +735,12 @@ pthread__sa_start(void)
|
|||
/* Start the round-robin timer. */
|
||||
if (rr != 0 && pthread__setrrtimer(rr, 1) != 0)
|
||||
abort();
|
||||
|
||||
pthread__concurrency = 1;
|
||||
if (pthread__maxconcurrency > pthread__concurrency) {
|
||||
pthread__concurrency += sa_setconcurrency(pthread__maxconcurrency);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -765,3 +773,28 @@ pthread_setrrtimer_np(int msec)
|
|||
|
||||
return (ret);
|
||||
}
|
||||
|
||||
void
|
||||
pthread__setconcurrency(int concurrency)
|
||||
{
|
||||
pthread_t self;
|
||||
int ret;
|
||||
|
||||
self = pthread__self();
|
||||
SDPRINTF(("(setconcurrency %p) requested delta %d, current %d\n",
|
||||
self, concurrency, pthread__concurrency));
|
||||
|
||||
concurrency += pthread__concurrency;
|
||||
if (concurrency > pthread__maxconcurrency)
|
||||
concurrency = pthread__maxconcurrency;
|
||||
|
||||
if (concurrency > pthread__concurrency) {
|
||||
ret = sa_setconcurrency(concurrency);
|
||||
/* pthread__concurrency += ret; */
|
||||
|
||||
SDPRINTF(("(setconcurrency %p) requested %d, now %d, ret %d\n",
|
||||
self, concurrency, pthread__concurrency, ret));
|
||||
}
|
||||
SDPRINTF(("(set %p concurrency) now %d\n",
|
||||
self, pthread__concurrency));
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue