mirror of
https://git.FreeBSD.org/src.git
synced 2025-01-11 14:10:34 +00:00
Eliminate a race condition in timed waits (cv, mutex, and sleeps).
MFC Candidate. PR: 93592
This commit is contained in:
parent
4b8e98d632
commit
aa8eff60a3
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=155962
@ -421,11 +421,6 @@ _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
/* Return invalid argument error: */
|
||||
rval = EINVAL;
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
curthread->wakeup_time.tv_sec = abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
|
||||
/* Reset the timeout and interrupted flags: */
|
||||
curthread->timeout = 0;
|
||||
curthread->interrupted = 0;
|
||||
@ -464,6 +459,11 @@ _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
* set the state.
|
||||
*/
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
THR_SET_STATE(curthread, PS_COND_WAIT);
|
||||
|
||||
/* Remember the CV: */
|
||||
|
@ -551,14 +551,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -572,6 +564,14 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
* be able to safely set the state.
|
||||
*/
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
@ -633,14 +633,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -659,6 +651,13 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
mutex_priority_adjust(curthread, *m);
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
@ -730,14 +729,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -756,6 +747,13 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
*/
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
|
@ -46,6 +46,7 @@ _nanosleep(const struct timespec *time_to_sleep,
|
||||
int ret = 0;
|
||||
struct timespec ts, ts1;
|
||||
struct timespec remaining_time;
|
||||
struct timespec wakeup_time;
|
||||
|
||||
/* Check if the time to sleep is legal: */
|
||||
if ((time_to_sleep == NULL) || (time_to_sleep->tv_sec < 0) ||
|
||||
@ -61,10 +62,11 @@ _nanosleep(const struct timespec *time_to_sleep,
|
||||
KSE_GET_TOD(curthread->kse, &ts);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
TIMESPEC_ADD(&curthread->wakeup_time, &ts, time_to_sleep);
|
||||
TIMESPEC_ADD(&wakeup_time, &ts, time_to_sleep);
|
||||
|
||||
THR_LOCK_SWITCH(curthread);
|
||||
curthread->interrupted = 0;
|
||||
curthread->wakeup_time = wakeup_time;
|
||||
THR_SET_STATE(curthread, PS_SLEEP_WAIT);
|
||||
|
||||
/* Reschedule the current thread to sleep: */
|
||||
|
@ -421,11 +421,6 @@ _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
/* Return invalid argument error: */
|
||||
rval = EINVAL;
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
curthread->wakeup_time.tv_sec = abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
|
||||
/* Reset the timeout and interrupted flags: */
|
||||
curthread->timeout = 0;
|
||||
curthread->interrupted = 0;
|
||||
@ -464,6 +459,11 @@ _pthread_cond_timedwait(pthread_cond_t * cond, pthread_mutex_t * mutex,
|
||||
* set the state.
|
||||
*/
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
THR_SET_STATE(curthread, PS_COND_WAIT);
|
||||
|
||||
/* Remember the CV: */
|
||||
|
@ -551,14 +551,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -572,6 +564,14 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
* be able to safely set the state.
|
||||
*/
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
@ -633,14 +633,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -659,6 +651,13 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
mutex_priority_adjust(curthread, *m);
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
@ -730,14 +729,6 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
/* Unlock the mutex structure: */
|
||||
THR_LOCK_RELEASE(curthread, &(*m)->m_lock);
|
||||
} else {
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
|
||||
/*
|
||||
* Join the queue of threads waiting to lock
|
||||
* the mutex and save a pointer to the mutex.
|
||||
@ -756,6 +747,13 @@ mutex_lock_common(struct pthread *curthread, pthread_mutex_t *m,
|
||||
*/
|
||||
|
||||
THR_SCHED_LOCK(curthread, curthread);
|
||||
/* Set the wakeup time: */
|
||||
if (abstime) {
|
||||
curthread->wakeup_time.tv_sec =
|
||||
abstime->tv_sec;
|
||||
curthread->wakeup_time.tv_nsec =
|
||||
abstime->tv_nsec;
|
||||
}
|
||||
THR_SET_STATE(curthread, PS_MUTEX_WAIT);
|
||||
THR_SCHED_UNLOCK(curthread, curthread);
|
||||
|
||||
|
@ -46,6 +46,7 @@ _nanosleep(const struct timespec *time_to_sleep,
|
||||
int ret = 0;
|
||||
struct timespec ts, ts1;
|
||||
struct timespec remaining_time;
|
||||
struct timespec wakeup_time;
|
||||
|
||||
/* Check if the time to sleep is legal: */
|
||||
if ((time_to_sleep == NULL) || (time_to_sleep->tv_sec < 0) ||
|
||||
@ -61,10 +62,11 @@ _nanosleep(const struct timespec *time_to_sleep,
|
||||
KSE_GET_TOD(curthread->kse, &ts);
|
||||
|
||||
/* Calculate the time for the current thread to wake up: */
|
||||
TIMESPEC_ADD(&curthread->wakeup_time, &ts, time_to_sleep);
|
||||
TIMESPEC_ADD(&wakeup_time, &ts, time_to_sleep);
|
||||
|
||||
THR_LOCK_SWITCH(curthread);
|
||||
curthread->interrupted = 0;
|
||||
curthread->wakeup_time = wakeup_time;
|
||||
THR_SET_STATE(curthread, PS_SLEEP_WAIT);
|
||||
|
||||
/* Reschedule the current thread to sleep: */
|
||||
|
Loading…
Reference in New Issue
Block a user