4.10. Cron�metros de Carreras: Un Pasatiempo del N�cleo

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.