Bagikan melalui


Penjadwalan User-Mode

Peringatan

Pada Windows 11, penjadwalan mode pengguna tidak didukung. Semua panggilan gagal dengan kesalahan ERROR_NOT_SUPPORTED.

Penjadwalan mode pengguna (UMS) adalah mekanisme ringan yang dapat digunakan aplikasi untuk menjadwalkan utas mereka sendiri. Aplikasi dapat beralih antara utas UMS dalam mode pengguna tanpa melibatkan penjadwal sistem dan mendapatkan kembali kontrol prosesor jika utas UMS memblokir di kernel. Utas UMS berbeda dari serat karena setiap utas UMS memiliki konteks utasnya sendiri alih-alih berbagi konteks utas dari satu utas. Kemampuan untuk beralih antar utas dalam mode pengguna membuat UMS lebih efisien daripada kumpulan utas untuk mengelola sejumlah besar item kerja durasi pendek yang memerlukan beberapa panggilan sistem.

UMS direkomendasikan untuk aplikasi dengan persyaratan performa tinggi yang perlu menjalankan banyak utas secara efisien secara bersamaan pada sistem multiprosedur atau multicore. Untuk memanfaatkan UMS, aplikasi harus menerapkan komponen penjadwal yang mengelola utas UMS aplikasi dan menentukan kapan mereka harus berjalan. Pengembang harus mempertimbangkan apakah persyaratan performa aplikasi mereka membenarkan pekerjaan yang terlibat dalam pengembangan komponen tersebut. Aplikasi dengan persyaratan performa sedang mungkin lebih baik dilayani dengan memungkinkan penjadwal sistem untuk menjadwalkan utas mereka.

UMS tersedia untuk aplikasi 64-bit yang berjalan pada versi AMD64 dan Itanium Windows 7 dan Windows Server 2008 R2 hingga Windows 10 Versi 21H2 dan Windows Server 2022. Fitur ini tidak tersedia di Windows versi Arm64, 32-bit atau di Windows 11.

Untuk detailnya, lihat bagian berikut ini:

Penjadwal UMS

Penjadwal UMS aplikasi bertanggung jawab untuk membuat, mengelola, dan menghapus utas UMS dan menentukan utas UMS mana yang akan dijalankan. Penjadwal aplikasi melakukan tugas-tugas berikut:

  • Membuat satu utas penjadwal UMS untuk setiap prosesor tempat aplikasi akan menjalankan utas pekerja UMS.
  • Membuat utas pekerja UMS untuk melakukan pekerjaan aplikasi.
  • Mempertahankan antrean rangkaian siap pakai sendiri dari utas pekerja yang siap dijalankan, dan memilih utas untuk dijalankan berdasarkan kebijakan penjadwalan aplikasi.
  • Membuat dan memantau satu atau beberapa daftar penyelesaian tempat sistem mengantre utas setelah selesai diproses di kernel. Ini termasuk utas pekerja dan utas yang baru dibuat sebelumnya diblokir pada panggilan sistem yang menjadi tidak diblokir.
  • Menyediakan fungsi titik entri penjadwal untuk menangani pemberitahuan dari sistem. Sistem memanggil fungsi titik masuk saat utas penjadwal dibuat, utas pekerja memblokir panggilan sistem, atau utas pekerja secara eksplisit menghasilkan kontrol.
  • Melakukan tugas pembersihan untuk utas pekerja yang telah selesai berjalan.
  • Melakukan pematian penjadwal secara teratur saat diminta oleh aplikasi.

Utas Penjadwal UMS

Utas penjadwal UMS adalah utas biasa yang telah dikonversi ke UMS dengan memanggil fungsi EnterUmsSchedulingMode . Penjadwal sistem menentukan kapan utas penjadwal UMS berjalan berdasarkan prioritasnya relatif terhadap utas siap lainnya. Prosesor tempat utas penjadwal berjalan dipengaruhi oleh afinitas utas, sama seperti untuk utas non-UMS.

Pemanggil EnterUmsSchedulingMode menentukan daftar penyelesaian dan fungsi titik entri UmsSchedulerProc untuk mengaitkan dengan utas penjadwal UMS. Sistem memanggil fungsi titik masuk yang ditentukan ketika selesai mengonversi utas panggilan ke UMS. Fungsi titik masuk penjadwal bertanggung jawab untuk menentukan tindakan berikutnya yang sesuai untuk utas yang ditentukan. Untuk informasi selengkapnya, lihat Fungsi Titik Entri Penjadwal UMS nanti dalam topik ini.

Aplikasi mungkin membuat satu utas penjadwal UMS untuk setiap prosesor yang akan digunakan untuk menjalankan utas UMS. Aplikasi ini mungkin juga mengatur afinitas setiap utas penjadwal UMS untuk prosesor logis tertentu, yang cenderung mengecualikan utas yang tidak terkait agar tidak berjalan pada prosesor tersebut, secara efektif menyimpannya untuk utas penjadwal tersebut. Ketahuilah bahwa mengatur afinitas utas dengan cara ini dapat memengaruhi performa sistem secara keseluruhan dengan kelaparan proses lain yang mungkin berjalan pada sistem. Untuk informasi selengkapnya tentang afinitas utas, lihat Beberapa Prosesor.

Utas Pekerja UMS, Konteks Utas, dan Daftar Penyelesaian

Utas pekerja UMS dibuat dengan memanggil CreateRemoteThreadEx dengan atribut PROC_THREAD_ATTRIBUTE_UMS_THREAD dan menentukan konteks utas UMS dan daftar penyelesaian.

Konteks utas UMS mewakili status utas UMS dari utas pekerja dan digunakan untuk mengidentifikasi utas pekerja dalam panggilan fungsi UMS. Ini dibuat dengan memanggil CreateUmsThreadContext.

Daftar penyelesaian dibuat dengan memanggil fungsi CreateUmsCompletionList . Daftar penyelesaian menerima utas pekerja UMS yang telah menyelesaikan eksekusi di kernel dan siap dijalankan dalam mode pengguna. Hanya sistem yang dapat mengantre utas pekerja ke daftar penyelesaian. Utas pekerja UMS baru secara otomatis diantrekan ke daftar penyelesaian yang ditentukan saat utas dibuat. Utas pekerja yang diblokir sebelumnya juga diantrekan ke daftar penyelesaian ketika tidak lagi diblokir.

Setiap utas penjadwal UMS dikaitkan dengan satu daftar penyelesaian. Namun, daftar penyelesaian yang sama dapat dikaitkan dengan sejumlah utas penjadwal UMS, dan utas penjadwal dapat mengambil konteks UMS dari daftar penyelesaian apa pun yang memiliki penunjuk.

Setiap daftar penyelesaian memiliki peristiwa terkait yang disinyalkan oleh sistem saat mengantre satu atau beberapa utas pekerja ke daftar kosong. Fungsi GetUmsCompletionListEvent mengambil handel ke peristiwa untuk daftar penyelesaian yang ditentukan. Aplikasi dapat menunggu lebih dari satu peristiwa daftar penyelesaian bersama dengan peristiwa lain yang masuk akal untuk aplikasi.

Fungsi Titik Entri Penjadwal UMS

Fungsi titik entri penjadwal aplikasi diimplementasikan sebagai fungsi UmsSchedulerProc . Sistem memanggil fungsi titik masuk penjadwal aplikasi pada waktu berikut:

  • Saat utas non-UMS dikonversi ke utas penjadwal UMS dengan memanggil EnterUmsSchedulingMode.
  • Ketika utas pekerja UMS memanggil UmsThreadYield.
  • Ketika utas pekerja UMS memblokir layanan sistem seperti panggilan sistem atau kesalahan halaman.

Parameter Alasan fungsi UmsSchedulerProc menentukan alasan fungsi titik masuk dipanggil. Jika fungsi titik entri dipanggil karena utas penjadwal UMS baru dibuat, parameter SchedulerParam berisi data yang ditentukan oleh pemanggil EnterUmsSchedulingMode. Jika fungsi titik masuk dipanggil karena utas pekerja UMS dihasilkan, parameter SchedulerParam berisi data yang ditentukan oleh pemanggil UmsThreadYield. Jika fungsi titik entri dipanggil karena utas pekerja UMS diblokir di kernel, parameter SchedulerParam adalah NULL.

Fungsi titik masuk penjadwal bertanggung jawab untuk menentukan tindakan berikutnya yang sesuai untuk utas yang ditentukan. Misalnya, jika utas pekerja diblokir, fungsi titik masuk penjadwal mungkin menjalankan utas pekerja UMS siap berikutnya yang tersedia.

Ketika fungsi titik entri penjadwal dipanggil, penjadwal aplikasi harus mencoba mengambil semua item dalam daftar penyelesaian terkait dengan memanggil fungsi DequeueUmsCompletionListItems . Fungsi ini mengambil daftar konteks utas UMS yang telah selesai diproses di kernel dan siap dijalankan dalam mode pengguna. Penjadwal aplikasi tidak boleh menjalankan utas UMS langsung dari daftar ini karena ini dapat menyebabkan perilaku yang tidak dapat diprediksi dalam aplikasi. Sebagai gantinya, penjadwal harus mengambil semua konteks utas UMS dengan memanggil fungsi GetNextUmsListItem sekali untuk setiap konteks, menyisipkan konteks utas UMS dalam antrean utas siap penjadwal, dan hanya kemudian menjalankan utas UMS dari antrean utas siap.

Jika penjadwal tidak perlu menunggu beberapa peristiwa, penjadwal harus memanggil DequeueUmsCompletionListItems dengan parameter batas waktu bukan nol sehingga fungsi menunggu peristiwa daftar penyelesaian sebelum kembali. Jika penjadwal perlu menunggu beberapa peristiwa daftar penyelesaian, penjadwal harus memanggil DequeueUmsCompletionListItems dengan parameter batas waktu nol sehingga fungsi segera kembali, bahkan jika daftar penyelesaian kosong. Dalam hal ini, penjadwal dapat menunggu secara eksplisit pada peristiwa daftar penyelesaian, misalnya, dengan menggunakan WaitForMultipleObjects.

Eksekusi Utas UMS

Utas pekerja UMS yang baru dibuat diantrekan ke daftar penyelesaian yang ditentukan dan tidak mulai berjalan sampai penjadwal UMS aplikasi memilihnya untuk dijalankan. Ini berbeda dari utas non-UMS, yang secara otomatis dijadwalkan penjadwal sistem untuk dijalankan kecuali pemanggil secara eksplisit membuat utas ditangguhkan.

Penjadwal menjalankan utas pekerja dengan memanggil ExecuteUmsThread dengan konteks UMS utas pekerja. Utas pekerja UMS berjalan sampai menghasilkan dengan memanggil fungsi, blok, atau penghentian UmsThreadYield .

Praktik Terbaik UMS

Aplikasi yang menerapkan UMS harus mengikuti praktik terbaik ini:

  • Struktur yang mendasar untuk konteks utas UMS dikelola oleh sistem dan tidak boleh dimodifikasi secara langsung. Sebagai gantinya, gunakan QueryUmsThreadInformation dan SetUmsThreadInformation untuk mengambil dan mengatur informasi tentang utas pekerja UMS.
  • Untuk membantu mencegah kebuntuan, utas penjadwal UMS tidak boleh berbagi kunci dengan utas pekerja UMS. Ini termasuk kunci yang dibuat aplikasi dan kunci sistem yang diperoleh secara tidak langsung oleh operasi seperti mengalokasikan dari tumpukan atau memuat DLL. Misalnya, penjadwal menjalankan utas pekerja UMS yang memuat DLL. Utas pekerja memperoleh kunci dan blok pemuat. Sistem memanggil fungsi titik entri penjadwal, yang kemudian memuat DLL. Hal ini menyebabkan kebuntuan, karena kunci loader sudah ditahan dan tidak dapat dilepaskan sampai utas pertama dibuka blokirnya. Untuk membantu menghindari masalah ini, delegasikan pekerjaan yang mungkin berbagi kunci dengan utas pekerja UMS ke utas pekerja UMS khusus atau utas non-UMS.
  • UMS paling efisien ketika sebagian besar pemrosesan dilakukan dalam mode pengguna. Jika memungkinkan, hindari melakukan panggilan sistem di utas pekerja UMS.
  • Utas pekerja UMS tidak boleh mengasumsikan penjadwal sistem sedang digunakan. Asumsi ini dapat memiliki efek halus; misalnya, jika utas dalam kode yang tidak diketahui menetapkan prioritas atau afinitas utas, penjadwal UMS mungkin masih menimpanya. Kode yang mengasumsikan penjadwal sistem sedang digunakan mungkin tidak berperilaku seperti yang diharapkan dan dapat rusak ketika dipanggil oleh utas UMS.
  • Sistem mungkin perlu mengunci konteks utas utas pekerja UMS. Misalnya, panggilan prosedur asinkron mode kernel (APC) mungkin mengubah konteks utas UMS, sehingga konteks utas harus dikunci. Jika penjadwal mencoba menjalankan konteks utas UMS saat dikunci, panggilan akan gagal. Perilaku ini dirancang, dan penjadwal harus dirancang untuk mencoba kembali akses ke konteks utas UMS.