il codice è uguale a:
static __inline__ int xchg_asm(int* lock, int val) {
int save_old_value_at_eax;
save_old_value_at_eax = *lock; /* with a wrong lock prefix */
xchg *lock with val and discard the original value of *lock.
return save_old_value_at_eax; /* but it not the real original value of *lock */
}
Si può vedere dal codice, save_old_value_at_eax
c'è il vero valore originale mentre la CPU esegue xchg. Si dovrebbe ottenere il valore vecchio/originale con l'istruzione xchg, non salvandolo prima di eseguire xchg. ("non è il vero valore vecchio/originale" significa, se un'altra CPU prende il blocco dopo che questa CPU ha salvato il valore ma prima che questa CPU esegua l'istruzione xchg, questa CPU avrà il vecchio valore sbagliato, e pensa che abbia preso il blocco riuscito, quindi, due CPU entrano nel CS contemporaneamente). Hai separato un'istruzione read-modify-write in tre istruzioni, le tre istruzioni complete non sono atomiche (anche se sposti il prefisso di blocco a xchg).
immagino si pensava il prefisso di blocco bloccherà l'INTERA tre istruzioni, ma in realtà il prefisso serratura può essere utilizzato solo per la sola istruzione di cui è attaccato (non tutte le istruzioni possono essere attaccati) E noi non serve il prefisso di blocco su SMP per xchg. Citazione di linux_kernel_src/arch/x86 // include/asm/cmpxchg.h
/*
* Note: no "lock" prefix even on SMP: xchg always implies lock anyway.
* Since this is generally used to protect other memory information, we
* use "asm volatile" and "memory" clobbers to prevent gcc from moving
* information around.
*/
I miei suggerimenti:
- do not repeat yourself, si prega di utilizzare il blocco rotazione del kernel di Linux.
- NON RIPETERE TE STESSO, utilizzare xchg(), cmpxchg() del kernel Linux se si desidera implementare un blocco di selezione.
- Ulteriori informazioni sulle istruzioni. puoi anche scoprire come il kernel Linux lo implementa.
fonte
2012-07-17 03:39:33
la mia aggiunta è sopra. –
Eccellente; probabilmente non è l'errore, ma mi sembra molto strano per la funzione 'spin_destroy()' per liberare memoria non allocata da 'spin_init()'. (Esiste anche una funzione 'spin_alloc()'?) – sarnold
spin_destory è in eccesso forse. –