summaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
authordeischen <deischen@FreeBSD.org>2003-04-23 21:46:50 +0000
committerdeischen <deischen@FreeBSD.org>2003-04-23 21:46:50 +0000
commitf8027ceb95ebbec411424424e7be00f63485adb8 (patch)
treeaf28d42652346683148a8b0c30e59e30d9b9b8dd /lib
parentb86b779077f57b963024aa4ff279e986002d957b (diff)
downloadFreeBSD-src-f8027ceb95ebbec411424424e7be00f63485adb8.zip
FreeBSD-src-f8027ceb95ebbec411424424e7be00f63485adb8.tar.gz
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
Diffstat (limited to 'lib')
-rw-r--r--lib/libkse/sys/thr_error.c6
-rw-r--r--lib/libkse/thread/thr_kern.c31
-rw-r--r--lib/libkse/thread/thr_private.h2
-rw-r--r--lib/libpthread/sys/thr_error.c6
-rw-r--r--lib/libpthread/thread/thr_kern.c31
-rw-r--r--lib/libpthread/thread/thr_private.h2
6 files changed, 76 insertions, 2 deletions
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 <pthread.h>
#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 <pthread.h>
#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 *);
OpenPOWER on IntegriCloud