/********************************************************************** TERMINATE Si occupa di: -Uccidere root e tutti i figli ricorsivamente -Rimettere i thread nella lista dei liberi -Togliere i thread dalle varie liste/array in cui sono presenti -Decrementare il valore di thread_count -Pulire la inbox da eventuali messaggi **********************************************************************/ void terminate (tcb_t *target) { msg_t *msg; tcb_t *child; /* Se ha un padre lo elimino dai suoi figli */ outChild(target); /* Caso ricorsivo -> HA figli (su cui viene chiamata la terminate) */ while (TRUE) { if ( (child = removeChild(target)) == NULL ) break; /* Passa al caso base e pulisce thread, liste, messaggi... */ terminate(child); } /* Caso base -> NON ha figli */ /* Se è in qualche lista o è il thread corrente lo elimino */ if (((outThread(&ready_queue, target)) != NULL) || (current_thread == target)) { /* Pulisco la inbox */ while (TRUE) { if ( (msg = popMessage(&(target->t_inbox), NULL)) == NULL ) break; freeMsg(msg); } /* Se è un manager lo elimino dal trap_managers array */ delete_manager(target); if (current_thread == target) current_thread=NULL; /* Restituisco ai thread liberi */ freeTcb(target); thread_count--; } else if (outThread(&wait_queue, target)) { /* Decremento contatore processi in attesa I/O o SSI */ if (target->waiting_for == SSI_tcb) soft_block_count--; /* Tutto come caso precedente*/ while (TRUE) { if ( (msg = popMessage(&(target->t_inbox), NULL)) == NULL ) break; freeMsg(msg); } delete_manager(target); freeTcb(target); thread_count--; } else PANIC(); }
/* inizializza tutti i tcb_t contenuti in tcbTable mettendoli nella lista tcbFree_h, rendedoli di fatto tutti disponibili all'utilizzo, questa funzione è chiamata solo una volta durante l'inizializzazione delle strutture. */ void initTcbs(void) { int i; INIT_LIST_HEAD(&tcbFree_h.t_next); for (i = 0; i < MAXTHREADS; i++) { INIT_LIST_HEAD(&(tcbTable[i].t_inbox)); freeTcb(&tcbTable[i]); } }
int main() { int i; initTcbs(); addokbuf("Initialized thread control blocks \n"); /* Check allocTcb */ for (i = 0; i < MAXPROC; i++) { if ((threadp[i] = allocTcb()) == NULL) adderrbuf("allocTcb(): unexpected NULL "); } if (allocTcb() != NULL) { adderrbuf("allocTcb(): allocated more than MAXPROC entries "); } addokbuf("allocTcb ok \n"); /* return the last 10 entries back to free list */ for (i = 10; i < MAXPROC; i++) freeTcb(threadp[i]); addokbuf("freed 10 entries \n"); /* create a 10-element thread queue */ qa = mkEmptyThreadQ(); if (!emptyThreadQ(qa)) adderrbuf("emptyThreadQ(qa): unexpected FALSE "); addokbuf("Inserting... \n"); for (i = 0; i < 10; i++) { if ((q = allocTcb()) == NULL) adderrbuf("allocTcb(): unexpected NULL while insert "); switch (i) { case 0: firstthread = q; break; case 5: midthread = q; break; case 9: lastthread = q; break; default: break; } insertBackThreadQ(&qa, q); } addokbuf("inserted 10 elements \n"); if (emptyThreadQ(qa)) adderrbuf("emptyThreadQ(qa): unexpected TRUE" ); /* Check outThreadQ and headThreadQ */ if (headThreadQ(qa) != firstthread) adderrbuf("headThreadQ(qa) failed "); q = outThreadQ(&qa, firstthread); if ((q == NULL) || (q != firstthread)) adderrbuf("outThreadQ(&qa, firstthread) failed on first entry "); freeTcb(q); q = outThreadQ(&qa, midthread); if (q == NULL || q != midthread) adderrbuf("outThreadQ(&qa, midthread) failed on middle entry "); freeTcb(q); if (outThreadQ(&qa, threadp[0]) != NULL) adderrbuf("outThreadQ(&qa, threadp[0]) failed on nonexistent entry "); addokbuf("outThreadQ() ok \n"); /* Check if removeThread and insertThread remove in the correct order */ addokbuf("Removing... \n"); for (i = 0; i < 8; i++) { if ((q = removeThreadQ(&qa)) == NULL) adderrbuf("removeThreadQ(&qa): unexpected NULL "); freeTcb(q); } if (q != lastthread) adderrbuf("removeThreadQ(): failed on last entry "); if (removeThreadQ(&qa) != NULL) adderrbuf("removeThreadQ(&qa): removes too many entries "); if (!emptyThreadQ(qa)) adderrbuf("emptyThreadQ(qa): unexpected FALSE "); addokbuf("insertThreadQ(), removeThreadQ() and emptyThreadQ() ok \n"); addokbuf("thread queues module ok \n"); addokbuf("After all, tomorrow is another day!\n"); return 0; }