void semaphore::wait(void){ sighold(SIGALRM); this->value -= 1; if(this->value < 0){ getRunningThread()->state = BLOCKED; this->waitQueue.push(getRunningThread()); sigrelse(SIGALRM); raise(SIGALRM); } else{ sigrelse(SIGALRM); } }
int thread_yield(){ #ifdef O_PREEMPTION interruptsOff(); #endif //le thread courant thread *th1 = getRunningThread(); //le prochain thread thread *th2 = prochainThread(); #ifdef O_PRIORITE updatePriority(th1); #endif #ifdef O_PREEMTION setAlarm(); #endif if(th2->tid != th1->tid){ addInFifo(th1); setRunningThread(th2); #ifdef O_PREEMPTION interruptsOn(); #endif swapcontext(th1->context,th2->context); } return 0; }
thread* prochainThread(){ //si aucun thread n'attend if(isEmptyFifo(&fifo_READY)) return getRunningThread(); //sinon on ordonnance #ifdef O_PRIORITE //ordonnancement: thread de plus grande priorité return removeBigPriority(&fifo_READY); #else //ordonnancement: le premier de la liste d'attente return removeFifoHead(&fifo_READY); #endif }
void thread_exit(void *retval){ #ifdef O_PREEMPTION interruptsOff(); #endif //le thread qui veut terminer son execution thread *courant = getRunningThread(); //on recupere la valeur de retour courant->valRetour = retval; //on met le statut a FINISH courant->state = STATUS_FINISH; #ifdef O_KILLCHILDREN //on tue tous les eventuels enfants du thread if(courant->is_father == TRUE){ killThreadChildren(courant->tid); } #endif //si le thread est attendu par un autre thread if(courant->est_attendu == TRUE){ thread* waiting = courant->threadAttendant; //on fait le nettoyage nettoyage_thread_termine(courant); //on lance le thread qui attendait que le thread termine removeThreadByTid(&fifo_STOP,waiting->tid); waiting->state = STATUS_READY; setRunningThread(waiting); #ifdef O_PREEMPTION interruptsOn(); #endif setcontext(waiting->context); exit(1); } //sinon on lance le prochain thread thread* prochain = prochainThread(); if(prochain->tid != courant->tid){ addInFifo(courant); setRunningThread(prochain); #ifdef O_PREEMPTION interruptsOn(); #endif setcontext(prochain->context); } exit(1); }
thread* retrouverLeThread(thread_t tid){ if(estLeThreadCourant(tid)) return getRunningThread(); //on le cherche dans la file d'attente thread* th = removeThreadByTid(&fifo_READY,tid); if(th == NULL){ //on le cherche dans la file des threads termines th = removeThreadByTid(&fifo_FINISH,tid); } if(th == NULL){ //on le cherche dans la file des threads termines th = removeThreadByTid(&fifo_STOP,tid); } return th;//vaut NULL si pas trouve }
int thread_join(thread_t identity, void **retval){ #ifdef O_PREEMPTION interruptsOff(); #endif //thread attendu thread* waited = retrouverLeThread(identity); //thread attendant thread* waiting = getRunningThread(); #ifdef O_PRIORITE updatePriority(waiting); #endif //si le thread à attendre n'existe pas if(!waited){ return -1; } //si le thread à attendre attend aussi un autre thread if(waited->state == STATUS_STOP){ return -1; } //on recupere l'adresse de la valeur de retour waited->adresseValRetour = retval; //on stocke dans la structure le thread qui attend waited->est_attendu = TRUE; waited->threadAttendant = waiting; //Si le thread a déjà terminé, on nettoie et on quitte if(waited->state == STATUS_FINISH){ nettoyage_thread_termine(waited); return 0; } //sinon on lance le thread waiting->state = STATUS_STOP; addInFifo(waiting); setRunningThread(waited); swapcontext(waiting->context, waited->context); return 0; }
int thread_create(thread_t*t,void*(*func)(void *),void*arg){ #ifdef O_PREEMPTION interruptsOff(); #endif //si le main n'est pas un thread, il le devient sinon if(MAIN_IS_THREAD == FALSE && mainBecomesThread()==-1) return -1; //on cree le context du thread ucontext_t *uc = createContext((void (*) (void))func,arg); if(uc == NULL) return -1; //on cree le thread *t = getNextTID(); thread *newth = newThread(*t, STATUS_READY, uc); //on met à jour la rélation thread pere et thread fils thread* pere = getRunningThread(); pere->is_father = TRUE; newth->father = pere; newth->context->uc_link = pere->context; addInFifo(pere); #ifdef O_PRIORITE updatePriority(pere); #endif //on lance le nouveau thread cree setRunningThread(newth); #ifdef O_PREEMPTION interruptsOn(); #endif swapcontext(pere->context, newth->context); return 0; }