How does a CPU timer work if the count value is larger than what it can hold?

Viewed 211

If I'm not mistaking, the C sleep function is one of the places a CPU timer is used. Linux will set a timer and removes the process from the scheduler. Timer counts down and once it hits 0 it will interrupt the CPU and the OS will re-add the process to the scheduler. Am I correct about this?

If so then what happens if the timer value is larger than the number of bits the counter hardware can handle? Let's say the counter has a max of 23 bits and I need a 24 bit value (i.e I need to sleep for a long time).

Edit:

Also, what If we have multiple sleeps going on at the same time, more than the CPU has counters for?

1 Answers

sleep function is one of the places a CPU timer is used

No. The Linux kernel implements a scheduler. When you call nanosleep() (the GNU C library on Linux uses nanosleep() to implement sleep()), you do a nanosleep syscall; this causes the kernel to not schedule that task (usually a thread in a userspace process) before the desired duration has elapsed, or a signal is delivered to an userspace signal handler installed without the SA_RESTART flag using that task (in which case the system call returns with -EINTR).

On a microcontroller, say an Arduino or similar, you can implement sleeping using a timer, though.

Let's say you have a timer facility that can count from anywhere up to TIMER_MAX to zero, i.e. sleep for any number of time units between 1 and TIMER_MAX. If you want to sleep for a longer duration, you can do so in TIMER_MAX intervals:

/* Timer-based sleep function; returns the number of units slept,
   at most 'units'.  Can only sleep between 1 and TIMER_MAX, inclusive. */
static unsigned short  timer_sleep(unsigned short units);

void sleep(unsigned long duration)
{
    /* "long" sleep(s) */
    while (duration >= TIMER_MAX)
        duration -= timer_sleep(TIMER_MAX);

    /* "short" sleep(s) */
    while (duration > 0)
        duration -= timer_sleep(duration);
}

You could replace the latter while loop with just a timer_sleep(duration), if timer_sleep(u) always returns u. Written as above, using two while loops, the sleep will work as long as timer_sleep(u) returns u or less.

Related