#include "sema.h" semStruc semBuf[MAX_SEM]; /*---------------------------------------------------------------- * getSemValue retourne la valeur d'un sémaphore. * * argument : sem est le numéro identifiant le sémaphore. * * valeur de retour : la valeur du sémaphore. * * note : cette fonction peut être appelée dans une fonction de * traitement d'interruption. Elle est principalement utilisée de * manière interne par le kernel. Les tâches NE devraient PAS * appeler directement cette fonction. * type : facultative. *---------------------------------------------------------------- */ unsigned char getSemValue(unsigned char sem) { return semBuf[sem].value; } /*---------------------------------------------------------------- * setSemValue modifie la valeur d'un sémaphore. * * arguments : sem est le numéro du sémaphore * val est la nouvelle valeur à attribuer au sémaphore * * valeur de retour : aucune. * * note : cette fonction peut être appelée dans une fonction de * traitement d'interruption. Elle est principalement utilisée de * manière interne par le kernel. Les tâches NE devraient PAS * appeler directement cette fonction. * type : facultative. *---------------------------------------------------------------- */ void setSemValue(unsigned char sem, unsigned char val) { semBuf[sem].value = val; } /*---------------------------------------------------------------- * higherWaitingTask donne le numéro de la tâche la plus * prioritaire qui est en attente sur un sémaphore. * * argument : sem est le numéro du sémaphore. * * valeur de retour : le numéro de la tâche de priorité la plus * élevée qui attend sur le sémaphore. * * note : cette fonction est utilisée de manière interne par le * kernel. Les tâches et les fonctions de traitement * d'interruption NE PEUVENT EN AUCUN CAS appeler directement * cette fonction. * type : facultative. *---------------------------------------------------------------- */ unsigned char higherWaitingTask(unsigned char sem) { return higherTask(semBuf[sem].waitingTasks); } /*---------------------------------------------------------------- * addWaitingTask ajoute une tâche à l'ensemble de celles qui * attendent sur un sémaphore. * * arguments : sem est le numéro du sémaphore. * task est le numéro de la tâche à ajouter. * * valeur de retour : aucune. * * note : cette fonction est utilisée de manière interne par le * kernel. Les tâches et les fonctions de traitement * d'interruption NE PEUVENT EN AUCUN CAS appeler directement * cette fonction. * type : facultative. *---------------------------------------------------------------- */ void addWaitingTask(unsigned char sem, unsigned char task) { setTaskBit(&(semBuf[sem].waitingTasks), task); } /*---------------------------------------------------------------- * remWaitingTask enlève une tâche de l'ensemble de celles qui * attendent sur un sémaphore. * * arguments : sem est le numéro du sémaphore. * task est le numéro de la tâche à retirer. * * valeur de retour : aucune. * * note : cette fonction est utilisée de manière interne par le * kernel. Les tâches et les fonctions de traitement * d'interruption NE PEUVENT EN AUCUN CAS appeler directement * cette fonction. * type : facultative. *---------------------------------------------------------------- */ void remWaitingTask(unsigned char sem, unsigned char task) { clearTaskBit(&(semBuf[sem].waitingTasks), task); } /*---------------------------------------------------------------- * waitSem réalise l'opération classique d'attente d'une tâche sur * un sémaphore. Si la valeur du sémaphore est nulle, la tâche * appelante est mise en attente sur ce sémaphore. Elle est * ajoutée à l'ensemble des tâches qui sont déjà en attente sur ce * sémaphore et stoppée. Si la valeur du sémaphore n'est pas * nulle, celle-ci est décrémentée et la tâche peut poursuivre * son exécution. * * arguments : task est le numéro de la tâche. * sem est le numéro du sémaphore. * * valeur de retour : aucune. * * note : cette fonction est utilisée de manière interne par le * kernel. Les tâches et les fonctions de traitement * d'interruption NE PEUVENT EN AUCUN CAS appeler directement * cette fonction. * type : facultative. *---------------------------------------------------------------- */ void waitSem(unsigned char task, unsigned char sem) { unsigned char semVal; if ((semVal = getSemValue(sem))) setSemValue(sem, semVal - 1); else { addWaitingTask(sem, task); stopTask(task); #ifdef WSDEBUG printf("Task %d is waiting on semaphore %d\n", task, sem); #endif } } /*---------------------------------------------------------------- * signalSem réalise l'opération classique signal. Si la valeur * du sémaphore est non nulle, ce qui veut dire qu'aucune tâche * n'est en attente sur un sémaphore, la valeur decelui-ci est * simplement incrémentée. Si sa valeur est nulle (ce qui veut * dire qu'il y a peut-être une tâche en attente sur ce * sémaphore), la tâche la plus prioritaire en attente sur ce * sémaphore, si elle existe, est à nouveau rendue exécutable. * Si aucune tâche n'était en attente, la tâche ayant exécuté * l'appel poursuit son exécution. * * arguments : sem est le numéro du sémaphore. * * valeur de retour : aucune. * * note : cette fonction peut être appelée dans une fonction de * traitement d'interruption. Elle est principalement utilisée de * manière interne par le kernel. Les tâches NE devraient PAS * appeler directement cette fonction. * type : facultative. *---------------------------------------------------------------- */ void signalSem(unsigned char sem) { unsigned char semVal, task; task = higherWaitingTask(sem); /* si task == MAX_TASK, cela veut dire qu'aucune tâche n'attend sur le sémaphore, donc on incrémente simplement sa valeur */ if ((semVal = getSemValue(sem)) || task == MAX_TASK) setSemValue(sem, semVal + 1); else { restartTask(task); remWaitingTask(sem, task); #ifdef WSDEBUG printf("Task %d, previously waiting on semaphore %d, " \ "is restarted\n", task, sem); #endif } }