From f8027ceb95ebbec411424424e7be00f63485adb8 Mon Sep 17 00:00:00 2001 From: deischen Date: Wed, 23 Apr 2003 21:46:50 +0000 Subject: Protect thread errno from being changed while operating on behalf of the KSE. Add a kse_reinit function to reinitialize a reused KSE. Submitted by: davidxu --- lib/libkse/sys/thr_error.c | 6 +++++- lib/libkse/thread/thr_kern.c | 31 +++++++++++++++++++++++++++++++ lib/libkse/thread/thr_private.h | 2 ++ lib/libpthread/sys/thr_error.c | 6 +++++- lib/libpthread/thread/thr_kern.c | 31 +++++++++++++++++++++++++++++++ lib/libpthread/thread/thr_private.h | 2 ++ 6 files changed, 76 insertions(+), 2 deletions(-) (limited to 'lib') diff --git a/lib/libkse/sys/thr_error.c b/lib/libkse/sys/thr_error.c index a4a8507..6f19f93 100644 --- a/lib/libkse/sys/thr_error.c +++ b/lib/libkse/sys/thr_error.c @@ -36,14 +36,18 @@ #include #include "libc_private.h" #include "thr_private.h" + extern int errno; -int * __error() +int * +__error(void) { struct pthread *curthread; if (__isthreaded == 0) return (&errno); + else if (_kse_in_critical()) + return &(_get_curkse()->k_error); else { curthread = _get_curthread(); if ((curthread == NULL) || (curthread == _thr_initial)) diff --git a/lib/libkse/thread/thr_kern.c b/lib/libkse/thread/thr_kern.c index 2da990e..63283f7 100644 --- a/lib/libkse/thread/thr_kern.c +++ b/lib/libkse/thread/thr_kern.c @@ -128,6 +128,7 @@ static void kse_check_completed(struct kse *kse); static void kse_check_waitq(struct kse *kse); static void kse_check_signals(struct kse *kse); static void kse_fini(struct kse *curkse); +static void kse_reinit(struct kse *kse); static void kse_sched_multi(struct kse *curkse); #ifdef NOT_YET static void kse_sched_single(struct kse *curkse); @@ -270,6 +271,10 @@ _kse_single_thread(struct pthread *curthread) /* Free the to-be-gc'd threads. */ while ((thread = TAILQ_FIRST(&_thread_gc_list)) != NULL) { TAILQ_REMOVE(&_thread_gc_list, thread, gcle); + for (i = 0; i < MAX_THR_LOCKLEVEL; i++) { + _lockuser_destroy(&thread->lockusers[i]); + } + _lock_destroy(&thread->lock); free(thread); } TAILQ_INIT(&gc_ksegq); @@ -508,6 +513,12 @@ _kse_critical_leave(kse_critical_t crit) THR_YIELD_CHECK(curthread); } +int +_kse_in_critical(void) +{ + return (_ksd_get_tmbx() == NULL); +} + void _thr_critical_enter(struct pthread *thread) { @@ -1777,6 +1788,8 @@ _kse_alloc(struct pthread *curthread) } KSE_LOCK_RELEASE(curthread->kse, &kse_lock); _kse_critical_leave(crit); + if (kse != NULL) + kse_reinit(kse); } if ((kse == NULL) && ((kse = (struct kse *)malloc(sizeof(*kse))) != NULL)) { @@ -1852,6 +1865,24 @@ _kse_alloc(struct pthread *curthread) return (kse); } +static void +kse_reinit(struct kse *kse) +{ + bzero(&kse->k_mbx, sizeof(struct kse_mailbox)); + kse->k_curthread = 0; + kse->k_kseg = 0; + kse->k_schedq = 0; + kse->k_locklevel = 0; + sigemptyset(&kse->k_sigmask); + bzero(&kse->k_sigq, sizeof(kse->k_sigq)); + kse->k_check_sigq = 0; + kse->k_flags = KF_INITIALIZED; + kse->k_waiting = 0; + kse->k_error = 0; + kse->k_cpu = 0; + kse->k_done = 0; +} + void kse_free_unlocked(struct kse *kse) { diff --git a/lib/libkse/thread/thr_private.h b/lib/libkse/thread/thr_private.h index a554796..fc2e4ee 100644 --- a/lib/libkse/thread/thr_private.h +++ b/lib/libkse/thread/thr_private.h @@ -197,6 +197,7 @@ struct kse { #define KF_STARTED 0x0001 /* kernel kse created */ #define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */ int k_waiting; + int k_error; /* syscall errno in critical */ int k_cpu; /* CPU ID when bound */ int k_done; /* this KSE is done */ }; @@ -1014,6 +1015,7 @@ void _set_curkse(struct kse *); struct kse *_kse_alloc(struct pthread *); kse_critical_t _kse_critical_enter(void); void _kse_critical_leave(kse_critical_t); +int _kse_in_critical(void); void _kse_free(struct pthread *, struct kse *); void _kse_init(); struct kse_group *_kseg_alloc(struct pthread *); diff --git a/lib/libpthread/sys/thr_error.c b/lib/libpthread/sys/thr_error.c index a4a8507..6f19f93 100644 --- a/lib/libpthread/sys/thr_error.c +++ b/lib/libpthread/sys/thr_error.c @@ -36,14 +36,18 @@ #include #include "libc_private.h" #include "thr_private.h" + extern int errno; -int * __error() +int * +__error(void) { struct pthread *curthread; if (__isthreaded == 0) return (&errno); + else if (_kse_in_critical()) + return &(_get_curkse()->k_error); else { curthread = _get_curthread(); if ((curthread == NULL) || (curthread == _thr_initial)) diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c index 2da990e..63283f7 100644 --- a/lib/libpthread/thread/thr_kern.c +++ b/lib/libpthread/thread/thr_kern.c @@ -128,6 +128,7 @@ static void kse_check_completed(struct kse *kse); static void kse_check_waitq(struct kse *kse); static void kse_check_signals(struct kse *kse); static void kse_fini(struct kse *curkse); +static void kse_reinit(struct kse *kse); static void kse_sched_multi(struct kse *curkse); #ifdef NOT_YET static void kse_sched_single(struct kse *curkse); @@ -270,6 +271,10 @@ _kse_single_thread(struct pthread *curthread) /* Free the to-be-gc'd threads. */ while ((thread = TAILQ_FIRST(&_thread_gc_list)) != NULL) { TAILQ_REMOVE(&_thread_gc_list, thread, gcle); + for (i = 0; i < MAX_THR_LOCKLEVEL; i++) { + _lockuser_destroy(&thread->lockusers[i]); + } + _lock_destroy(&thread->lock); free(thread); } TAILQ_INIT(&gc_ksegq); @@ -508,6 +513,12 @@ _kse_critical_leave(kse_critical_t crit) THR_YIELD_CHECK(curthread); } +int +_kse_in_critical(void) +{ + return (_ksd_get_tmbx() == NULL); +} + void _thr_critical_enter(struct pthread *thread) { @@ -1777,6 +1788,8 @@ _kse_alloc(struct pthread *curthread) } KSE_LOCK_RELEASE(curthread->kse, &kse_lock); _kse_critical_leave(crit); + if (kse != NULL) + kse_reinit(kse); } if ((kse == NULL) && ((kse = (struct kse *)malloc(sizeof(*kse))) != NULL)) { @@ -1852,6 +1865,24 @@ _kse_alloc(struct pthread *curthread) return (kse); } +static void +kse_reinit(struct kse *kse) +{ + bzero(&kse->k_mbx, sizeof(struct kse_mailbox)); + kse->k_curthread = 0; + kse->k_kseg = 0; + kse->k_schedq = 0; + kse->k_locklevel = 0; + sigemptyset(&kse->k_sigmask); + bzero(&kse->k_sigq, sizeof(kse->k_sigq)); + kse->k_check_sigq = 0; + kse->k_flags = KF_INITIALIZED; + kse->k_waiting = 0; + kse->k_error = 0; + kse->k_cpu = 0; + kse->k_done = 0; +} + void kse_free_unlocked(struct kse *kse) { diff --git a/lib/libpthread/thread/thr_private.h b/lib/libpthread/thread/thr_private.h index a554796..fc2e4ee 100644 --- a/lib/libpthread/thread/thr_private.h +++ b/lib/libpthread/thread/thr_private.h @@ -197,6 +197,7 @@ struct kse { #define KF_STARTED 0x0001 /* kernel kse created */ #define KF_INITIALIZED 0x0002 /* initialized on 1st upcall */ int k_waiting; + int k_error; /* syscall errno in critical */ int k_cpu; /* CPU ID when bound */ int k_done; /* this KSE is done */ }; @@ -1014,6 +1015,7 @@ void _set_curkse(struct kse *); struct kse *_kse_alloc(struct pthread *); kse_critical_t _kse_critical_enter(void); void _kse_critical_leave(kse_critical_t); +int _kse_in_critical(void); void _kse_free(struct pthread *, struct kse *); void _kse_init(); struct kse_group *_kseg_alloc(struct pthread *); -- cgit v1.1