Separate thread synchronization from signals in libthr. Instead
use msleep() and wakeup_one(). Discussed with: jhb, peter, tjr
This commit is contained in:
parent
9af414d156
commit
1713a51661
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=127482
@ -604,3 +604,5 @@
|
||||
439 UNIMPL extattr_list_link
|
||||
440 UNIMPL kse_switchin
|
||||
441 UNIMPL ksem_timedwait
|
||||
442 MNOPROTO { int thr_suspend(const struct timespec *timeout); }
|
||||
443 MNOPROTO { int thr_wake(thr_id_t id); }
|
||||
|
@ -254,3 +254,64 @@ thr_kill(struct thread *td, struct thr_kill_args *uap)
|
||||
PROC_UNLOCK(p);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
thr_suspend(struct thread *td, struct thr_suspend_args *uap)
|
||||
/* const struct timespec *timeout */
|
||||
{
|
||||
struct timespec ts;
|
||||
struct timeval tv;
|
||||
int error;
|
||||
int hz;
|
||||
|
||||
hz = 0;
|
||||
error = 0;
|
||||
if (uap->timeout != NULL) {
|
||||
error = copyin((const void *)uap->timeout, (void *)&ts,
|
||||
sizeof(struct timespec));
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (ts.tv_nsec < 0 || ts.tv_nsec > 1000000000)
|
||||
return (EINVAL);
|
||||
if (ts.tv_sec == 0 && ts.tv_nsec == 0)
|
||||
return (ETIMEDOUT);
|
||||
TIMESPEC_TO_TIMEVAL(&tv, &ts);
|
||||
hz = tvtohz(&tv);
|
||||
}
|
||||
PROC_LOCK(td->td_proc);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
if ((td->td_flags & TDF_THRWAKEUP) == 0) {
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
error = msleep((void *)td, &td->td_proc->p_mtx,
|
||||
td->td_priority | PCATCH, "lthr", hz);
|
||||
mtx_lock_spin(&sched_lock);
|
||||
}
|
||||
td->td_flags &= ~TDF_THRWAKEUP;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
PROC_UNLOCK(td->td_proc);
|
||||
return (error == EWOULDBLOCK ? ETIMEDOUT : error);
|
||||
}
|
||||
|
||||
int
|
||||
thr_wake(struct thread *td, struct thr_wake_args *uap)
|
||||
/* thr_id_t id */
|
||||
{
|
||||
struct thread *tdsleeper, *ttd;
|
||||
|
||||
tdsleeper = ((struct thread *)uap->id);
|
||||
PROC_LOCK(tdsleeper->td_proc);
|
||||
FOREACH_THREAD_IN_PROC(tdsleeper->td_proc, ttd) {
|
||||
if (ttd == tdsleeper)
|
||||
break;
|
||||
}
|
||||
if (ttd == NULL) {
|
||||
PROC_UNLOCK(tdsleeper->td_proc);
|
||||
return (ESRCH);
|
||||
}
|
||||
mtx_lock_spin(&sched_lock);
|
||||
tdsleeper->td_flags |= TDF_THRWAKEUP;
|
||||
mtx_unlock_spin(&sched_lock);
|
||||
wakeup_one((void *)tdsleeper);
|
||||
PROC_UNLOCK(tdsleeper->td_proc);
|
||||
return (0);
|
||||
}
|
||||
|
@ -629,5 +629,7 @@
|
||||
440 MSTD { int kse_switchin(const struct __mcontext *mcp, \
|
||||
long val, long *loc); }
|
||||
441 MNOSTD { int ksem_timedwait(semid_t id, struct timespec *abstime); }
|
||||
442 MSTD { int thr_suspend(const struct timespec *timeout); }
|
||||
443 MSTD { int thr_wake(thr_id_t id); }
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/compat/freebsd32/syscalls.master
|
||||
|
@ -356,6 +356,7 @@ struct thread {
|
||||
#define TDF_NEEDSIGCHK 0x020000 /* Thread may need signal delivery. */
|
||||
#define TDF_SA 0x040000 /* A scheduler activation based thread. */
|
||||
#define TDF_UMTXWAKEUP 0x080000 /* Libthr thread must not sleep on a umtx. */
|
||||
#define TDF_THRWAKEUP 0x100000 /* Libthr thread must not suspend itself. */
|
||||
#define TDF_DEADLKTREAT 0x800000 /* Lock aquisition - deadlock treatment. */
|
||||
|
||||
/* "private" flags kept in td_pflags */
|
||||
|
@ -46,6 +46,8 @@ int thr_create(ucontext_t *ctx, thr_id_t *id, int flags);
|
||||
int thr_self(thr_id_t *id);
|
||||
void thr_exit(void);
|
||||
int thr_kill(thr_id_t id, int sig);
|
||||
int thr_suspend(const struct timespec *timeout);
|
||||
int thr_wake(thr_id_t id);
|
||||
|
||||
#endif /* !_KERNEL */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user