aboutsummaryrefslogtreecommitdiff
path: root/lib/libpthread/thread
diff options
context:
space:
mode:
authorDavid Xu <davidxu@FreeBSD.org>2003-11-29 14:22:29 +0000
committerDavid Xu <davidxu@FreeBSD.org>2003-11-29 14:22:29 +0000
commit170422c2ef6a210a6e29b278d1ac9be50cdacb7c (patch)
tree4a32c5e1d4d462b62323406ce2e8a4f54b00fc1b /lib/libpthread/thread
parent5a8fe60d7e677d822305195ee569a3edd0ce3b3d (diff)
downloadsrc-170422c2ef6a210a6e29b278d1ac9be50cdacb7c.tar.gz
src-170422c2ef6a210a6e29b278d1ac9be50cdacb7c.zip
1.Macro optimizing KSE_LOCK_ACQUIRE and THR_LOCK_ACQUIRE to use static fall
through branch predict as suggested in INTEL IA32 optimization guide. 2.Allocate siginfo arrary separately to avoid pthread to be allocated at 2K boundary, which hits L1 address alias problem and causes context switch to be slow down. 3.Simplify context switch code by removing redundant code, code size is reduced, so it is expected to run faster. Reviewed by: deischen Approved by: re (scottl)
Notes
Notes: svn path=/head/; revision=123048
Diffstat (limited to 'lib/libpthread/thread')
-rw-r--r--lib/libpthread/thread/thr_kern.c115
-rw-r--r--lib/libpthread/thread/thr_private.h15
2 files changed, 31 insertions, 99 deletions
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c
index 5186c524948c..7fd8b38fe0a8 100644
--- a/lib/libpthread/thread/thr_kern.c
+++ b/lib/libpthread/thread/thr_kern.c
@@ -611,21 +611,16 @@ _thr_sched_switch(struct pthread *curthread)
void
_thr_sched_switch_unlocked(struct pthread *curthread)
{
- struct pthread *td;
struct pthread_sigframe psf;
struct kse *curkse;
- int ret;
- volatile int uts_once;
volatile int resume_once = 0;
- ucontext_t uc;
+ ucontext_t *uc;
/* We're in the scheduler, 5 by 5: */
curkse = _get_curkse();
curthread->need_switchout = 1; /* The thread yielded on its own. */
curthread->critical_yield = 0; /* No need to yield anymore. */
- thr_accounting(curthread);
-
/* Thread can unlock the scheduler lock. */
curthread->lock_switch = 1;
@@ -638,109 +633,44 @@ _thr_sched_switch_unlocked(struct pthread *curthread)
psf.psf_valid = 0;
curthread->curframe = &psf;
- /*
- * Enter the scheduler if any one of the following is true:
- *
- * o The current thread is dead; it's stack needs to be
- * cleaned up and it can't be done while operating on
- * it.
- * o The current thread has signals pending, should
- * let scheduler install signal trampoline for us.
- * o There are no runnable threads.
- * o The next thread to run won't unlock the scheduler
- * lock. A side note: the current thread may be run
- * instead of the next thread in the run queue, but
- * we don't bother checking for that.
- */
if (curthread->attr.flags & PTHREAD_SCOPE_SYSTEM)
kse_sched_single(&curkse->k_kcb->kcb_kmbx);
- else if ((curthread->state == PS_DEAD) ||
- (((td = KSE_RUNQ_FIRST(curkse)) == NULL) &&
- (curthread->state != PS_RUNNING)) ||
- ((td != NULL) && (td->lock_switch == 0))) {
+ else {
curkse->k_switch = 1;
_thread_enter_uts(curthread->tcb, curkse->k_kcb);
}
- else {
- uts_once = 0;
- THR_GETCONTEXT(&curthread->tcb->tcb_tmbx.tm_context);
- if (uts_once == 0) {
- uts_once = 1;
-
- /* Switchout the current thread. */
- kse_switchout_thread(curkse, curthread);
- _tcb_set(curkse->k_kcb, NULL);
-
- /* Choose another thread to run. */
- td = KSE_RUNQ_FIRST(curkse);
- KSE_RUNQ_REMOVE(curkse, td);
- curkse->k_curthread = td;
-
- /*
- * Make sure the current thread's kse points to
- * this kse.
- */
- td->kse = curkse;
-
- /*
- * Reset the time slice if this thread is running
- * for the first time or running again after using
- * its full time slice allocation.
- */
- if (td->slice_usec == -1)
- td->slice_usec = 0;
-
- /* Mark the thread active. */
- td->active = 1;
-
- /* Remove the frame reference. */
- td->curframe = NULL;
-
- /*
- * Continue the thread at its current frame.
- * Note: TCB is set in _thread_switch
- */
- ret = _thread_switch(curkse->k_kcb, td->tcb, 0);
- /* This point should not be reached. */
- if (ret != 0)
- PANIC("Bad return from _thread_switch");
- PANIC("Thread has returned from _thread_switch");
- }
- }
+
+ /*
+ * It is ugly we must increase critical count, because we
+ * have a frame saved, we must backout state in psf
+ * before we can process signals.
+ */
+ curthread->critical_count += psf.psf_valid;
- if (psf.psf_valid) {
- /*
- * It is ugly we must increase critical count, because we
- * have a frame saved, we must backout state in psf
- * before we can process signals.
- */
- curthread->critical_count++;
- }
+ /*
+ * Unlock the scheduling queue and leave the
+ * critical region.
+ */
+ /* Don't trust this after a switch! */
+ curkse = _get_curkse();
- if (curthread->lock_switch != 0) {
- /*
- * Unlock the scheduling queue and leave the
- * critical region.
- */
- /* Don't trust this after a switch! */
- curkse = _get_curkse();
+ curthread->lock_switch = 0;
+ KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
+ _kse_critical_leave(&curthread->tcb->tcb_tmbx);
- curthread->lock_switch = 0;
- KSE_SCHED_UNLOCK(curkse, curkse->k_kseg);
- _kse_critical_leave(&curthread->tcb->tcb_tmbx);
- }
/*
* This thread is being resumed; check for cancellations.
*/
if ((psf.psf_valid ||
((curthread->check_pending || THR_NEED_ASYNC_CANCEL(curthread))
&& !THR_IN_CRITICAL(curthread)))) {
+ uc = alloca(sizeof(ucontext_t));
resume_once = 0;
- THR_GETCONTEXT(&uc);
+ THR_GETCONTEXT(uc);
if (resume_once == 0) {
resume_once = 1;
curthread->check_pending = 0;
- thr_resume_check(curthread, &uc, &psf);
+ thr_resume_check(curthread, uc, &psf);
}
}
THR_ACTIVATE_LAST_LOCK(curthread);
@@ -2443,6 +2373,8 @@ _thr_alloc(struct pthread *curthread)
free(thread);
thread = NULL;
} else {
+ thread->siginfo = calloc(_SIG_MAXSIG,
+ sizeof(siginfo_t));
/*
* Initialize thread locking.
* Lock initializing needs malloc, so don't
@@ -2494,6 +2426,7 @@ thr_destroy(struct pthread *thread)
_lockuser_destroy(&thread->lockusers[i]);
_lock_destroy(&thread->lock);
_tcb_dtor(thread->tcb);
+ free(thread->siginfo);
free(thread);
}
diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h
index d8453ffa81b0..fc5f97e7c97a 100644
--- a/lib/libpthread/thread/thr_private.h
+++ b/lib/libpthread/thread/thr_private.h
@@ -244,13 +244,13 @@ do { \
*/
#define KSE_LOCK_ACQUIRE(kse, lck) \
do { \
- if ((kse)->k_locklevel >= MAX_KSE_LOCKLEVEL) \
- PANIC("Exceeded maximum lock level"); \
- else { \
+ if ((kse)->k_locklevel < MAX_KSE_LOCKLEVEL) { \
(kse)->k_locklevel++; \
_lock_acquire((lck), \
&(kse)->k_lockusers[(kse)->k_locklevel - 1], 0); \
} \
+ else \
+ PANIC("Exceeded maximum lock level"); \
} while (0)
#define KSE_LOCK_RELEASE(kse, lck) \
@@ -665,7 +665,7 @@ struct pthread {
* Used for tracking delivery of signal handlers.
*/
struct pthread_sigframe *curframe;
- siginfo_t siginfo[_SIG_MAXSIG];
+ siginfo_t *siginfo;
/*
* Cancelability flags - the lower 2 bits are used by cancel
@@ -846,15 +846,14 @@ do { \
#define THR_LOCK_ACQUIRE(thrd, lck) \
do { \
- if ((thrd)->locklevel >= MAX_THR_LOCKLEVEL) \
- PANIC("Exceeded maximum lock level"); \
- else { \
+ if ((thrd)->locklevel < MAX_THR_LOCKLEVEL) { \
THR_DEACTIVATE_LAST_LOCK(thrd); \
(thrd)->locklevel++; \
_lock_acquire((lck), \
&(thrd)->lockusers[(thrd)->locklevel - 1], \
(thrd)->active_priority); \
- } \
+ } else \
+ PANIC("Exceeded maximum lock level"); \
} while (0)
#define THR_LOCK_RELEASE(thrd, lck) \