Votre observation est bonne: sur un système monoprocesseur, il n'y a pas de raison de tourner pour attendre une ressource, car vous pourrez aussi bien changer de threads plus tôt que plus tard. Mutex et sémaphores font exactement cela.
Sur un système multiprocesseur, un thread sur un autre processeur peut libérer le verrou sans vous basculer vers le contexte. Spinlocks peut être utile, alors, si vous ne vous attendez pas à attendre longtemps, car il peut être plus rapide juste pour traîner jusqu'à ce que l'autre thread déverrouille la chose. Si vous allez dormir sur un mutex, vous êtes essentiellement assuré d'un temps mort important avant que vous ne soyez reporté. En revanche, dans le code noyau, la situation change: les gestionnaires d'interruption doivent accéder aux ressources partagées avec le reste du noyau, mais ils ne peuvent pas dormir. Les mutexs mettent le noyau en veille, donc vous ne pouvez pas les utiliser, mais les spinlocks ne sont pas utiles car rien n'interrompra un gestionnaire d'interruption sur un uniprocesseur (enfin, peut-être une autre interruption, mais c'est effrayant).
Dans un noyau, puis, spinlocks dans un gestionnaire d'interruption compiler à un no-op. Ils sont complètement élidés, comme vous pourriez le penser. En même temps, pour empêcher les courses, les verrouillages dans le reste du noyau désactivent les interruptions juste avant qu'elles ne tournent réellement sur quelque chose (car les tâches du noyau peuvent être planifiées). Ces codes n'ont besoin que de verrous (par opposition aux mutex) s'ils partagent du code avec un gestionnaire d'interruption.
En général, vous avez raison: spinlocks vraiment ne font pas beaucoup de sens sur un monoprocesseur si vous avez mutex, parce que les mutex perdre moins de temps.
La première URL est obsolète, rendez-vous à la place. http://uw714doc.sco.com/fr/man/html.3synch/Intro.3synch.html –