summaryrefslogtreecommitdiffstats
path: root/lib/libpthread/thread/thr_kern.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libpthread/thread/thr_kern.c')
-rw-r--r--lib/libpthread/thread/thr_kern.c64
1 files changed, 45 insertions, 19 deletions
diff --git a/lib/libpthread/thread/thr_kern.c b/lib/libpthread/thread/thr_kern.c
index 6176b71..c4e9d5e 100644
--- a/lib/libpthread/thread/thr_kern.c
+++ b/lib/libpthread/thread/thr_kern.c
@@ -42,6 +42,7 @@ __FBSDID("$FreeBSD$");
#include <machine/atomic.h>
#include <assert.h>
+#include <errno.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
@@ -134,7 +135,7 @@ static void kse_sched_single(struct kse *curkse);
static void kse_switchout_thread(struct kse *kse, struct pthread *thread);
static void kse_wait(struct kse *kse, struct pthread *td_wait);
static void kse_free_unlocked(struct kse *kse);
-static void kseg_free(struct kse_group *kseg);
+static void kseg_free_unlocked(struct kse_group *kseg);
static void kseg_init(struct kse_group *kseg);
static void kseg_reinit(struct kse_group *kseg);
static void kse_waitq_insert(struct pthread *thread);
@@ -404,7 +405,7 @@ _kse_lock_wait(struct lock *lock, struct lockuser *lu)
* is granted.
*/
saved_flags = curkse->k_mbx.km_flags;
- curkse->k_mbx.km_flags |= KMF_NOUPCALL;
+ curkse->k_mbx.km_flags |= KMF_NOUPCALL | KMF_NOCOMPLETED;
kse_release(&ts);
curkse->k_mbx.km_flags = saved_flags;
@@ -703,6 +704,9 @@ kse_sched_multi(struct kse *curkse)
struct pthread_sigframe *curframe;
int ret;
+ THR_ASSERT(curkse->k_mbx.km_curthread == NULL,
+ "Mailbox not null in kse_sched_multi");
+
/* Check for first time initialization: */
if ((curkse->k_flags & KF_INITIALIZED) == 0) {
/* Setup this KSEs specific data. */
@@ -714,8 +718,10 @@ kse_sched_multi(struct kse *curkse)
}
/* This may have returned from a kse_release(). */
- if (KSE_WAITING(curkse))
+ if (KSE_WAITING(curkse)) {
+ DBG_MSG("Entered upcall when KSE is waiting.");
KSE_CLEAR_WAIT(curkse);
+ }
/* Lock the scheduling lock. */
KSE_SCHED_LOCK(curkse, curkse->k_kseg);
@@ -1067,7 +1073,7 @@ _thr_gc(struct pthread *curthread)
crit = _kse_critical_enter();
KSE_LOCK_ACQUIRE(curthread->kse, &kse_lock);
kse_free_unlocked(td->kse);
- kseg_free(td->kseg);
+ kseg_free_unlocked(td->kseg);
KSE_LOCK_RELEASE(curthread->kse, &kse_lock);
_kse_critical_leave(crit);
}
@@ -1080,12 +1086,13 @@ _thr_gc(struct pthread *curthread)
/*
* Only new threads that are running or suspended may be scheduled.
*/
-void
+int
_thr_schedule_add(struct pthread *curthread, struct pthread *newthread)
{
struct kse *curkse;
kse_critical_t crit;
int need_start;
+ int ret;
/*
* If this is the first time creating a thread, make sure
@@ -1106,6 +1113,7 @@ _thr_schedule_add(struct pthread *curthread, struct pthread *newthread)
KSEG_THRQ_ADD(newthread->kseg, newthread);
TAILQ_INSERT_TAIL(&newthread->kseg->kg_kseq, newthread->kse,
k_kgqe);
+ newthread->kseg->kg_ksecount = 1;
if (newthread->state == PS_RUNNING)
THR_RUNQ_INSERT_TAIL(newthread);
newthread->kse->k_curthread = NULL;
@@ -1119,7 +1127,9 @@ _thr_schedule_add(struct pthread *curthread, struct pthread *newthread)
curkse = _get_curkse();
_ksd_setprivate(&newthread->kse->k_ksd);
newthread->kse->k_flags |= KF_INITIALIZED;
- kse_create(&newthread->kse->k_mbx, 1);
+ ret = kse_create(&newthread->kse->k_mbx, 1);
+ if (ret != 0)
+ ret = errno;
_ksd_setprivate(&curkse->k_ksd);
_kse_critical_leave(crit);
}
@@ -1156,7 +1166,9 @@ _thr_schedule_add(struct pthread *curthread, struct pthread *newthread)
*/
KSE_WAKEUP(newthread->kse);
}
+ ret = 0;
}
+ return (ret);
}
void
@@ -1420,13 +1432,13 @@ kse_wait(struct kse *kse, struct pthread *td_wait)
KSE_GET_TOD(kse, &ts);
if ((td_wait == NULL) || (td_wait->wakeup_time.tv_sec < 0)) {
- /* Limit sleep to no more than 2 minutes. */
- ts_sleep.tv_sec = 120;
+ /* Limit sleep to no more than 1 minute. */
+ ts_sleep.tv_sec = 60;
ts_sleep.tv_nsec = 0;
} else {
TIMESPEC_SUB(&ts_sleep, &td_wait->wakeup_time, &ts);
- if (ts_sleep.tv_sec > 120) {
- ts_sleep.tv_sec = 120;
+ if (ts_sleep.tv_sec > 60) {
+ ts_sleep.tv_sec = 60;
ts_sleep.tv_nsec = 0;
}
}
@@ -1462,6 +1474,7 @@ kse_fini(struct kse *kse)
/* Remove this KSE from the KSEG's list of KSEs. */
KSE_SCHED_LOCK(kse, kse->k_kseg);
TAILQ_REMOVE(&kse->k_kseg->kg_kseq, kse, k_kgqe);
+ kse->k_kseg->kg_ksecount--;
if (TAILQ_EMPTY(&kse->k_kseg->kg_kseq))
free_kseg = kse->k_kseg;
KSE_SCHED_UNLOCK(kse, kse->k_kseg);
@@ -1472,7 +1485,7 @@ kse_fini(struct kse *kse)
*/
KSE_LOCK_ACQUIRE(kse, &kse_lock);
if (free_kseg != NULL)
- kseg_free(free_kseg);
+ kseg_free_unlocked(free_kseg);
kse_free_unlocked(kse);
KSE_LOCK_RELEASE(kse, &kse_lock);
kse_exit();
@@ -1491,14 +1504,11 @@ kse_fini(struct kse *kse)
if ((active_kse_count > 1) &&
(kse->k_kseg->kg_threadcount == 0)) {
KSE_SCHED_UNLOCK(kse, kse->k_kseg);
- /*
- * XXX - We need a way for the KSE to do a timed
- * wait.
- */
kse_release(&ts);
/* The above never returns. */
}
- KSE_SCHED_UNLOCK(kse, kse->k_kseg);
+ else
+ KSE_SCHED_UNLOCK(kse, kse->k_kseg);
/* There are no more threads; exit this process: */
if (kse->k_kseg->kg_threadcount == 0) {
@@ -1708,7 +1718,7 @@ _kseg_alloc(struct pthread *curthread)
* no more threads that reference it.
*/
static void
-kseg_free(struct kse_group *kseg)
+kseg_free_unlocked(struct kse_group *kseg)
{
TAILQ_REMOVE(&active_kse_groupq, kseg, kg_qe);
TAILQ_INSERT_HEAD(&free_kse_groupq, kseg, kg_qe);
@@ -1716,6 +1726,20 @@ kseg_free(struct kse_group *kseg)
active_kseg_count--;
}
+void
+_kseg_free(struct kse_group *kseg)
+{
+ struct kse *curkse;
+ kse_critical_t crit;
+
+ crit = _kse_critical_enter();
+ curkse = _get_curkse();
+ KSE_LOCK_ACQUIRE(curkse, &kse_lock);
+ kseg_free_unlocked(kseg);
+ KSE_LOCK_RELEASE(curkse, &kse_lock);
+ _kse_critical_leave(crit);
+}
+
/*
* Allocate a new KSE.
*
@@ -1747,8 +1771,8 @@ _kse_alloc(struct pthread *curthread)
if (kse != NULL) {
TAILQ_REMOVE(&free_kseq, kse, k_qe);
free_kse_count--;
- active_kse_count++;
TAILQ_INSERT_TAIL(&active_kseq, kse, k_qe);
+ active_kse_count++;
}
KSE_LOCK_RELEASE(curthread->kse, &kse_lock);
_kse_critical_leave(crit);
@@ -1817,8 +1841,8 @@ _kse_alloc(struct pthread *curthread)
return (NULL);
}
kse->k_flags = 0;
- active_kse_count++;
TAILQ_INSERT_TAIL(&active_kseq, kse, k_qe);
+ active_kse_count++;
if (curthread != NULL) {
KSE_LOCK_RELEASE(curthread->kse, &kse_lock);
_kse_critical_leave(crit);
@@ -1830,6 +1854,7 @@ _kse_alloc(struct pthread *curthread)
void
kse_free_unlocked(struct kse *kse)
{
+ TAILQ_REMOVE(&active_kseq, kse, k_qe);
active_kse_count--;
kse->k_kseg = NULL;
kse->k_flags &= ~KF_INITIALIZED;
@@ -1868,6 +1893,7 @@ kseg_reinit(struct kse_group *kseg)
TAILQ_INIT(&kseg->kg_threadq);
TAILQ_INIT(&kseg->kg_schedq.sq_waitq);
kseg->kg_threadcount = 0;
+ kseg->kg_ksecount = 0;
kseg->kg_idle_kses = 0;
kseg->kg_flags = 0;
}
OpenPOWER on IntegriCloud