2013-01-17 7 views
7

Per darvi un contesto completo la mia discussione è iniziata con l'osservazione che sto eseguendo un SMP linux (3.0.1-rt11) su ARM cortex SoC basato su A8 che è un uniprocessore. Ero curioso di sapere se ci saranno dei vantaggi in termini di prestazioni disabilitando il supporto SMP. E se sì quale impatto avrà sui miei driver e gestori di interrupt.Informazioni sul collegamento tra CONFIG_SMP, Spinlocks e CONFIG_PREEMPT nel più recente (3.0.0 e sopra) kernel Linux

Ho fatto qualche lettura e ho incontrato due argomenti correlati: spinlock e preemption del kernel. Ho fatto un po 'più di googling e di lettura, ma questa volta ho solo alcune risposte stantie e contraddittorie. Quindi ho pensato di provare StackOverflow.

origine dei miei dubbi/domande è questa para da driver di periferica Linux 3a edizione Capitolo 5:

spinlocks sono, per loro natura, destinato a circolare su multiprocessore sistemi, anche se una workstation monoprocessore esecuzione un preemptive kernel si comporta come SMP, per quanto riguarda la concorrenza. Se un sistema uniprocessore non invasivo è andato in un giro su un blocco, lo girerebbe per sempre; nessun altro thread sarebbe mai stato in grado di ottenere la CPU per rilasciare il blocco. Per questo motivo, le operazioni spinlock sui sistemi uniprocessore senza preemption abilitato sono ottimizzate per fare nulla, ad eccezione di quelle che modificano lo stato di mascheramento IRQ . A causa della preventiva, anche se non ti aspetti mai che il tuo codice sia eseguito su un sistema SMP, devi ancora implementare il blocco appropriato.

I miei dubbi/domande sono:

a) è Linux kernel preemptive nello spazio kernel di default? In caso affermativo, questa preemption è limitata ai soli processi o ai gestori di interrupt possono anche essere preventivati?

b) Il kernel di Linux (su ARM) supporta interrupt annidato? Se sì, ogni gestore di interrupt (metà superiore) avrà il proprio stack o condivideranno lo stesso stack in modalità kernel 4k/8k?

c) Se disattivo SMP (Config_SMP) e preemption (Config_preempt) i blocchi di spin nei miei driver e gli interrupt handler hanno senso?

d) In che modo il kernel gestisce gli interrupt generati durante l'esecuzione della metà superiore, verranno disabilitati o mascherati?

Dopo un po 'googling ho trovato questo:

Per i kernel compilati senza CONFIG_SMP, e senza CONFIG_PREEMPT non esistono spinlocks affatto. Questa è una decisione di progettazione eccellente: quando nessun altro può essere eseguito allo stesso tempo, non c'è motivo di avere un blocco.

Se il kernel viene compilato senza CONFIG_SMP, ma CONFIG_PREEMPT è insieme, quindi spinlocks sufficiente disattivare prelazione, che è sufficiente per evitare corse. Per la maggior parte degli scopi, possiamo pensare alla prelazione come equivalente a SMP, e non ci preoccupiamo separatamente.

Ma non c'è nessuna versione o data del kernel su source.Qualcuno può confermare se è ancora valido per gli ultimi kernel di Linux?

+0

Ecco quattro domande, quindi dividerlo in quanto potrebbero non essere risolti insieme. –

risposta

6

a) Se Linux è preemptive o no dipende dal fatto che non lo si configuri in questo modo
con CONFIG_PREEMPT. Non esiste un valore predefinito. Se esegui make config, dovrai scegliere.

b) Gli interrupt si annidano su Linux; mentre gli interrupt vengono elaborati, altri interrupt possono essere disattivati. Questo è vero su ARM e su numerose altre architetture. È tutto nella stessa pila. Ovviamente, lo stack spaziale dell'utente non è utilizzato per gli interrupt!

c) Se si disattiva SMP e prelazione, spinlocks nel codice si ridurrà a no-op, se sono i spinlocks regolari, e spinlocks IRQ (spin_lock_irqsave/spin_lock_irqrestore) si trasformerà in interrupt disabilitare/abilitare. Questi ultimi sono ancora essenziali, quindi; impediscono le razze tra le attività che eseguono il codice e interrompono l'esecuzione del codice.

d) La "metà superiore" si riferisce tradizionalmente alle routine di servizio di interruzione. Il codice mezzo superiore di un driver viene eseguito da interrupt. La metà inferiore è chiamata da attività (per leggere o scrivere dati o qualsiasi altra cosa). I dettagli sulla gestione degli interrupt sono specifici per l'architettura.

Ultimamente ho lavorato a stretto contatto con interrupt Linux su una particolare architettura MIPS. Su quella scheda particolare, c'erano 128 linee di interruzione mascherabili tramite due parole a 64 bit. Il kernel ha implementato uno schema di priorità sopra questo, quindi prima di eseguire un gestore per un dato interrupt, quelli inferiori sono stati mascherati tramite aggiornamenti di questi registri a 2x64 bit. Ho implementato una modifica in modo che le priorità di interrupt possano essere impostate in modo arbitrario, anziché in base alla posizione dell'hardware, e in modo dinamico scrivendo valori in una voce /proc. Inoltre, ho inserito un hack in base al quale una parte della priorità numerica dell'IRQ si sovrapponeva alla priorità in tempo reale delle attività. Quindi le attività RT (cioè i thread dello spazio utente) assegnate a determinati intervalli di livelli prioritari erano in grado di sopprimere implicitamente un certo intervallo di interruzioni durante l'esecuzione. Questo è stato molto utile per evitare che interrupt mal funzionanti interferiscano con attività critiche (ad esempio, una routine di servizio di interruzione nel codice del driver IDE utilizzato per il flash compatto, che esegue loop occupati a causa di un'interfaccia hardware mal progettata, causando la scrittura flash su diventare l'attività di massima priorità de facto nel sistema.) Comunque, il comportamento di mascheramento IRQ non è scritto in pietra, se si ha il controllo del kernel utilizzato dai clienti.

Il citato dichiarazioni in questione sono vere solo circa spinlocks regolari (spin_lock funzione/macro) non spinlocks IRQ (spin_lock_irqsave). In un kernel preempibile su un uniprocessore, lo spin_lock deve semplicemente disabilitare la prelazione, che è sufficiente per mantenere tutte le altre attività fuori dal kernel fino a spin_unlock. Ma spin_lock_irqsave deve disabilitare gli interrupt.

Problemi correlati