allocate multiple condition variable but currently only use one, also cleanup helper function to keep track of allocations
This commit is contained in:
parent
8f42b8ba7b
commit
1ab599d606
1 changed files with 42 additions and 15 deletions
57
src/sched.c
57
src/sched.c
|
@ -11,7 +11,7 @@ struct task_info {
|
||||||
|
|
||||||
struct scheduler {
|
struct scheduler {
|
||||||
/* Indicateur de changement d'état */
|
/* Indicateur de changement d'état */
|
||||||
pthread_cond_t cond;
|
pthread_cond_t *cond;
|
||||||
|
|
||||||
/* Taille de la pile */
|
/* Taille de la pile */
|
||||||
int qlen;
|
int qlen;
|
||||||
|
@ -38,9 +38,15 @@ static struct scheduler sched;
|
||||||
/* Lance une tâche de la pile */
|
/* Lance une tâche de la pile */
|
||||||
void *sched_worker(void *);
|
void *sched_worker(void *);
|
||||||
|
|
||||||
|
/* Nettoie les opérations effectuées par l'initialisation de l'ordonnanceur */
|
||||||
|
int cleanup_init(int);
|
||||||
|
|
||||||
int
|
int
|
||||||
sched_init(int nthreads, int qlen, taskfunc f, void *closure)
|
sched_init(int nthreads, int qlen, taskfunc f, void *closure)
|
||||||
{
|
{
|
||||||
|
sched.cond = NULL;
|
||||||
|
sched.tasks = NULL;
|
||||||
|
|
||||||
if(qlen <= 0) {
|
if(qlen <= 0) {
|
||||||
fprintf(stderr, "qlen must be greater than 0\n");
|
fprintf(stderr, "qlen must be greater than 0\n");
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -60,15 +66,22 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(pthread_cond_init(&sched.cond, NULL) != 0) {
|
// Initialisation des variables de conditions de chaque processus
|
||||||
fprintf(stderr, "Can't init condition variable\n");
|
if(!(sched.cond = malloc(sched.nthreads * sizeof(pthread_cond_t)))) {
|
||||||
return -1;
|
perror("Variable conditions");
|
||||||
|
return cleanup_init(-1);
|
||||||
|
}
|
||||||
|
for(int i = 0; i < sched.nthreads; ++i) {
|
||||||
|
if(pthread_cond_init(&sched.cond[i], NULL) != 0) {
|
||||||
|
fprintf(stderr, "Can't init condition variable for thread %d\n", i);
|
||||||
|
return cleanup_init(-1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sched.top = -1;
|
sched.top = -1;
|
||||||
if((sched.tasks = malloc(qlen * sizeof(struct task_info))) == NULL) {
|
if((sched.tasks = malloc(qlen * sizeof(struct task_info))) == NULL) {
|
||||||
fprintf(stderr, "Can't allocate memory for stack\n");
|
perror("Stack");
|
||||||
return -1;
|
return cleanup_init(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_t threads[nthreads];
|
pthread_t threads[nthreads];
|
||||||
|
@ -87,26 +100,40 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sched.tasks);
|
return cleanup_init(-1);
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(sched_spawn(f, closure, &sched) < 0) {
|
if(sched_spawn(f, closure, &sched) < 0) {
|
||||||
fprintf(stderr, "Can't create the initial task\n");
|
fprintf(stderr, "Can't create the initial task\n");
|
||||||
return -1;
|
return cleanup_init(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(int i = 0; i < nthreads; ++i) {
|
for(int i = 0; i < nthreads; ++i) {
|
||||||
if((pthread_join(threads[i], NULL) != 0)) {
|
if((pthread_join(threads[i], NULL) != 0)) {
|
||||||
fprintf(stderr, "Can't wait the thread %d\n", i);
|
fprintf(stderr, "Can't wait the thread %d\n", i);
|
||||||
return -1;
|
return cleanup_init(-1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
free(sched.tasks);
|
return cleanup_init(1);
|
||||||
|
}
|
||||||
|
|
||||||
return 1;
|
int
|
||||||
|
cleanup_init(int ret_code)
|
||||||
|
{
|
||||||
|
if(!sched.cond) {
|
||||||
|
free(sched.cond);
|
||||||
|
sched.cond = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!sched.tasks) {
|
||||||
|
|
||||||
|
free(sched.tasks);
|
||||||
|
sched.tasks = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_code;
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -123,7 +150,7 @@ sched_spawn(taskfunc f, void *closure, struct scheduler *s)
|
||||||
|
|
||||||
s->tasks[++s->top] = (struct task_info){closure, f};
|
s->tasks[++s->top] = (struct task_info){closure, f};
|
||||||
|
|
||||||
pthread_cond_signal(&s->cond);
|
pthread_cond_signal(&s->cond[0]);
|
||||||
pthread_mutex_unlock(&s->mutex);
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -143,13 +170,13 @@ sched_worker(void *arg)
|
||||||
if(s->nthsleep == s->nthreads) {
|
if(s->nthsleep == s->nthreads) {
|
||||||
// Signal a tout les threads que il n'y a plus rien à faire
|
// Signal a tout les threads que il n'y a plus rien à faire
|
||||||
// si un thread attend une tâche
|
// si un thread attend une tâche
|
||||||
pthread_cond_broadcast(&s->cond);
|
pthread_cond_broadcast(&s->cond[0]);
|
||||||
pthread_mutex_unlock(&s->mutex);
|
pthread_mutex_unlock(&s->mutex);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_cond_wait(&s->cond, &s->mutex);
|
pthread_cond_wait(&s->cond[0], &s->mutex);
|
||||||
s->nthsleep--;
|
s->nthsleep--;
|
||||||
pthread_mutex_unlock(&s->mutex);
|
pthread_mutex_unlock(&s->mutex);
|
||||||
continue;
|
continue;
|
||||||
|
|
Reference in a new issue