timerfd yang dipasang terhadap wall clock dapat mengalami perubahan clock diskontinu sebelum deadline tercapai. Dengan TFD_TIMER_CANCEL_ON_SET, Linux mengekspos kejadian itu melalui descriptor: read() berikutnya gagal dengan ECANCELED, bukan menyajikan lompatan clock sebagai expiration timer biasa.
Cakupan flag ini sengaja sempit. Efeknya berlaku ketika timerfd_settime() memasang timer absolut pada CLOCK_REALTIME atau CLOCK_REALTIME_ALARM, lalu clock tersebut mengalami perubahan diskontinu.
Cancellation terikat pada timer realtime absolut
timerfd_create() memilih clock yang menjadi basis timer. Descriptor dengan CLOCK_REALTIME mengikuti system wall clock, sedangkan CLOCK_MONOTONIC mengikuti clock yang tidak disetel melalui perubahan wall clock.
timerfd_settime() menentukan apakah nilai expiration bersifat relatif atau absolut. TFD_TIMER_ABSTIME membuat it_value ditafsirkan sebagai timestamp absolut pada clock yang dipilih.
int fd = timerfd_create(CLOCK_REALTIME, TFD_CLOEXEC);
struct itimerspec spec = {
.it_value = {
.tv_sec = deadline,
.tv_nsec = 0,
},
};
int rc = timerfd_settime(
fd,
TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET,
&spec,
NULL
);Agar TFD_TIMER_CANCEL_ON_SET memiliki efek cancellation yang didefinisikan, timer harus absolut dan memakai CLOCK_REALTIME atau CLOCK_REALTIME_ALARM. Flag ini bukan fasilitas cancellation umum untuk semua clock pada timerfd.
Perubahan clock diskontinu menghasilkan ECANCELED
Wall-clock time dapat diubah secara diskontinu oleh operasi seperti clock_settime() atau settimeofday(). Operasi semacam itu memindahkan realtime clock ke posisi baru, bukan sekadar membiarkannya berjalan normal.
Ketika timerfd yang memenuhi syarat dipasang dengan TFD_TIMER_CANCEL_ON_SET, perubahan diskontinu menandai timer sebagai canceled. read() pada descriptor tersebut kemudian gagal dengan ECANCELED.
CLOCK_REALTIME
10:00 -------- timer dipasang untuk 10:30 -------->
|
+-- clock diubah langsung ke 11:00
|
`-- read timerfd -> ECANCELEDError tersebut berbeda dari expiration count normal. Read timerfd yang berhasil mengembalikan unsigned integer 64-bit berisi jumlah expiration. ECANCELED menyatakan bahwa basis realtime berubah secara diskontinu ketika mode cancellation aktif.
Flag melaporkan event pada domain clock, bukan drift timer
TFD_TIMER_CANCEL_ON_SET tidak melaporkan setiap koreksi yang dilakukan subsistem timekeeping kernel. Trigger yang didokumentasikan adalah perubahan diskontinu pada CLOCK_REALTIME atau CLOCK_REALTIME_ALARM untuk timer yang memenuhi syarat.
Perbedaan ini penting karena sinkronisasi wall clock juga dapat melibatkan penyesuaian bertahap. Clock yang sedang disesuaikan secara gradual tetap bergerak melewati waktu; kontrak cancellation berpusat pada perubahan diskontinu, bukan setiap koreksi laju atau aksi sinkronisasi.
Interface ini melaporkan batas yang spesifik: timestamp absolut ditafsirkan pada domain realtime yang posisinya direset saat timer masih aktif.
Timer relatif memiliki semantics berbeda
Timer relatif menyatakan durasi sejak timer dipasang. Timer realtime absolut menyatakan posisi pada clock yang dapat disetel. Kedua kontrak tersebut berbeda ketika wall clock bergerak.
relatif: expire setelah 30 menit
absolut: expire pada realtime timestamp TTFD_TIMER_CANCEL_ON_SET terkait dengan kontrak kedua. Flag ini memberi software cara untuk mendeteksi bahwa sistem koordinat wall clock berubah setelah deadline absolut dipasang.
Untuk deadline berbasis elapsed time yang tidak boleh mengikuti perubahan wall clock, monotonic clock merupakan domain yang relevan. CLOCK_MONOTONIC tidak terpengaruh oleh penyetelan wall clock secara diskontinu, sehingga mekanisme cancellation realtime bukan modelnya.
Cancellation terlihat melalui semantics read
Timerfd adalah file descriptor, sehingga state expiration dapat masuk ke event handling berbasis descriptor. Aplikasi dapat menunggunya melalui poll, select, atau epoll, lalu mengonsumsi state timer dengan read().
Hasil cancellation muncul pada batas read. Kode yang menganggap setiap timerfd readable hanya menghasilkan expiration count dapat salah menangani mode ini jika error read() tidak diperiksa.
uint64_t expirations;
ssize_t n = read(fd, &expirations, sizeof(expirations));
if (n < 0 && errno == ECANCELED) {
/* Realtime clock berubah secara diskontinu. */
}Branch tersebut berbeda secara semantik dari EAGAIN pada descriptor nonblocking. EAGAIN menyatakan belum ada expiration yang tersedia; ECANCELED melaporkan invalidation akibat perubahan clock yang memenuhi kondisi.
Re-arming menetapkan deadline absolut baru
Setelah software menerima cancellation, software dapat membaca state clock saat ini, menghitung kembali kebijakan yang diperlukan, lalu memasang descriptor lagi. Kernel tidak menentukan arti civil-time intent awal setelah clock meloncat.
Batas kebijakan ini penting untuk schedule yang terikat pada wall time. Koreksi clock langsung dapat menempatkan sistem sebelum atau sesudah timestamp awal. Memperlakukan deadline lama secara otomatis sebagai expiration biasa akan menyembunyikan fakta bahwa koordinat waktu telah berubah.
Cancellation memberi aplikasi titik keputusan eksplisit. Aplikasi dapat membuang deadline, menerjemahkannya menjadi timestamp absolut baru, menjalankan pekerjaan terkait, atau menerapkan kebijakan lain berdasarkan model waktunya sendiri.
Pemilihan clock tetap menjadi keputusan semantik utama
Flag ini tidak membuat timer realtime setara dengan timer monotonic. Flag hanya membuat satu kelas gangguan realtime terlihat. Timer realtime absolut tetap mengikuti clock yang dapat disetel, sedangkan timer monotonic tetap merepresentasikan domain clock berbeda.
TFD_TIMER_CANCEL_ON_SET berguna tepat pada batas tersebut. Flag mempertahankan makna deadline wall-clock absolut tanpa diam-diam mencampurkan reset wall clock diskontinu ke penanganan expiration normal. ECANCELED yang dihasilkan memungkinkan kode berbasis descriptor membedakan expiration timer dari invalidation posisi clock yang menjadi dasar expiration tersebut.