Los cron�metros pueden producir sus propios problemas con las
carreras. Considera una colecci�n de objeros (listas, hash, etc)
donde cada objeto tiene un cron�metro que lo va a destruir.
Si quieres destruir la colecci�n entera (digamos en el borrado
de un m�dulo), quiz�s realices lo siguiente:
/* ESTE C�DIGO ES MALO MALO MALO MALO: SI HUBIERA ALGO PEOR
USUAR�A NOTACI�N H�NGARA */
spin_lock_bh(&list_lock);
while (list) {
struct foo *next = list->next;
del_timer(&list->timer);
kfree(list);
list = next;
}
spin_unlock_bh(&list_lock);
Tarde o temprano, esto romper�a en SMP, porque un cron�metro puede
acabar antes que spin_lock_bh(), y s�lo
obtendr�a el bloqueo despu�s de spin_unlock_bh(),
y entonces intentar�a liberar el elemento (�el cual ya ha sido liberado!).
Esto puede ser eliminado comprobando el resultado de
del_timer(): si retorna
1, el cron�metro ha sido borrado.
Si 0, significa (en este caso)
que est� actualmente ejecut�ndose, por lo tanto lo que podemos
hacer es:
retry:
spin_lock_bh(&list_lock);
while (list) {
struct foo *next = list->next;
if (!del_timer(&list->timer)) {
/* Le da al cron�metro una oportunidad para borrarlo */
spin_unlock_bh(&list_lock);
goto retry;
}
kfree(list);
list = next;
}
spin_unlock_bh(&list_lock);
Otro problema com�n es el borrando de cron�metros que se reinician a ellos
mismos (llamando a add_timer() al final de
su funci�n cron�metro). Porque este es un caso bastante com�n que es
propenso a carreras, puedes poner una llamada a timer_exit()
muy al funal de tu funci�n cron�metro, y usar del_timer_sync()
para manejar este caso. �l retorna el n�mero de veces que el cron�metro
tuvo que ser borrado antes de que finalmente lo par�ramos a�adi�ndolo
otra vez.