userland part of no-syscall upcall stack return

- add pt_stackinfo to struct __pthread_st
- add pthread__stackinfo_offset returning the offset from ss_sp to
  pt_stackinfo
- pass stackinfo_offset to sa_register and set SA_FLAG_STACKINFO to
  make the kernel use it
- call pthread__sa_recycle in pthread__resolve_locks; g/c recycleq and
  pthread__recycle_bulk
- return stack in pthread__sa_recycle by incrementing sasi_stackgen
- make pthread__sa_recycle debugging output formatting conditional on
  pthread__debug_newline
This commit is contained in:
cl 2004-01-02 19:14:00 +00:00
parent 90e89977d4
commit 33622a5943
3 changed files with 36 additions and 40 deletions

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_int.h,v 1.23 2003/12/31 16:45:48 cl Exp $ */
/* $NetBSD: pthread_int.h,v 1.24 2004/01/02 19:14:00 cl Exp $ */
/*-
* Copyright (c) 2001,2002,2003 The NetBSD Foundation, Inc.
@ -158,6 +158,11 @@ struct __pthread_st {
*/
pthread_spin_t* pt_heldlock;
/* Upcall stack information shared between kernel and
* userland.
*/
struct sa_stackinfo_t pt_stackinfo;
/* Thread-specific data */
void* pt_specific[PTHREAD_KEYS_MAX];
@ -245,6 +250,8 @@ void pthread_init(void) __attribute__ ((__constructor__));
/* Set up/clean up a thread's basic state. */
void pthread__initthread(pthread_t self, pthread_t t);
/* Get offset from stack start to struct sa_stackinfo */
ssize_t pthread__stackinfo_offset(void);
/* Go do something else. Don't go back on the run queue */
void pthread__block(pthread_t self, pthread_spin_t* queuelock);

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_sa.c,v 1.25 2004/01/02 18:56:39 cl Exp $ */
/* $NetBSD: pthread_sa.c,v 1.26 2004/01/02 19:14:00 cl Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -37,7 +37,7 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: pthread_sa.c,v 1.25 2004/01/02 18:56:39 cl Exp $");
__RCSID("$NetBSD: pthread_sa.c,v 1.26 2004/01/02 19:14:00 cl Exp $");
#include <err.h>
#include <errno.h>
@ -83,7 +83,6 @@ void pthread__upcall(int type, struct sa_t *sas[], int ev, int intr,
void pthread__find_interrupted(int type, struct sa_t *sas[], int ev, int intr,
pthread_t *qhead, pthread_t *schedqhead, pthread_t self);
void pthread__resolve_locks(pthread_t self, pthread_t *interrupted);
void pthread__recycle_bulk(pthread_t self, pthread_t qhead);
extern void pthread__switch_return_point(void);
@ -374,13 +373,12 @@ pthread__find_interrupted(int type, struct sa_t *sas[], int ev, int intr,
void
pthread__resolve_locks(pthread_t self, pthread_t *intqueuep)
{
pthread_t victim, prev, next, switchto, runq, recycleq, intqueue;
pthread_t victim, prev, next, switchto, runq, intqueue;
pthread_t tmp;
pthread_spin_t *lock;
PTHREADD_ADD(PTHREADD_RESOLVELOCKS);
recycleq = NULL;
runq = self;
intqueue = *intqueuep;
switchto = NULL;
@ -469,13 +467,12 @@ pthread__resolve_locks(pthread_t self, pthread_t *intqueuep)
prev->pt_next = next;
else
intqueue = next;
victim->pt_next = recycleq;
recycleq = victim;
if (victim->pt_switchto == victim) {
victim->pt_switchto = NULL;
victim->pt_switchtouc = NULL;
SDPRINTF((" switchto self"));
}
pthread__sa_recycle(victim, self);
} else {
/*
* Not finished yet.
@ -609,35 +606,10 @@ pthread__resolve_locks(pthread_t self, pthread_t *intqueuep)
}
/* Recycle upcalls. */
pthread__recycle_bulk(self, recycleq);
SDPRINTF(("(rl %p) exiting\n", self));
*intqueuep = runq;
}
void
pthread__recycle_bulk(pthread_t self, pthread_t qhead)
{
int count, ret;
pthread_t upcall;
stack_t recyclable[PT_UPCALLSTACKS];
count = 0;
while(qhead != NULL) {
upcall = qhead;
qhead = qhead->pt_next;
upcall->pt_state = PT_STATE_RUNNABLE;
upcall->pt_next = NULL;
upcall->pt_parent = NULL;
recyclable[count] = upcall->pt_stack;
count++;
}
ret = sa_stacks(count, recyclable);
pthread__assert(ret == count);
SDPRINTF(("(recycle_bulk %p) recycled %d stacks\n", self, count));
}
/*
* Stash away an upcall and its stack, possibly recycling it to the kernel.
* Must be running in the context of "new".
@ -645,15 +617,18 @@ pthread__recycle_bulk(pthread_t self, pthread_t qhead)
void
pthread__sa_recycle(pthread_t old, pthread_t new)
{
int ret;
old->pt_next = NULL;
old->pt_parent = NULL;
old->pt_state = PT_STATE_RUNNABLE;
ret = sa_stacks(1, &old->pt_stack);
pthread__assert(ret == 1);
SDPRINTF(("(recycle %p) recycled %p\n", new, old));
#ifdef PTHREAD__DEBUG
if (pthread__debug_newline == 1)
SDPRINTF(("(recycle %p) recycling %p\n", new, old));
else
SDPRINTF((" (recycling %p)", old));
#endif
old->pt_stackinfo.sasi_stackgen++;
}
/*
@ -721,7 +696,9 @@ pthread__sa_start(void)
if (value)
rr = atoi(value);
ret = sa_register(pthread__upcall, NULL, flags, 0);
flags |= SA_FLAG_STACKINFO;
ret = sa_register(pthread__upcall, NULL, flags,
pthread__stackinfo_offset());
if (ret) {
if (errno == ENOSYS)
errx(1,

View File

@ -1,4 +1,4 @@
/* $NetBSD: pthread_stack.c,v 1.9 2003/11/27 16:30:54 cl Exp $ */
/* $NetBSD: pthread_stack.c,v 1.10 2004/01/02 19:14:00 cl Exp $ */
/*-
* Copyright (c) 2001 The NetBSD Foundation, Inc.
@ -37,11 +37,12 @@
*/
#include <sys/cdefs.h>
__RCSID("$NetBSD: pthread_stack.c,v 1.9 2003/11/27 16:30:54 cl Exp $");
__RCSID("$NetBSD: pthread_stack.c,v 1.10 2004/01/02 19:14:00 cl Exp $");
#include <err.h>
#include <errno.h>
#include <signal.h>
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <ucontext.h>
@ -186,3 +187,14 @@ pthread__stackid_setup(void *base, size_t size)
return t;
}
ssize_t
pthread__stackinfo_offset()
{
size_t pagesize;
pagesize = (size_t)sysconf(_SC_PAGESIZE);
return (-(2 * pagesize) +
offsetof(struct __pthread_st, pt_stackinfo));
}