- Dukungan Linux untuk preemption real-time adalah pekerjaan yang telah menunggu masuk ke mainline selama hampir 20 tahun, dan Thomas Gleixner menyatakan di Linux Plumbers Conference 2023 bahwa hambatan besar terakhirnya adalah
printk() - Tujuannya adalah agar proses dengan prioritas tertinggi dapat berjalan dengan latensi pendek yang dapat diprediksi, dan untuk itu banyak bagian inti kernel telah ditulis ulang selama waktu yang lama
printk()dapat dipanggil dari konteks apa pun sehingga jauh lebih rumit daripada sekadar keluaran log, dan output sinkron saat ini bertentangan dengan target latensi real-time- Sejak 2018, sekitar 300 patch telah masuk upstream atau sedang menunggu di linux-next, dan tugas yang tersisa adalah handover pesan darurat serta penanganan keamanan driver konsol
- Setelah pembenahan
printk()selesai dan sisa kode real-time siap di linux-next, penggabungan pada merge window yang sama juga dimungkinkan, tetapi Gleixner mengatakan ia tidak akan lagi memprediksi kapan itu selesai
Pekerjaan preemption real-time yang berlangsung hampir 20 tahun
- Dukungan real-time Linux pertama kali muncul di LWN pada 2004, dan lama terlihat seperti “tinggal sedikit lagi selesai”
- LWN bahkan menulis judul the realtime preemption endgame pada 2009, tetapi di Linux Plumbers Conference 2023, Gleixner menilai bahwa kali ini garis akhirnya benar-benar sudah dekat
- Bagi Gleixner sendiri, ini adalah pekerjaan yang berlangsung hampir 25 tahun
- Ia mulai mengerjakan dukungan real-time Linux pada 1999
- Proyeknya sendiri juga telah berlanjut hampir 20 tahun
- Ia mengatakan akan ada “a big party” saat pekerjaan ini selesai, tetapi hambatan besar terakhir yang tersisa adalah
printk()
Latensi yang ingin dikurangi oleh preemption real-time
- Tujuan preemption real-time adalah agar proses dengan prioritas tertinggi selalu bisa berjalan dengan latensi minimum dan dapat diprediksi
- Untuk itu, kernel harus bisa dipreempt dalam sebanyak mungkin situasi, dan pengecualian harus dibatasi pada cakupan yang sempit dan jelas
- Cara kerja dasarnya telah mapan sejak lama, tetapi menyelesaikan detail-detail masalahnya membutuhkan waktu yang panjang
- Dalam proses ini, banyak bagian dari kernel inti telah ditulis ulang, dan manfaatnya meluas ke seluruh kernel, melampaui use case real-time
Mengapa printk() menjadi hambatan terakhir
- Ketika kode kernel perlu mengirim pesan ke konsol dan log, ia memanggil
printk()atau fungsi yang dibangun di atasnya - Ini terlihat seperti output sederhana, tetapi
printk()harus bekerja dalam hampir semua konteks- Dapat dipanggil bahkan dari handler non-maskable interrupt
- Dapat dipanggil lagi dari dalam pemanggilan
printk()lain - Dalam situasi crash sistem, informasi output bisa sangat penting sehingga sulit membatasi konteks pemanggilannya
- Karena tuntutan ini,
printk()memiliki masalah konkurensi, locking, dan penanganan driver yang saling terkait secara kompleks printk()di kernel saat ini memiliki struktur sinkron sepenuhnya- Pemanggilan tidak akan kembali sampai pesan dikirim ke semua tujuan yang telah dikonfigurasi
- Gleixner menyebut struktur ini “stupid”
- Terutama saat boot, sebagian besar output mungkin hanya noise, tetapi sistem tetap harus menunggu sampai semuanya dikirim
- Waktu tunggu ini berbenturan langsung dengan latensi yang ingin dikurangi oleh pekerjaan real-time
- Para pengembang real-time sudah lama memindahkan output
printk()ke thread terpisah agar menjadi asinkron, tetapi kode itu lebih mirip serangkaian hack daripada solusi mendasar
Pengerjaan ulang printk() sejak 2018
- Masalah
printk()mulai ditangani secara serius sejak 2018, dan sekitar 300 patch telah masuk upstream atau sedang menunggu di linux-next - Saat ini, tiga set patch terakhir untuk menyelesaikan pekerjaan itu sedang berjalan
- Salah satu detail tersulit adalah mekanisme handover
- Ketika kernel harus mencetak pesan darurat seperti saat crash, kernel mungkin perlu mengambil alih kontrol dari konsol yang sedang mencetak pesan berprioritas lebih rendah
- Tidak mudah melakukan ini dengan aman dalam konteks apa pun
- Tantangan lain adalah menandai driver konsol yang tidak aman digunakan dalam konteks tertentu
- Misalnya, jika perlu mencetak pesan saat non-maskable interrupt tetapi memerlukan pengaturan mode video, itu tidak akan bisa bekerja
- Gleixner menjawab bahwa tidak ada perubahan konsep mendasar dalam setahun terakhir
- Kernel memiliki 76 driver konsol yang perlu diperbaiki
- Kode handover telah diubah agar driver dapat diperbarui satu per satu, tanpa harus memperbaiki semuanya sekaligus
- Diskusi tambahan terbaru tentang pekerjaan
printk()ada di artikel ini
Output asinkron dan syarat penggabungan ke mainline
- Ketika Masami Hiramatsu bertanya pesan kernel mana yang harus dicetak secara sinkron, Gleixner menjawab bahwa hampir semuanya harus dibuat asinkron
- Output asinkron mengurangi latensi yang muncul dari pemanggilan
printk(), dan memungkinkan adanya thread kernel terpisah untuk setiap konsol- Konsol yang cepat bisa berjalan dengan kecepatannya sendiri tanpa menunggu konsol yang paling lambat
- Kode diubah agar pesan penting disalin sepenuhnya ke buffer pesan sebelum baris pertama dicetak
- Ini adalah langkah antisipasi jika driver konsol yang rusak merusak seluruh sistem
- Untuk urutan output yang lebih aman, sistem menulis terlebih dahulu ke konsol yang diketahui aman
- Misalnya, jika ada persistent-memory store, sistem menyimpan pesan lebih dulu sebelum mengirimkannya ke perangkat fisik
- Ini adalah cara untuk mempertahankan isi output meskipun driver yang rusak mematikan sistem
- Gleixner mengatakan pekerjaan ini memang sudah dekat, tetapi
printk()sulit diprediksi, sehingga ia tidak akan lagi menyebutkan perkiraan waktu selesai - Meski begitu, ia berharap sisa kode preemption real-time bisa masuk ke mainline sebelum ulang tahun ke-20 pada akhir 2024
- Ketika Clark Williams bertanya apakah sisa kode real-time akan dimasukkan pada merge window yang sama setelah patch
printk()masuk upstream, Gleixner menjawab “yes” secara bersyarat- Jika semua kode sudah staged di linux-next dan tampak siap, itu bisa dicoba
1 komentar
Opini Hacker News
QNX sudah menangani bagian ini dengan benar sejak puluhan tahun lalu. Mikrokernel memiliki batas atas untuk semua pekerjaan yang dilakukannya, dan kodenya pun hanya puluhan ribu baris
Mikrokernel hanya melakukan alokasi memori, dispatch CPU, dan pengiriman pesan antarproses. Sisanya, termasuk driver dan logger, semuanya berada di ruang pengguna, dan bisa dipreempt oleh thread dengan prioritas lebih tinggi
Kernel QNX tidak menangani string. Tidak ada parsing, formatting, maupun pesan. Linux sudah menjadi terlalu besar untuk real-time, dan karena harus membuat jutaan baris kode kernel semuanya bisa dipreempt, strukturnya sendiri tidak cocok untuk real-time. Itulah sebabnya butuh 20 tahun untuk memperbaikinya
Kontribusi terbesarnya terhadap desain kernel mungkin adalah penggunaan capability secara menyeluruh, sebagai cara untuk mengekspor kendali ke ruang pengguna dengan aman sekaligus fleksibel
Membesarnya kernel itu sendiri tidak terlalu saya khawatirkan. Banyak waktu pengembangan dicurahkan ke Linux, dan meskipun desktop tidak setinggi server dalam prioritas, pekerjaan untuk membuat kernel berkinerja baik di perangkat portabel dan semacamnya juga akan menguntungkan pengguna desktop
mainyang terstruktur baik dalam C atau bahasa turunan C.mainhanya mengoordinasikan pemanggilan fungsi lain, dan meskipun di sini kernel QNX melakukan inisialisasi lebih sedikit, konsep besarnya miripSaya bukan pengembang kernel, tetapi cara mempertahankannya tetap sederhana seperti ini tampak bagus
Ada contoh yang menunjukkan bagaimana kernel tetap berusaha mengeluarkan pesan log dengan cara apa pun bahkan pada sistem yang sedang sekarat, dan bagaimana itu digunakan di lingkungan produksi nyata
https://netflixtechblog.com/kubernetes-and-kernel-panics-ed6...
Saya penasaran apakah setelah masalah ini diperbaiki, sebagian kombinasi hardware/software yang dibuat untuk real-time bisa cukup banyak digantikan. Sekarang ada banyak pilihan chip ARM dan x86 yang murah, hemat daya, dan ber-clock tinggi
Karena clock-nya sangat tinggi, meskipun ada kasus yang terlewat, sering kali ada banyak siklus cadangan sehingga real-time yang sempurna mungkin menjadi kurang penting. Saya tahu ini tidak elegan maupun efisien, tetapi kadang komponen umum mengalahkan ketepatan
Satu pekerjaan yang dibuat buruk bisa menahan kernel dan mencegahnya melakukan hal yang berguna. Inti hard real-time adalah “tidak ada apa pun yang bisa menghalangi eksekusi pekerjaan penting ini”. Di bidang otomotif atau dirgantara, sistem kendali harus tetap berjalan dalam kondisi apa pun
Jika benar-benar membutuhkan real-time, berarti memang benar-benar membutuhkannya, dan “cukup mendekati” itu tidak ada. Namun ini hanya kesan saya sebagai orang luar
Sistem operasi, sekalipun RTOS, terlalu banyak mengganggu. Saya tidak tahu perubahan ini akan mengubah apa. Namun ini bergantung pada aplikasinya, dan ada banyak kasus yang hanya membutuhkan “hampir real-time”, jadi bisa berguna untuk penggunaan seperti itu
Diskusi di sini berfokus pada pembedaan antara aplikasi real-time “hard” dan “soft”. Untuk hard real-time, kemungkinan besar Anda sejak awal tidak ingin memakai sistem operasi umum seperti Linux, sementara pada soft real-time seperti konferensi video atau pemutaran audio, sesekali tersendat atau kehilangan beberapa frame bukanlah bencana
Argumennya adalah bahwa RT Linux akan menjadi solusi kuat untuk penggunaan soft real-time seperti itu. Namun penggunaan soft yang diusulkan itu sekarang pun sudah bisa dilakukan dengan embedded Linux. Pemutaran video atau audio software berlatensi rendah bukannya tidak mungkin, dan 20 tahun lalu pun sudah mungkin
Masalah muncul ketika pada sistem yang sibuk, I/O yang tidak bisa dipreempt sering menyela, tetapi di lingkungan embedded hal seperti itu jarang terjadi. Ada alasan yang meyakinkan untuk membuat kernel sepenuhnya bisa dipreempt dan memberi lebih banyak kendali penjadwalan, tetapi itu tidak banyak berkaitan dengan alasan bahwa Linux harus menggantikan sistem operasi real-time minimal atau kode bare-metal
Ini lebih mirip praktik higienis yang baik, dan membuat sistem operasi bekerja lebih baik di bawah beban bahkan untuk aplikasi non-real-time
Ini kabar baik, tetapi sekalipun kernel Linux menjadi real-time, perangkat kerasnya kemungkinan besar tetap tidak real-time karena cache dan sihir rumit di dalam CPU
Perangkat keras yang besar dan kompleks tidak cocok untuk real-time sejati. Karena itu AbsInt dan alat worst-case execution time (WCET) terutama menangani arsitektur CPU yang sederhana. 8051 benar-benar akan bertahan selamanya. Sebagai catatan, ada juga Zephyr RTOS
Cukup asumsikan kondisi seperti tidak ada cache hit sama sekali dan beban maksimum. Kalau kita bisa menetapkan batas atas waktu yang dibutuhkan, itu tidak masalah
Timer bisa menerima input encoder kuadratur dan hanya mengirim interrupt saat wrapping, atau sistem GPIO bisa dihubungkan ke DMA untuk melakukan streaming memori ke pin output tanpa campur tangan CPU. Streaming ke DAC atau transfer DMA dari ADC ke memori juga memungkinkan. Hal-hal seperti ini sering melewati cache demi latensi yang dapat diprediksi
Dalam praktiknya, banyak sistem real-time harus memproses dan mengagregasi data sensor yang terus bertambah, sehingga makin lama makin kuat
Saat masih junior, saya mengalami banyak sekali wawancara yang membuat frustrasi karena pewawancara tidak tahu apa sebenarnya arti real-time. Banyak orang melewatkan konsep “dan latensi yang dapat diprediksi” seperti di tulisan itu, dan tampaknya menganggap real-time sekadar berarti “cepat”
Jika mengendalikan sistem pengereman mobil, “latensi rata-rata 50 ms tetapi maksimum 80 ms” mungkin bisa diterima, tetapi “latensi rata-rata 1 ms tetapi bisa menjadi panjang secara arbitrer dan mungkin memakan beberapa detik” tidak bisa diterima
Logging sinkron kembali menimbulkan masalah. Di perusahaan, kami mengalami hal serupa karena GLOG (library logging Google); misalnya jika stdout adalah file, ia bisa terblokir pada I/O disk
Saat layanan kami berhenti lebih dari 100 ms, 90–99% penyebabnya adalah GLOG
“Kalau sesuatu wajib dicatat sebagai log tetapi log tidak bisa ditulis, apa yang akan dilakukan?” Belakangan saya cukup menunjuk ke teorema CAP dan mengatakan bahwa logging sama seperti sistem terdistribusi lainnya. Mungkin karena ada artikel Wikipedia dengan gambar segitiga dan kata “teorema”, orang-orang cenderung menerimanya
Setelah itu kami beralih ke pengiriman UDP. Lebih baik kehilangan sebagian log daripada kehilangan seluruh operasi produksi
$MSFTjuga ada masalah jenis “library logging merusak semuanya”. Bayangkan 100 thread masing-masing memiliki buffer logging 300 MBTentu saja memorinya hancur, dan server pun crash bahkan pada SKU termahal Azure App Service
Ini benar-benar mengingatkan masa lalu. Sekitar 17–18 tahun lalu, saya mengompilasi kernel Debian dengan RT_PREEMPT untuk dipakai pada peralatan ilmiah yang membutuhkan timing lebih ketat
Latensi dan jitternya sangat mengesankan. Setelah itu hampir tidak pernah saya pikirkan lagi, tetapi saat membuat aplikasi embedded dengan Raspberry Pi dan tidak ingin beralih ke mikrokontroler yang memakai RTOS, sepertinya ini punya banyak kegunaan
Saya pernah melihat usulan lama bahwa Linux bisa dijalankan sebagai sebuah task di RTOS, jadi ini terasa sangat menarik. Hal-hal yang membutuhkan deadline hard real-time dijalankan di RTOS, sehingga tidak terpengaruh latensi yang bisa ditimbulkan oleh sistem memori virtual. Saya tidak ingat apakah itu hanya ide sederhana atau benar-benar diimplementasikan, dan saya juga baru sekali melihat penyebutan bahwa RpiOS berada di atas RTOS, jadi saya penasaran
Penasaran apa artinya ini bagi pengguna umum. Apakah ini fitur yang hanya diaktifkan dalam situasi yang sangat spesifik, atau bisa juga menghadirkan sistem yang lebih responsif bagi masyarakat umum?
Setiap tugas mendapat anggaran X dan tidak boleh melampauinya. Jika dalam kasus terbaik cepat tetapi dalam kasus terburuk lambat, itu berarti sistem harus selalu mengasumsikan kasus terburuk
Contoh menghindari pemanggilan
printk()sinkron persis seperti itu, dan seharusnya memperbaiki latensi saat beban tinggi meski RT tidak diaktifkan. Saya rasa kernel RT yang sepenuhnya di-upstream tidak akan berperilaku berbeda dari kernel biasa kecuali benar-benar menjalankan proses RT. Alasan upstream memakan waktu lama adalah karena diperlukan kompromi untuk memungkinkan RT, dan menurut artikel, kompromi seperti itu kini tidak banyak tersisaKarena ketika penjadwalan real-time diperlukan, mereka bisa menggunakan kernel mainline terbaru
Penasaran bagaimana pendapat kalian tentang Xenomai[1]. Sudah beberapa tahun menggunakannya tanpa masalah
Di BeagleBone Black, jitter biasanya berada di kisaran ratusan nanodetik, dan saya menganggapnya real-time “keras”. Bisa menjadwalkan tugas periodik dalam satuan puluhan mikrodetik dan tidak pernah terlewat
Berbeda dengan Real-Time Linux yang mencoba membuat Linux itu sendiri dapat dipreempt, Xenomai pada dasarnya adalah kernel tersendiri dan menjalankan Linux sebagai tugas di atasnya. Ia menyediakan ABI sehingga tugas buatan pengguna dapat berjalan berdampingan dengan Linux atau dengan prioritas lebih tinggi. Misalnya, masalah
printk()dapat dilewati: Xenomai tidak peduli dan dengan senang hati melakukan context switch dariprintkuntuk menjalankan tugas penggunaKekurangannya adalah di dalam konteks Xenomai, pemanggilan sistem biasa tidak dapat dilakukan. Sebenarnya bisa, tetapi tentu saja itu merusak model real-time. Misalnya, jika memanggil
printf()ataumalloc()dari dalam tugas Xenomai, itu tidak dapat dipreempt. ABI Xenomai sebisa mungkin mereplikasi hal-hal yang mungkin dibutuhkan dari sisi pemanggilan sistem, dan jika Anda puas menangani alokasi heap sendiri, ia bekerja dengan sangat baik[1]: https://xenomai.org/