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:
cl 2004-03-14 01:19:41 +00:00
parent ea5ec0212d
commit f2f106648c
9 changed files with 195 additions and 66 deletions

View File

@ -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);

View File

@ -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));
}

View File

@ -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

View File

@ -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 */

View File

@ -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);

View File

@ -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;

View File

@ -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. */

View File

@ -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));
}

View File

@ -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));
}