VanDamme M1x VanM1x
VanDamme M1x VanM1x

Reputation: 1

My function sched_init don't do what i want

I need to make a LIFO scheduler in C using pthread.

The LIFO scheduler contains a single stack of tasks whose maximum size is given by the

parameter passed to sched_init. Initially, the stack contains only the initial task. When a

thread has nothing to do, it unstacks a task from the stack and performs it; if there are no tasks ready

the thread goes to sleep waiting for one (for example, the sched_spawn function can

try to wake up a thread). When a new task is created, it is stacked on the stack.

The scheduler terminates when the stack is empty and all threads are asleep.

You'll notice that the stack is a shared structure, so you'll need to protect it with synchronization pri- mitives.

mitives. You'll also need to use synchronization primitives to wake up any

and terminate them when the scheduler become idle.

That's my file.h:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>

struct scheduler;

typedef void (*taskfunc)(void*, struct scheduler *);

// Structure pour une tâche
typedef struct {
    taskfunc task;
    void *closure;
} Task;

typedef struct scheduler
{
  Task *tasks;
  int qlen;
  int nthreads;
  int size;
  pthread_t *threads;
  pthread_mutex_t mutex; // Mutex pour la synchronisation
  pthread_cond_t condition; // Condition pour attendre les tâches
} scheduler;

static inline int
sched_default_threads()
{
    return sysconf(_SC_NPROCESSORS_ONLN);
}

int sched_init(int nthreads, int qlen, taskfunc f, void *closure);
int sched_spawn(taskfunc f, void *closure, struct scheduler *s);

#include "sched.h"

/*************************************************/
/*                                               */
/*                sucre syntaxique               */
/*                                               */
/*************************************************/

#define AND &&
#define OR ||
#define ISNOT !=
#define NOT !
#define then

typedef enum { FALSE, TRUE} bool;

/*************************************************/
/*                                               */
/*                predeclarations                */
/*                                               */
/*************************************************/

/* initialise un struct scheduler vide */
void initVide(struct scheduler *L);

/* renvoie 1 si le struct scheduler en parametre est vide, 0 sinon */
bool estVide(struct scheduler *L);

/* renvoie le premier element du struct scheduler en parametre */
taskfunc premier(struct scheduler *L);

/* renvoie un nouveau struct scheduler correspondant a celui en parametre, avec l'element task ajoute en haut de la pile */
struct scheduler ajoute(taskfunc task, void *closure, struct scheduler *L);

/* modifie le struct scheduler en parametre: task est ajoute comme premier element */
void empile(taskfunc task, void *closure, struct scheduler* L);

/* modifie le struct scheduler en parametre: le premier element est retire */
void depile(struct scheduler* L);

/* affichage simple du struct scheduler */
void affiche(struct scheduler *L);
/* longueur en recursif et en iteratif */
int longueur (struct scheduler *L);

/*************************************************/
/*                                               */
/*                briques de base                */
/*                                               */
/*************************************************/

void initVide(struct scheduler *L) {
    L->tasks = NULL;
    L->qlen = 0;
    L->nthreads = 0;
    L->size = 0;
    L->threads = NULL;
    pthread_mutex_init(&(L->mutex), NULL);
    pthread_cond_init(&(L->condition), NULL);
}

bool estVide(struct scheduler *L) {
    return L->size == 0;
}

taskfunc premier(struct scheduler *L) {
    if (estVide(L)) {
        fprintf(stderr, "Erreur : le struct scheduler est vide.\n");
        exit(EXIT_FAILURE);
    }
    return L->tasks[0].task;
}

struct scheduler ajoute(taskfunc task, void *closure, struct scheduler *L) {
    Task newTask = {task, closure};
    if (L->size >= L->qlen) {
        fprintf(stderr, "Erreur : le scheduler est plein.\n");
        exit(EXIT_FAILURE);
    }
    L->tasks[L->size++] = newTask;
    return *L;
}

void empile(taskfunc task, void *closure, struct scheduler *L)
{
  ajoute(task, closure, L) ;
}

void depile(struct scheduler *L) {
    if (estVide(L)) {
        fprintf(stderr, "Erreur : le struct scheduler est vide.\n");
        exit(EXIT_FAILURE);
    }
    free(L->tasks[L->size - 1].closure); // Libère la mémoire de la tâche retirée
    L->size--; // Réduit la taille du struct scheduler
}

/*************************************************/
/*                                               */
/*     Affiche, avec les briques de base         */
/*                                               */
/*************************************************/

void affiche(struct scheduler *L) {
    for (int i = 0; i < L->size; i++) {
        printf("%p ", L->tasks[i].task);
    }
    printf("\n");
}

/*************************************************/
/*                                               */
/*     Longueur, sans les briques de base        */
/*                                               */
/*************************************************/

int longueur (struct scheduler *L)
{
    return L -> size;
}

/*************************************************/
/*                                               */
/*       Libere la memoire                       */
/*                                               */
/*************************************************/

void VideScheduler(struct scheduler *L)
{
  if(NOT(estVide(L)))
  {
    depile(L);
    VideScheduler(L);
  }

}

// Fonction de tâche simple qui affiche un message
void *task_function(void *arg) {
    char *message = (char *)arg;
    printf("Thread %lu executing task: %s\n", pthread_self(), message);
    sleep(1); // Simulation d'une tâche longue
    return NULL;
}

int sched_init(int nthreads, int qlen, taskfunc f, void *closure) {
    // Faut initialiser notre ordonnanceur et créez les threads si nécessaire
    // Il faut également initialiser la pile de tâches avec la tâche initiale
    struct scheduler *scheduler = (struct scheduler *)malloc(sizeof(struct scheduler));
    if (scheduler == NULL) {
        perror("Erreur lors de l'allocation du struct scheduler");
        return -1;
    }
    scheduler->nthreads = (nthreads == 0) ? sched_default_threads() : nthreads;
    scheduler->qlen = qlen;
    scheduler->tasks = (Task *)malloc(qlen * sizeof(Task));
    if (scheduler->tasks == NULL) {
        perror("Erreur lors de l'allocation de la mémoire pour les tâches");
        free(scheduler);
        return -1;
    }

    // Ajout de la tâche initiale au tableau de tâches
    scheduler->tasks[0].task = f;
    scheduler->tasks[0].closure = closure;
    scheduler->size++;

    // Vérification si la taille du tableau est suffisante pour le nombre de threads à créer
    if (scheduler->nthreads > qlen) {
        printf("Ajustement du nombre de threads au maximum de la capacité du tableau de tâches.\n");
        scheduler->nthreads = qlen;
    }
    // Création des threads
    scheduler->threads = (pthread_t *)malloc(scheduler->nthreads * sizeof(pthread_t));
    if (scheduler->threads == NULL) {
        perror("Erreur lors de l'allocation de la mémoire pour les threads");
        free(scheduler->tasks);
        free(scheduler);
        return -1;
    }
    for (int i = 0; i < scheduler->nthreads; i++) {
        pthread_create(&(scheduler->threads[i]), NULL,(void *(*)(void *))f, closure);
    }

    // Ajout de la tâche initiale
    empile(f, closure, scheduler);

    // Attente de la fin des threads
    for (int i = 1; i < scheduler->nthreads; i++) {
        pthread_join(scheduler->threads[i], NULL);
    }
    return 0;

}

int sched_spawn(taskfunc f, void *closure, struct scheduler *s) {
    return -1;
}

int main(){
    char *message = "Task1";
    // Initialisation du scheduler avec 2 threads et une longueur de file de 5
    int result = sched_init(0, 4, task_function, (void*) message); // Initialisation du scheduler
    if (result != 0) {
        fprintf(stderr, "Erreur lors de l'initialisation du scheduler\n");
        return EXIT_FAILURE;
    }
    return EXIT_SUCCESS;
}

I've tried to do this as a first test but I think I'm off-topic. Could you please tell me if I'm in agreement with what I've explained in the statement? I'd like to point out that I have an appendix file that implements the quicksort and serves as an example where I need to use my LIFO scheduler to execute the quicksort and see how long it took to do the quicksort.

Upvotes: 0

Views: 41

Answers (0)

Related Questions