Pengantar Objek Mutex

Seperti namanya, objek mutex adalah mekanisme sinkronisasi yang dirancang untuk memastikan akses yang saling eksklusif ke satu sumber daya yang dibagikan di antara sekumpulan utas mode kernel. Hanya driver tingkat tertinggi, seperti driver sistem file (FSD) yang menggunakan utas pekerja eksekutif, yang kemungkinan akan menggunakan objek mutex.

Mungkin, driver tingkat tertinggi dengan utas yang dibuat driver atau rutinitas panggilan balik worker-thread mungkin menggunakan objek mutex. Namun, setiap driver dengan utas yang dapat dipertanyakan atau rutinitas panggilan balik alur pekerja harus mengelola akuisisi, menunggu, dan melepaskan objek mutexnya dengan sangat hati-hati.

Objek mutex memiliki fitur bawaan yang menyediakan utas sistem (hanya mode kernel) akses bebas kebuntuan yang saling eksklusif ke sumber daya bersama di komputer SMP. Kernel menetapkan kepemilikan mutex ke satu utas pada satu waktu.

Memperoleh kepemilikan muteks mencegah pengiriman panggilan prosedur asinkron (APC) mode kernel normal. Utas tidak akan didahului oleh APC kecuali kernel mengeluarkan perangkat lunak APC_LEVEL mengganggu untuk menjalankan APC kernel khusus, seperti rutinitas penyelesaian IRP manajer I/O yang mengembalikan hasil kepada pemohon asli operasi I/O

Utas dapat memperoleh kepemilikan objek mutex yang sudah dimilikinya (kepemilikan rekursif), tetapi objek mutex yang diperoleh secara rekursif tidak diatur ke status Sinyal sampai utas melepaskan kepemilikannya sepenuhnya. Utas semacam itu harus secara eksplisit merilis mutex sebanyak yang diperoleh kepemilikan sebelum utas lain dapat memperoleh mutex.

Kernel tidak pernah mengizinkan utas yang memiliki mutex untuk menyebabkan transisi ke mode pengguna tanpa terlebih dahulu melepaskan mutex dan mengaturnya ke status Sinyal. Jika ada utas yang dibuat FSD atau dibuat driver yang memiliki mutex mencoba mengembalikan kontrol ke manajer I/O sebelum merilis kepemilikan mutex, kernel akan menurunkan sistem.

Setiap driver yang menggunakan objek mutex harus memanggil KeInitializeMutex sekali sebelum menunggu atau melepaskan objek mutexnya. Gambar berikut menggambarkan bagaimana dua utas sistem mungkin menggunakan objek mutex.

diagram yang mengilustrasikan menunggu objek mutex.

Seperti yang ditunjukkan oleh gambar sebelumnya, driver yang menggunakan objek mutex harus menyediakan penyimpanan untuk objek mutex, yang harus merupakan residen. Driver dapat menggunakan ekstensi perangkat dari objek perangkat yang dibuat driver, ekstensi pengontrol jika menggunakan objek pengontrol, atau kumpulan yang tidak disebarkan yang dialokasikan oleh driver.

Ketika driver memanggil KeInitializeMutex (biasanya dari rutinitas AddDevice-nya ), driver harus meneruskan penunjuk ke penyimpanan driver untuk objek mutex, yang diinisialisasi kernel ke status Sinyal.

Setelah driver tingkat tertinggi seperti itu diinisialisasi, driver dapat mengelola akses yang saling eksklusif ke sumber daya bersama seperti yang ditunjukkan pada gambar sebelumnya. Misalnya, rutinitas pengiriman driver untuk operasi dan utas yang sinkron secara inheren mungkin menggunakan mutex untuk melindungi antrean yang dibuat driver untuk RUN.

Karena KeInitializeMutexselalu mengatur status awal objek mutex ke Signaled (seperti yang ditunjukkan oleh gambar sebelumnya):

  1. Panggilan awal rutin pengiriman ke KeWaitForSingleObject dengan penunjuk Mutex segera menempatkan utas saat ini ke status siap, memberikan kepemilikan utas mutex, dan mengatur ulang status mutex ke Tidak Diberi Sinyal. Segera setelah rutinitas pengiriman dilanjutkan berjalan, ia dapat dengan aman memasukkan IRP ke dalam antrean yang dilindungi mutex.

  2. Ketika utas kedua (rutinitas pengiriman lain, rutinitas panggilan balik alur pekerja yang disediakan driver, atau utas yang dibuat driver) memanggil KeWaitForSingleObject dengan penunjuk Mutex , utas kedua dimasukkan ke dalam status tunggu.

  3. Ketika rutinitas pengiriman selesai mengantre IRP seperti yang dijelaskan pada langkah 1, ia memanggil KeReleaseMutex dengan penunjuk Mutex dan nilai Boolean Wait , yang menunjukkan apakah berniat untuk memanggil KeWaitForSingleObject (atau KeWaitForMutexObject) dengan Mutex segera setelah KeReleaseMutex mengembalikan kontrol.

  4. Dengan asumsi rutin pengiriman merilis kepemilikannya atas mutex di langkah 3 (Tunggu diatur ke FALSE), mutex diatur ke status Sinyal oleh KeReleaseMutex. Mutex saat ini tidak memiliki pemilik, sehingga kernel menentukan apakah utas lain sedang menunggu mutex tersebut. Jika demikian, kernel membuat utas kedua (lihat langkah 2) pemilik mutex, mungkin meningkatkan prioritas utas ke nilai prioritas real-time terendah, dan mengubah statusnya menjadi siap.

  5. Kernel mengirimkan utas kedua untuk eksekusi segera setelah prosesor tersedia: yaitu, ketika tidak ada utas lain dengan prioritas yang lebih tinggi saat ini dalam keadaan siap dan tidak ada rutinitas mode kernel untuk dijalankan pada IRQL yang lebih tinggi. Utas kedua (pengiriman rutin antrean IRP atau rutinitas panggilan balik utas pekerja driver atau utas yang dibuat driver yang mengantre IRP) sekarang dapat dengan aman mengakses antrean runtime integrasi yang dilindungi mutex sampai memanggil KeReleaseMutex.

Jika utas memperoleh kepemilikan objek mutex secara rekursif, utas tersebut harus secara eksplisit memanggil KeReleaseMutex sebanyak menunggu pada mutex untuk mengatur objek mutex ke status Sinyal. Misalnya, jika utas memanggil KeWaitForSingleObject dan kemudian KeWaitForMutexObject dengan penunjuk Mutex yang sama, alur harus memanggil KeReleaseMutex dua kali ketika memperoleh mutex untuk mengatur objek mutex tersebut ke status Sinyal.

Memanggil KeReleaseMutex dengan parameter Tunggu yang diatur ke TRUE menunjukkan niat pemanggil untuk segera memanggil rutinitas dukungan KeWaitXxx saat kembali dari KeReleaseMutex.

Pertimbangkan panduan berikut untuk mengatur parameter Tunggu ke KeReleaseMutex:

Utas yang dapat dipertanyakan atau rutinitas driver yang dapat dipertanyakan yang berjalan di IRQL PASSIVE_LEVEL tidak boleh memanggil KeReleaseMutex dengan parameter Tunggu diatur ke TRUE. Panggilan seperti itu menyebabkan kesalahan halaman fatal jika pemanggil kebetulan di-page out antara panggilan ke KeReleaseMutex dan ObjekKeWait Xxx.

Setiap rutinitas driver standar yang berjalan pada IRQL yang lebih besar dari PASSIVE_LEVEL tidak dapat menunggu interval nonzero pada objek dispatcher apa pun tanpa menurunkan sistem. Namun, rutinitas seperti itu dapat memanggil KeReleaseMutex jika memiliki mutex saat berjalan di IRQL kurang dari atau sama dengan DISPATCH_LEVEL.

Untuk ringkasan IRQL tempat rutinitas driver standar dijalankan, lihat Mengelola Prioritas Perangkat Keras.