Changeset View
Changeset View
Standalone View
Standalone View
sys/kern/kern_umtx.c
Show First 20 Lines • Show All 615 Lines • ▼ Show 20 Lines | |||||
umtxq_signal_thread(struct umtx_q *uq) | umtxq_signal_thread(struct umtx_q *uq) | ||||
{ | { | ||||
UMTXQ_LOCKED_ASSERT(umtxq_getchain(&uq->uq_key)); | UMTXQ_LOCKED_ASSERT(umtxq_getchain(&uq->uq_key)); | ||||
umtxq_remove(uq); | umtxq_remove(uq); | ||||
wakeup(uq); | wakeup(uq); | ||||
} | } | ||||
/* | |||||
* Wake up a maximum of n_wake threads that are waiting on an userland | |||||
* object identified by key. The remaining threads are removed from queue | |||||
* identified by key and added to the queue identified by key2 (requeued). | |||||
* The n_requeue specifies an upper limit on the number of threads that | |||||
* are requeued to the second queue. | |||||
*/ | |||||
int | |||||
umtxq_requeue(struct umtx_key *key, int n_wake, struct umtx_key *key2, | |||||
int n_requeue) | |||||
{ | |||||
struct umtxq_queue *uh, *uh2; | |||||
struct umtx_q *uq, *uq_temp; | |||||
int ret; | |||||
ret = 0; | |||||
UMTXQ_LOCKED_ASSERT(umtxq_getchain(key)); | |||||
UMTXQ_LOCKED_ASSERT(umtxq_getchain(key2)); | |||||
uh = umtxq_queue_lookup(key, UMTX_SHARED_QUEUE); | |||||
uh2 = umtxq_queue_lookup(key2, UMTX_SHARED_QUEUE); | |||||
if (uh == NULL) | |||||
return (0); | |||||
TAILQ_FOREACH_SAFE(uq, &uh->head, uq_link, uq_temp) { | |||||
if (++ret <= n_wake) { | |||||
umtxq_remove(uq); | |||||
wakeup_one(uq); | |||||
} else { | |||||
umtxq_remove(uq); | |||||
uq->uq_key = *key2; | |||||
markj: umtxq_sleep() cannot tolerate the queue hash changing like this. It will wake up with the wrong… | |||||
umtxq_insert(uq); | |||||
if (ret - n_wake == n_requeue) | |||||
break; | |||||
} | |||||
} | |||||
return (ret); | |||||
} | |||||
static inline int | static inline int | ||||
tstohz(const struct timespec *tsp) | tstohz(const struct timespec *tsp) | ||||
{ | { | ||||
struct timeval tv; | struct timeval tv; | ||||
TIMESPEC_TO_TIMEVAL(&tv, tsp); | TIMESPEC_TO_TIMEVAL(&tv, tsp); | ||||
return tvtohz(&tv); | return tvtohz(&tv); | ||||
} | } | ||||
▲ Show 20 Lines • Show All 4,392 Lines • Show Last 20 Lines |
umtxq_sleep() cannot tolerate the queue hash changing like this. It will wake up with the wrong hash chain lock held.