Ejemplo n.º 1
0
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;
}