summaryrefslogtreecommitdiffstats
path: root/lib/libpthread
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2003-11-29 14:22:29 +0000
committerdavidxu <davidxu@FreeBSD.org>2003-11-29 14:22:29 +0000
commit2cc3179bff30b557c1e7aa6ae05b785a6a6ea541 (patch)
tree4a32c5e1d4d462b62323406ce2e8a4f54b00fc1b /lib/libpthread
parente9f088c4690b0c842d1bca9a0dabf69d914a8c36 (diff)
downloadFreeBSD-src-2cc3179bff30b557c1e7aa6ae05b785a6a6ea541.zip
FreeBSD-src-2cc3179bff30b557c1e7aa6ae05b785a6a6ea541.tar.gz
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)
Diffstat (limited to 'lib/libpthread')
-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 5186c52..7fd8b38 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 d8453ff..fc5f97e 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) \
OpenPOWER on IntegriCloud