mutex as allocation

This commit is contained in:
Mylloon 2024-04-21 14:42:36 +02:00
parent f5e7a51861
commit 4481d3d25d
Signed by: Anri
GPG key ID: A82D63DFF8D1317F

View file

@ -17,7 +17,7 @@ struct scheduler {
int qlen;
/* Mutex qui protège la structure */
pthread_mutex_t mutex;
pthread_mutex_t *mutex;
/* Nombre de threads instanciés */
int nthreads;
@ -39,7 +39,7 @@ static struct scheduler sched;
void *sched_worker(void *);
/* Nettoie les opérations effectuées par l'initialisation de l'ordonnanceur */
int cleanup_init(int);
int sched_init_cleanup(int);
int
sched_init(int nthreads, int qlen, taskfunc f, void *closure)
@ -63,27 +63,35 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
sched.nthsleep = 0;
if(pthread_mutex_init(&sched.mutex, NULL) != 0) {
fprintf(stderr, "Can't init mutex\n");
return -1;
// Initialisation des mutex de chaque processus
if(!(sched.mutex = malloc(sched.nthreads * sizeof(pthread_mutex_t)))) {
perror("Mutexes");
return sched_init_cleanup(-1);
}
for(int i = 0; i < sched.nthreads; ++i) {
if(pthread_mutex_init(&sched.mutex[i], NULL) != 0) {
fprintf(stderr, "Can't init mutex for thread %d\n", i);
return sched_init_cleanup(-1);
}
}
// Initialisation des variables de conditions de chaque processus
if(!(sched.cond = malloc(sched.nthreads * sizeof(pthread_cond_t)))) {
perror("Variable conditions");
return cleanup_init(-1);
return sched_init_cleanup(-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);
return sched_init_cleanup(-1);
}
}
sched.top = -1;
if((sched.tasks = malloc(qlen * sizeof(struct task_info))) == NULL) {
perror("Stack");
return cleanup_init(-1);
return sched_init_cleanup(-1);
}
pthread_t threads[nthreads];
@ -102,34 +110,43 @@ sched_init(int nthreads, int qlen, taskfunc f, void *closure)
fprintf(stderr, "\n");
}
return cleanup_init(-1);
return sched_init_cleanup(-1);
}
}
if(sched_spawn(f, closure, &sched) < 0) {
fprintf(stderr, "Can't create the initial task\n");
return cleanup_init(-1);
return sched_init_cleanup(-1);
}
for(int i = 0; i < nthreads; ++i) {
if((pthread_join(threads[i], NULL) != 0)) {
fprintf(stderr, "Can't wait the thread %d\n", i);
return cleanup_init(-1);
return sched_init_cleanup(-1);
}
}
return cleanup_init(1);
return sched_init_cleanup(1);
}
int
cleanup_init(int ret_code)
sched_init_cleanup(int ret_code)
{
if(!sched.cond) {
if(sched.mutex) {
for(int i = 0; i < sched.nthreads; ++i) {
pthread_mutex_destroy(&sched.mutex[i]);
}
free(sched.mutex);
sched.mutex = NULL;
}
if(sched.cond) {
free(sched.cond);
sched.cond = NULL;
}
if(!sched.tasks) {
if(sched.tasks) {
free(sched.tasks);
sched.tasks = NULL;
@ -141,10 +158,10 @@ cleanup_init(int ret_code)
int
sched_spawn(taskfunc f, void *closure, struct scheduler *s)
{
pthread_mutex_lock(&s->mutex);
pthread_mutex_lock(&s->mutex[0]);
if(s->top + 1 >= s->qlen) {
pthread_mutex_unlock(&s->mutex);
pthread_mutex_unlock(&s->mutex[0]);
errno = EAGAIN;
fprintf(stderr, "Stack is full\n");
return -1;
@ -153,7 +170,7 @@ sched_spawn(taskfunc f, void *closure, struct scheduler *s)
s->tasks[++s->top] = (struct task_info){closure, f};
pthread_cond_signal(&s->cond[0]);
pthread_mutex_unlock(&s->mutex);
pthread_mutex_unlock(&s->mutex[0]);
return 0;
}
@ -164,7 +181,7 @@ sched_worker(void *arg)
struct scheduler *s = (struct scheduler *)arg;
while(1) {
pthread_mutex_lock(&s->mutex);
pthread_mutex_lock(&s->mutex[0]);
// S'il on a rien à faire
if(s->top == -1) {
@ -173,14 +190,14 @@ sched_worker(void *arg)
// Signal a tout les threads que il n'y a plus rien à faire
// si un thread attend une tâche
pthread_cond_broadcast(&s->cond[0]);
pthread_mutex_unlock(&s->mutex);
pthread_mutex_unlock(&s->mutex[0]);
break;
}
pthread_cond_wait(&s->cond[0], &s->mutex);
pthread_cond_wait(&s->cond[0], &s->mutex[0]);
s->nthsleep--;
pthread_mutex_unlock(&s->mutex);
pthread_mutex_unlock(&s->mutex[0]);
continue;
}
@ -188,7 +205,7 @@ sched_worker(void *arg)
taskfunc f = s->tasks[s->top].f;
void *closure = s->tasks[s->top].closure;
s->top--;
pthread_mutex_unlock(&s->mutex);
pthread_mutex_unlock(&s->mutex[0]);
// Exécute la tâche
f(closure, s);