Su código es igual 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 */
}
Se puede ver en el código, save_old_value_at_eax
no es el valor original real, mientras que la CPU realice xchg. Debe obtener el valor antiguo/original mediante la instrucción xchg, no guardándolo antes de realizar xchg. ("no es el verdadero valor original/antiguo" significa, si otra CPU toma el bloqueo después de que esta CPU guarda el valor, pero antes de que esta CPU realice la instrucción xchg, esta CPU obtendrá el valor antiguo incorrecto, y cree que tomó el bloqueo exitoso, por lo tanto, dos CPU ingresan a la CS al mismo tiempo). Has separado una instrucción de lectura-modificación-escritura en tres instrucciones, las tres instrucciones completas no son atómicas (incluso si mueves el prefijo de bloqueo a xchg).
supongo que pensó el prefijo de bloqueo bloqueará el TODA tres instrucciones, pero en realidad prefijo de bloqueo sólo puede ser utilizado para la única instrucción que se adjunta (no todas las instrucciones se pueden unir) y nosotros no necesita el prefijo de bloqueo en SMP para xchg. Presupuesto de 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.
*/
Mis sugerencias:
- No te repitas, por favor utilice el bloqueo de giro del núcleo de Linux.
- NO SE REPITA, utilice xchg(), cmpxchg() del kernel de Linux si desea implementar un bloqueo de giro.
- Más información sobre instrucciones. También puede averiguar cómo lo implementa el kernel de Linux.
mi adición está arriba. –
Excelente; probablemente no sea el error, pero me parece muy extraño que la función 'spin_destroy()' libere la memoria que no fue asignada por 'spin_init()'. (¿Hay una función 'spin_alloc()' también?) – sarnold
spin_destory es quizás exceso. –