summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_kse.c
diff options
context:
space:
mode:
authordavidxu <davidxu@FreeBSD.org>2003-02-20 08:18:15 +0000
committerdavidxu <davidxu@FreeBSD.org>2003-02-20 08:18:15 +0000
commitd08eff5aaa66076b328937fb041e0151f6ede542 (patch)
tree401288c5feee9a5b4aefd2c3518465123a82a17e /sys/kern/kern_kse.c
parenta46312efdc71dcf1aac1dcda3dd813b6c6a9b237 (diff)
downloadFreeBSD-src-d08eff5aaa66076b328937fb041e0151f6ede542.zip
FreeBSD-src-d08eff5aaa66076b328937fb041e0151f6ede542.tar.gz
Add a timeout parameter to kse_release.
Diffstat (limited to 'sys/kern/kern_kse.c')
-rw-r--r--sys/kern/kern_kse.c38
1 files changed, 27 insertions, 11 deletions
diff --git a/sys/kern/kern_kse.c b/sys/kern/kern_kse.c
index fc021ac..7bd1c29 100644
--- a/sys/kern/kern_kse.c
+++ b/sys/kern/kern_kse.c
@@ -465,7 +465,7 @@ kse_exit(struct thread *td, struct kse_exit_args *uap)
*/
/*
struct kse_release_args {
- register_t dummy;
+ struct timespec *timeout;
};
*/
int
@@ -473,6 +473,9 @@ kse_release(struct thread *td, struct kse_release_args *uap)
{
struct proc *p;
struct ksegrp *kg;
+ struct timespec ts, ts2, ts3, timeout;
+ struct timeval tv;
+ int error;
p = td->td_proc;
kg = td->td_ksegrp;
@@ -483,25 +486,38 @@ kse_release(struct thread *td, struct kse_release_args *uap)
if ((td->td_mailbox != NULL) || (td->td_ksegrp->kg_numupcalls == 0))
return (EINVAL);
KASSERT((td->td_upcall != NULL), ("%s: not own an upcall", __func__));
-
- PROC_LOCK(p);
+ if (uap->timeout != NULL) {
+ if ((error = copyin(uap->timeout, &timeout, sizeof(timeout))))
+ return (error);
+ getnanouptime(&ts);
+ timespecadd(&ts, &timeout);
+ TIMESPEC_TO_TIMEVAL(&tv, &timeout);
+ }
mtx_lock_spin(&sched_lock);
/* Change OURSELF to become an upcall. */
td->td_flags = TDF_UPCALLING;
if (p->p_sflag & PS_NEEDSIGCHK)
td->td_flags |= TDF_ASTPENDING;
- if ((td->td_upcall->ku_flags & KUF_DOUPCALL) == 0 &&
- (kg->kg_completed == NULL)) {
+ mtx_unlock_spin(&sched_lock);
+ PROC_LOCK(p);
+ while ((td->td_upcall->ku_flags & KUF_DOUPCALL) == 0 &&
+ (kg->kg_completed == NULL)) {
kg->kg_upsleeps++;
- mtx_unlock_spin(&sched_lock);
- msleep(&kg->kg_completed, &p->p_mtx, PPAUSE|PCATCH, "ksepause",
- NULL);
+ error = msleep(&kg->kg_completed, &p->p_mtx, PPAUSE|PCATCH,
+ "kse_rel", (uap->timeout ? tvtohz(&tv) : 0));
kg->kg_upsleeps--;
PROC_UNLOCK(p);
- } else {
- mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
+ if (uap->timeout == NULL || error != EWOULDBLOCK)
+ return (0);
+ getnanouptime(&ts2);
+ if (timespeccmp(&ts2, &ts, >=))
+ return (0);
+ ts3 = ts;
+ timespecsub(&ts3, &ts2);
+ TIMESPEC_TO_TIMEVAL(&tv, &ts3);
+ PROC_LOCK(p);
}
+ PROC_UNLOCK(p);
return (0);
}
OpenPOWER on IntegriCloud