Download Documentazione del progetto
Transcript
CAPITOLO 6. SCELTE DI IMPLEMENTAZIONE DEL SISTEMA 149 essenzialmente avviene richiamando una per una le funzioni di pulizia denite dai singoli oggetti contenuti nell'oggetto principale (thmx e thmx_gadget rispettivamente), per poi de-registrare il modulo presso il kernel. Essendo coivolti diversi kernel thread per l'esecuzione, questo ha richiesto una sincronizzazione per la terminazione di tali thread. Tale sincronizzazione è stata implementata impostando una opportuna variabile atomica da ambo i lati (thmx.disconnect_state sull'host e thmx_gadget.running sul gadget). Visto che tutti i thread eseguono dei loop inniti in cui rimangono in attesa su delle apposite wait_queue nché il chiamante non li sveglia, e solo allora eseguono il proprio lavoro per poi tornare in attesa, è stato suciente inserire dei controlli ogni volta che i thread escono dall'attesa: se è stata impostata la variabile di disconnessione del sistema, l'esecuzione può terminare. In questo modo, il thread principale semplicemente imposta tale variabile e poi sveglia il thread. Inne, però, la sincronizzazione è stata forzata utilizzando delle struct completion: ogni volta che il thread padre risveglia un glio per la terminazione, utilizza la funzione wake_up_interruptible_sync() la quale fa sì che il processo chiamante mantenga la cpu anche dopo la chiamata a tale funzione (che comunque non è atomica). Questo per evi- tare che il thread glio acquisisca il processore prima che il thread chiamante non lo stia aspettando per la terminazione. Infatti, subito dopo la wake_up_interruptible_sync(), il thread chiamante esegue la wait_for_completion(), attendendo così la terminazione del thread svechiamata a gliato. Questo, una volta risvegliato e dopo aver notato che il modulo si trova in uno stato di terminazione, prima di uscire chiama la che risveglia il processo in attesa di tale terminazione. complete(),