2013-02-26 4 views
11

Quando un mutex è già bloccato da T1 e T2 tenta di bloccarlo, qual è il processo per T2?Implementazione e segnalazione mutex

credo che più o meno così:

-T2 prova a bloccare, non riesce, forse spinlocks un po ', quindi chiama il rendimento ...
-T2 è prevista per l'esecuzione di un paio di volte, prova a bloccare fallisce, i rendimenti ...
-Eventually T1 sblocca, T2 è previsto per l'esecuzione e riesce a bloccare il mutex ...

fa T1 sblocco esplicito segnale alla pianificazione o di altri thread che il mutex è sbloccato? Oppure si sblocca e lascia lo scheduler per pianificare i thread bloccati quando si ritiene opportuno farlo (in quanto lo scheduler non ha idea di thread bloccati e non li considera come speciali)?

+1

"Penso che il principio di mutua esclusione garantisca che nessun 2 o più thread entri nella sezione critica allo stesso tempo. Ora, che tu abbia una coda per i thread che stanno cercando di bloccare il mutex o che tu faccia solo un busy-wait fino a quando un mutex è libero dipende da come lo implementa e quali sono le tue esigenze per mutex. Ad esempio, 'mutex' in RTOS come VxWorks implementa il protocollo del limite di priorità, che potrebbe non essere necessario nel sistema operativo generale (GPOS). – Raj

risposta

3

In breve: sì, forse ...

Si tratta di dettagli di implementazione, ed è piuttosto difficile da dire senza al quale sistema operativo meno sul fatto che sta parlando. In genere, lo sblocco di un mutex segnerà solo il thread in attesa come "eseguibile", ma non (necessariamente) invocherà lo scheduler in quel momento - e anche se lo scheduler viene chiamato, non significa che T2 sarà il thread successivo correre.

In Linux, il codice immette lo mutex_unlock() che verifica se vi sono attività in attesa (controllando se il conteggio dei blocchi è inferiore a zero - inizia da 1 per sbloccato, una richiesta di blocco singola lo azzera, un ulteriore tentativo di blocco lo renderà negativo). Se c'è un ulteriore processo di attesa, chiama uno "sblocco a percorso lento", che tramite un paio di funzioni di reindirizzamento per consentire dettagli di implementazione, finisce in __mutex_unlock_common_slowpath - poche righe più in basso, c'è una chiamata a wake_up_process che alla fine finisce in try_to_wake_up - che essenzialmente accoda l'attività come "pronto per essere eseguito", quindi chiama lo scheduler (tramite diversi livelli di funzioni!)

+0

quindi stai dicendo che su linux thread che blocca è contrassegnato come non eseguibile (quindi sched non pianificarlo prima che sia contrassegnato come eseguibile) – NoSenseEtAl

+0

Sì, è corretto. Questo presuppone che tu stia usando il kernel mutex tho ', che potrebbe non essere quello che, ad esempio, implementa pthread_mutex. –

+0

molto buona risposta ... senza che ti infastidisca molto ... puoi dire velocemente se il futex differisce da questo in qualche modo significativo. – NoSenseEtAl

6

Dipende dal sistema operativo. Ho visto solo girare, girare con yield, variabili di condizione generale nel kernel, programmazione controllata da userland e primitive di blocco specializzate con supporto del kernel.

Lo spinning e lo spinning con yield hanno prestazioni terribili. La pianificazione teoricamente controllata dall'utilizzatore (vedi Scheduler activations) dovrebbe avere le migliori prestazioni, ma per quanto ne so nessuno l'ha mai fatto funzionare correttamente in tutti i casi. Le variabili di condizione di uso generale nel kernel e primitive di blocco specializzate con supporto del kernel dovrebbero eseguire più o meno le stesse con futex in Linux come il miglior esempio di quest'ultimo.

Ci sono situazioni in cui la rotazione può avere prestazioni migliori. In Solaris alcune primitive di blocco nel kernel hanno una modalità adattiva in cui il blocco gira finché il processo che blocca il blocco è in esecuzione su una CPU diversa. Se il proprietario del lucchetto dorme o viene arrestato, il cameriere di blocco va anche a dormire. In altri kernel ci sono classi di serrature in cui il proprietario del lucchetto non può essere preimpostato o dormire quando si tiene il lucchetto, quindi in quei casi la rotazione funziona bene. In generale, tuttavia, specialmente nel campo dell'utente, la rotazione ha casi orribili degenerati (il processo di rotazione gira finché non viene eseguito il pre-rilascio per consentire al proprietario del blocco di funzionare) che è molto negativo per le prestazioni. Si noti che le primitive di blocco specializzate come futex potrebbero implementare ottimizzazioni come questa, cosa che le variabili di condizione generale non possono normalmente.

+0

nice A, ma "Spinning and spinning with yield have terrible performance" dovrebbe essere qualificato ... Posso immaginare scenari di bassa contesa e bassa quantità di lavoro sotto lock dove gli spinlock sono veloci. – NoSenseEtAl

+1

Tutti i blocchi sono (abbastanza) efficienti quando non ci sono conflitti. Anche i metodi di bloccaggio ben progettati sono efficaci anche quando c'è un alto contenimento. Dipende anche dal numero di processori disponibili - un'attesa "spinning" è terribile su un singolo processore, perché l'altro thread che attualmente sta bloccando il lock non verrà eseguito, e T2 sta usando tutta la CPU per controllare se T1 chi non ha intenzione di scappare ha rilasciato il lucchetto - questo è un uso piuttosto inutile del tempo della CPU. –

+0

@Mat stavo pensando al sistema multicore, ma ofc sono d'accordo con te per single core. – NoSenseEtAl

1

dire che abbiamo seguente scenario:

1. T1 got M1. M1 locked. 
2. T2 tries to get M1 and gets blocked as M1 is locked. 
3. T3 tries to get M1 and gets blocked as M1 is locked. 
4. ...some time later... 
5. T1 unlocks M1.* 
6. T2 got M1. 
7. T3 is unblocked and tries to get M1 but is blocked again as T2 got M1 first. 

* La chiamata di sistema, sblocco, dovrebbe notificare tutti bloccato attività/processi/discussioni che sono bloccati su blocco chiamata del mutex . Sono quindi programmati da eseguire. Ciò non significa che siano eseguiti in quanto potrebbe esserci già qualcuno in esecuzione. Come altri affermano, dipende dall'implementazione come è fatto. Se davvero vuoi imparare questo bene, ti consiglio questo book