zephyrproject-rtos / zephyr

Primary Git Repository for the Zephyr Project. Zephyr is a new generation, scalable, optimized, secure RTOS for multiple hardware architectures.
https://docs.zephyrproject.org
Apache License 2.0
10.93k stars 6.65k forks source link

Posix CLOCK_THREAD_CPUTIME_ID for clock_gettime implementation #80363

Open jrp631 opened 1 month ago

jrp631 commented 1 month ago

Posix execition time clock implementation

So far, when using the POSIX interface CLOCK_THREAD-CPUTIME_ID has not been supported, and it would be convinient to have support for an execution time clock, specially when using mulithreaded, preemptive POSIX code from a different platform.

Taking advantage of thread runtime stats?

My knowledge of Zephyrs source code and internal tools is not very deep but here is a proposal I've tested myself.

Since Zephyr implements thread runtime stats, which have a record of the ammount of CPU cycles that Thread has taken we can use them and turn them into struct timespec. Adding minimal code to clock_gettime and usage.c

/*clock.c*/
case CLOCK_THREAD_CPUTIME_ID:
        k_tid_t thread = k_current_get();
        //if (!k_thread_runtime_stats_enabled(thread)) {
        //  errno = EINVAL;
        //  return -1;
        //}

        k_thread_runtime_stats_t stats;
        k_thread_runtime_stats_get(thread, &stats);
        uint64_t cycles = stats.execution_cycles;

        uint64_t ns = k_cyc_to_ns_floor64(cycles);

        ts->tv_sec = ns / NSEC_PER_SEC;
        ts->tv_nsec = ns % NSEC_PER_SEC;
        return 0;
   //more code

Assuming Stats are not enabled since startup

A function k_thread_runtime_stats_enabled can be added to usage.c to check if the runtime stats are enabled and if they are not, notice the user.

/*usage.c*/
//check if runtime stats are enabled
int k_thread_runtime_stats_enabled(k_tid_t thread)
{
    k_spinlock_key_t  key;

    CHECKIF(thread == NULL) {
        return -EINVAL;
    }
    key = k_spin_lock(&usage_lock);
    int enabled = thread->base.usage.track_usage;
    k_spin_unlock(&usage_lock, key);
    return enabled;
}
#endif /* CONFIG_SCHED_THREAD_USAGE_ANALYSIS */

This function could be called at the beggining of the CLOCK_THREAD_CPUTIME_ID assuming that runtime stats should be enabled by the programmer.

Preemptive Busy_wait

This new functionallity comes specially handy when triying to implement a busy_wait() like function that does not take into account the time the calling thread has been preempted.

github-actions[bot] commented 1 month ago

Hi @jrp631! We appreciate you submitting your first issue for our open-source project. šŸŒŸ

Even though I'm a bot, I can assure you that the whole community is genuinely grateful for your time and effort. šŸ¤–šŸ’™