Commit 137cd5fc authored by Peter W. Draper's avatar Peter W. Draper
Browse files

Merge branch 'rewait_fixes' into 'master'

Rewait fixes

Fixes the deadlock described in #125.

See merge request !122
parents c4d1b553 51dec77e
...@@ -136,9 +136,6 @@ struct task *queue_gettask(struct queue *q, const struct task *prev, ...@@ -136,9 +136,6 @@ struct task *queue_gettask(struct queue *q, const struct task *prev,
lock_type *qlock = &q->lock; lock_type *qlock = &q->lock;
struct task *res = NULL; struct task *res = NULL;
/* If there are no tasks, leave immediately. */
if (q->count == 0) return NULL;
/* Grab the task lock. */ /* Grab the task lock. */
if (blocking) { if (blocking) {
if (lock_lock(qlock) != 0) error("Locking the qlock failed.\n"); if (lock_lock(qlock) != 0) error("Locking the qlock failed.\n");
...@@ -146,6 +143,12 @@ struct task *queue_gettask(struct queue *q, const struct task *prev, ...@@ -146,6 +143,12 @@ struct task *queue_gettask(struct queue *q, const struct task *prev,
if (lock_trylock(qlock) != 0) return NULL; if (lock_trylock(qlock) != 0) return NULL;
} }
/* If there are no tasks, leave immediately. */
if (q->count == 0) {
lock_unlock_blind(qlock);
return NULL;
}
/* Set some pointers we will use often. */ /* Set some pointers we will use often. */
int *qtid = q->tid; int *qtid = q->tid;
struct task *qtasks = q->tasks; struct task *qtasks = q->tasks;
......
...@@ -983,8 +983,7 @@ void scheduler_start(struct scheduler *s, unsigned int mask, ...@@ -983,8 +983,7 @@ void scheduler_start(struct scheduler *s, unsigned int mask,
const int waiting_old = s->waiting; const int waiting_old = s->waiting;
/* We are going to use the task structure in a modified way to pass /* We are going to use the task structure in a modified way to pass
information information to the task. Don't do this at home !
to the task. Don't do this at home !
- ci and cj will give the range of tasks to which the waits will be applied - ci and cj will give the range of tasks to which the waits will be applied
- the flags will be used to transfer the mask - the flags will be used to transfer the mask
- the rank will be used to transfer the submask - the rank will be used to transfer the submask
...@@ -1009,6 +1008,7 @@ void scheduler_start(struct scheduler *s, unsigned int mask, ...@@ -1009,6 +1008,7 @@ void scheduler_start(struct scheduler *s, unsigned int mask,
/* Wait for the rewait tasks to have executed. */ /* Wait for the rewait tasks to have executed. */
pthread_mutex_lock(&s->sleep_mutex); pthread_mutex_lock(&s->sleep_mutex);
pthread_cond_broadcast(&s->sleep_cond);
while (s->waiting > waiting_old) { while (s->waiting > waiting_old) {
pthread_cond_wait(&s->sleep_cond, &s->sleep_mutex); pthread_cond_wait(&s->sleep_cond, &s->sleep_mutex);
} }
...@@ -1030,6 +1030,11 @@ void scheduler_start(struct scheduler *s, unsigned int mask, ...@@ -1030,6 +1030,11 @@ void scheduler_start(struct scheduler *s, unsigned int mask,
} }
} }
/* To be safe, fire of one last sleep_cond in a safe way. */
pthread_mutex_lock(&s->sleep_mutex);
pthread_cond_broadcast(&s->sleep_cond);
pthread_mutex_unlock(&s->sleep_mutex);
// message( "enqueueing tasks took %.3f %s." , // message( "enqueueing tasks took %.3f %s." ,
// clocks_from_ticks( getticks() - tic ), clocks_getunit()); // clocks_from_ticks( getticks() - tic ), clocks_getunit());
} }
...@@ -1125,7 +1130,7 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) { ...@@ -1125,7 +1130,7 @@ void scheduler_enqueue(struct scheduler *s, struct task *t) {
if (qid >= s->nr_queues) error("Bad computed qid."); if (qid >= s->nr_queues) error("Bad computed qid.");
/* If no previous owner, find the shortest queue. */ /* If no previous owner, pick a random queue. */
if (qid < 0) qid = rand() % s->nr_queues; if (qid < 0) qid = rand() % s->nr_queues;
/* Increase the waiting counter. */ /* Increase the waiting counter. */
...@@ -1279,7 +1284,10 @@ struct task *scheduler_gettask(struct scheduler *s, int qid, ...@@ -1279,7 +1284,10 @@ struct task *scheduler_gettask(struct scheduler *s, int qid,
if (res == NULL) { if (res == NULL) {
#endif #endif
pthread_mutex_lock(&s->sleep_mutex); pthread_mutex_lock(&s->sleep_mutex);
if (s->waiting > 0) pthread_cond_wait(&s->sleep_cond, &s->sleep_mutex); res = queue_gettask(&s->queues[qid], prev, 1);
if (res == NULL && s->waiting > 0) {
pthread_cond_wait(&s->sleep_cond, &s->sleep_mutex);
}
pthread_mutex_unlock(&s->sleep_mutex); pthread_mutex_unlock(&s->sleep_mutex);
} }
} }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment