Лекція №11. механізми синхронізації
В операційній системі з витісняє багатозадачність, та ще підтримує кілька процесорів, гостро постає завдання синхронізації доступу до спільно використовуваних ресурсів комп'ютера, будь то апаратний пристрій або структура в пам'яті.
Спін-блокування - найпростіший механізм синхронізації. Спін-блокування може бути захоплена. і звільнена. Якщо спін-блокування була захоплена, подальша спроба захопити спін-блокування будь-яким потоком призведе до виконання нескінченного циклу зі спробою захоплення спін-блокування (стан потоку busy-waiting). Цикл закінчиться тільки тоді, коли колишній власник спін-блокування звільнить її. Використання спін-блокувань безпечно на мультипроцесорних платформах, тобто гарантується, що, навіть якщо її запитують одночасно два потоки на двох процесорах, захопить її тільки один з потоків.
Спін-блокування призначені для захисту даних, доступ до яких здійснюється на різних, в т.ч. підвищених рівнях IRQL. Тепер уявімо таку ситуацію: код, який працює на рівні IRQL PASSIVE_LEVEL захопив спін-блокування для подальшого безпечного зміни деяких даних. Після цього код був перерваний кодом з більш високим рівнем IRQL DISPATCH_LEVEL, який спробував захопити ту ж спін-блокування, і, як випливає з опису спін-блокування, увійшов в нескінченний цикл очікування звільнення блокування. Цей цикл ніколи не закінчиться, тому що код, який захопив спін-блокування і повинен її звільнити, має більш низький рівень IRQL і ніколи не отримає шансу виконатися! Щоб така ситуація не виникла, необхідний механізм, який дозволить коду з деяким рівнем IRQL переривати код з більш низьким рівнем IRQL в той момент коли код з більш низьким рівнем IRQL володіє спін-блокуванням. Таким механізмом є підвищення поточного рівня IRQL в момент захоплення спін-блокування до деякого рівня IRQL, асоційованого зі спин-блокуванням, і відновлення старого рівня IRQL в момент її звільнення. Зі сказаного випливає, що код, який працює на підвищеному рівні IRQL, не має права звертатися до ресурсу, захищеному спін-блокуванням, якщо рівень IRQL спін-блокування нижче рівня IRQL виробляє доступ до ресурсу коду. При спробі таким кодом захопити спін-блокування його рівень IRQL буде знижений до рівня IRQL спін-блокування, що призведе до непередбачуваних наслідків.
В NT є 2 види спін-блокувань:
· Звичайні спін-блокування, особливим випадком яких є спін-блокування скасування запиту в / в, використовувані при організації черг запитів в / в (див. Лекцію 10 п. [10.3] Скасування запитів в / в).
· Спін-блокування синхронізації переривань
З звичайними спін-блокуваннями пов'язаний IRQL DISPATCH_LEVEL, тобто
1. всі спроби їх захоплення повинні проводитися на рівні IRQL<=DISPATCH_LEVEL
2. в разі захоплення спін-блокування поточний рівень IRQL піднімається до рівня DISPATCH_LEVEL.
З спін-блокуваннями синхронізації переривань пов'язаний один з рівнів DIRQL.
Використання звичайних спін-блокувань буде описано нижче (за винятком спін-блокувань скасування запитів в / в, які були описані в розділі 10.3).
Використання спін-блокувань синхронізації переривань буде описано в лекції присвяченій обробці переривань (орієнтовно, лекція №13).