//
// Syd: rock-solid application kernel
// benches/sys/kill.rs: kill microbenchmarks
//
// Copyright (c) 2024 Ali Polatel <alip@chesswob.org>
//
// SPDX-License-Identifier: GPL-3.0

// This micro-benchmark tests the performance of sending signals (kill) to the
// current process. We ignore SIGINT and SIGTERM so they don't terminate us.

use std::mem::zeroed;

use brunch::{benches, Bench};
use libc::{
    c_int, getpid, kill, sigaction, sigemptyset, sighandler_t, sigset_t, SIGINT, SIGTERM, SIG_IGN,
};

fn main() {
    // -- Init Phase --

    // Get our own PID.
    let pid = unsafe { getpid() };

    // Prepare to ignore SIGINT and SIGTERM so we don't exit.
    unsafe {
        let mut new_action: sigaction = zeroed();
        sigemptyset(&mut new_action.sa_mask as *mut sigset_t);
        new_action.sa_sigaction = SIG_IGN as sighandler_t; // set handler to ignore
        new_action.sa_flags = 0;

        // Install ignore handlers.
        sigaction(SIGINT, &new_action, std::ptr::null_mut());
        sigaction(SIGTERM, &new_action, std::ptr::null_mut());
    }

    // -- Bench Phase --
    benches!(
        inline:

        // 1) Send self signal 0 (no signal is actually sent, but kill
        //    checks permissions).
        Bench::new("SendSignal0").run(|| {
            unsafe {
                let _ = kill(pid, 0);
            }
        }),

        // 2) Send self SIGINT.
        Bench::new("SendSignalSIGINT").run(|| {
            unsafe {
                let _ = kill(pid, SIGINT as c_int);
            }
        }),

        // 3) Send self SIGTERM.
        Bench::new("SendSignalSIGTERM").run(|| {
            unsafe {
                let _ = kill(pid, SIGTERM as c_int);
            }
        }),
    );
}
