diff options
author | davidxu <davidxu@FreeBSD.org> | 2002-11-18 01:59:31 +0000 |
---|---|---|
committer | davidxu <davidxu@FreeBSD.org> | 2002-11-18 01:59:31 +0000 |
commit | 51e72f155cee881407bd9846fb7536ba9d389507 (patch) | |
tree | 18ead637adf47f0ef341097ad01c39153e03fa2b /sys/kern/kern_kse.c | |
parent | 8ebcb8237164e4662037f02b98cc426e8367ceec (diff) | |
download | FreeBSD-src-51e72f155cee881407bd9846fb7536ba9d389507.zip FreeBSD-src-51e72f155cee881407bd9846fb7536ba9d389507.tar.gz |
1. Support versioning and wall clock in kse mailbox,
also add rusage time in thread mailbox.
2. Minor change for thread limit code in thread_user_enter(),
fix typo in kse_release() last I committed.
Reviewed by: deischen, mini
Diffstat (limited to 'sys/kern/kern_kse.c')
-rw-r--r-- | sys/kern/kern_kse.c | 117 |
1 files changed, 108 insertions, 9 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c index 1837e2a..2672c43 100644 --- a/sys/kern/kern_kse.c +++ b/sys/kern/kern_kse.c @@ -374,7 +374,7 @@ kse_release(struct thread *td, struct kse_release_args *uap) msleep(p->p_sigacts, &p->p_mtx, PPAUSE|PCATCH, "pause", 0); mtx_lock_spin(&sched_lock); - td->td_flags &= ~TDF_UNBOUND; + td->td_flags |= TDF_UNBOUND; thread_schedule_upcall(td, td->td_kse); thread_exit(); } @@ -783,6 +783,7 @@ thread_export_context(struct thread *td) void *addr; int error; ucontext_t uc; + uint temp; p = td->td_proc; kg = td->td_ksegrp; @@ -820,10 +821,7 @@ thread_export_context(struct thread *td) for (;;) { mbx = (uintptr_t)kg->kg_completed; if (suword(addr, mbx)) { - PROC_LOCK(p); - psignal(p, SIGSEGV); - PROC_UNLOCK(p); - return (EFAULT); + goto bad; } PROC_LOCK(p); if (mbx == (uintptr_t)kg->kg_completed) { @@ -833,7 +831,18 @@ thread_export_context(struct thread *td) } PROC_UNLOCK(p); } + addr = (caddr_t)td->td_mailbox + + offsetof(struct kse_thr_mailbox, tm_sticks); + temp = fuword(addr) + td->td_usticks; + if (suword(addr, temp)) + goto bad; return (0); + +bad: + PROC_LOCK(p); + psignal(p, SIGSEGV); + PROC_UNLOCK(p); + return (EFAULT); } /* @@ -874,6 +883,78 @@ thread_link_mboxes(struct ksegrp *kg, struct kse *ke) } /* + * This function should be called at statclock interrupt time + */ +int +thread_add_ticks_intr(int user, uint ticks) +{ + struct thread *td = curthread; + struct kse *ke = td->td_kse; + + if (ke->ke_mailbox == NULL) + return -1; + if (user) { + /* Current always do via ast() */ + ke->ke_flags |= KEF_ASTPENDING; + ke->ke_uuticks += ticks; + } else { + if (td->td_mailbox != NULL) + td->td_usticks += ticks; + else + ke->ke_usticks += ticks; + } + return 0; +} + +static int +thread_update_uticks(void) +{ + struct thread *td = curthread; + struct proc *p = td->td_proc; + struct kse *ke = td->td_kse; + struct kse_thr_mailbox *tmbx; + caddr_t addr; + uint uticks, sticks; + struct timespec ts; + + KASSERT(!(td->td_flags & TDF_UNBOUND), ("thread not bound.")); + + if (ke->ke_mailbox == NULL) + return 0; + + nanotime(&ts); + if (copyout(&ts, (caddr_t)&ke->ke_mailbox->km_timeofday, sizeof(ts))) + goto bad; + + uticks = ke->ke_uuticks; + ke->ke_uuticks = 0; + sticks = ke->ke_usticks; + ke->ke_usticks = 0; + tmbx = (void *)fuword((caddr_t)ke->ke_mailbox + + offsetof(struct kse_mailbox, km_curthread)); + if ((tmbx == NULL) || (tmbx == (void *)-1)) + return 0; + if (uticks) { + addr = (caddr_t)tmbx + offsetof(struct kse_thr_mailbox, tm_uticks); + uticks += fuword(addr); + if (suword(addr, uticks)) + goto bad; + } + if (sticks) { + addr = (caddr_t)tmbx + offsetof(struct kse_thr_mailbox, tm_sticks); + sticks += fuword(addr); + if (suword(addr, sticks)) + goto bad; + } + return 0; +bad: + PROC_LOCK(p); + psignal(p, SIGSEGV); + PROC_UNLOCK(p); + return -1; +} + +/* * Discard the current thread and exit from its context. * * Because we can't free a thread while we're operating under its context, @@ -1267,14 +1348,28 @@ thread_user_enter(struct proc *p, struct thread *td) (void *)fuword( (void *)&ke->ke_mailbox->km_curthread); #endif if ((td->td_mailbox == NULL) || - (td->td_mailbox == (void *)-1) || - (p->p_numthreads > max_threads_per_proc)) { + (td->td_mailbox == (void *)-1)) { td->td_mailbox = NULL; /* single thread it.. */ + mtx_lock_spin(&sched_lock); td->td_flags &= ~TDF_UNBOUND; + mtx_unlock_spin(&sched_lock); } else { - if (td->td_standin == NULL) - td->td_standin = thread_alloc(); + /* + * when thread limit reached, act like that the thread + * has already done an upcall. + */ + if (p->p_numthreads > max_threads_per_proc) { + if (td->td_standin != NULL) + thread_stash(td->td_standin); + td->td_standin = NULL; + } else { + if (td->td_standin == NULL) + td->td_standin = thread_alloc(); + } + mtx_lock_spin(&sched_lock); td->td_flags |= TDF_UNBOUND; + mtx_unlock_spin(&sched_lock); + td->td_usticks = 0; } } } @@ -1335,6 +1430,7 @@ thread_userret(struct thread *td, struct trapframe *frame) */ error = thread_export_context(td); td->td_mailbox = NULL; + td->td_usticks = 0; if (error) { /* * If we are not running on a borrowed KSE, then @@ -1352,6 +1448,7 @@ thread_userret(struct thread *td, struct trapframe *frame) td->td_flags &= ~TDF_UNBOUND; PROC_UNLOCK(td->td_proc); mtx_unlock_spin(&sched_lock); + thread_update_uticks(); return (error); /* go sync */ } thread_exit(); @@ -1424,6 +1521,7 @@ thread_userret(struct thread *td, struct trapframe *frame) } } + thread_update_uticks(); /* * To get here, we know there is no other need for our * KSE so we can proceed. If not upcalling, go back to @@ -1468,6 +1566,7 @@ thread_userret(struct thread *td, struct trapframe *frame) offsetof(struct kse_mailbox, km_curthread), 0); #else /* if user pointer arithmetic is ok in the kernel */ error = suword((caddr_t)&ke->ke_mailbox->km_curthread, 0); + ke->ke_uuticks = ke->ke_usticks = 0; #endif if (!error) return (0); |