menios icon indicating copy to clipboard operation
menios copied to clipboard

clock_nanosleep() and timerfd support

Open pbalduino opened this issue 3 months ago • 0 comments

Goal

Implement clock_nanosleep() syscall and timerfd mechanisms for event-driven time waits.

Context

Only POSIX nanosleep() exists; clock_nanosleep() variant is missing (src/kernel/syscall/syscall.c has no handler). This limits sleep to CLOCK_REALTIME and prevents absolute time sleeps.

Current State

  • ✅ nanosleep() implemented (#287)
  • ❌ clock_nanosleep() missing
  • ❌ No timerfd support for event-driven waits

What's Needed

1. clock_nanosleep() Syscall

// SYS_clock_nanosleep - Sleep on specific clock
// int clock_nanosleep(clockid_t clk_id, int flags,
//                     const struct timespec *req, struct timespec *rem)
long sys_clock_nanosleep(clockid_t clk_id, int flags,
                         const struct timespec *req, struct timespec *rem);

// Flags
#define TIMER_ABSTIME 1  // Absolute time (vs relative)

Features:

  • Support CLOCK_REALTIME, CLOCK_MONOTONIC
  • TIMER_ABSTIME flag for absolute sleep deadlines
  • Return remaining time if interrupted
  • Proper error codes (EINVAL for bad clock, EINTR if interrupted)

2. timerfd Support

// Create timer file descriptor
int timerfd_create(int clockid, int flags);

// Set timer
int timerfd_settime(int fd, int flags,
                   const struct itimerspec *new_value,
                   struct itimerspec *old_value);

// Get timer
int timerfd_gettime(int fd, struct itimerspec *curr_value);

Features:

  • Timer as a file descriptor (pollable, epoll-able)
  • One-shot and periodic timers
  • Read returns number of expirations
  • TFD_NONBLOCK and TFD_CLOEXEC flags

Implementation Strategy

Phase 1: clock_nanosleep()

  1. Add SYS_CLOCK_NANOSLEEP to syscall table
  2. Implement sys_clock_nanosleep() handler
  3. Extend sleep queue to track clock source
  4. Support absolute vs relative time
  5. Add libc wrapper

Phase 2: timerfd

  1. Create timerfd file operations
  2. Implement timerfd_create() syscall
  3. Implement timerfd_settime()/gettime()
  4. Integrate with file descriptor table
  5. Support poll/select on timerfd
  6. Add libc wrappers

Files to Create/Modify

  • src/kernel/syscall/syscall.c - Add clock_nanosleep handler
  • src/kernel/time/sleep.c - Extend sleep queue for multiple clocks
  • src/kernel/fs/timerfd.c (new) - timerfd implementation
  • include/sys/timerfd.h (new) - timerfd userspace API
  • libc/src/time/clock_nanosleep.c (new)
  • test/test_clock_nanosleep.c (new)
  • test/test_timerfd.c (new)

Usage Examples

clock_nanosleep() absolute time

#include <time.h>

// Sleep until absolute time
struct timespec deadline;
clock_gettime(CLOCK_MONOTONIC, &deadline);
deadline.tv_sec += 5;  // 5 seconds from now

clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &deadline, NULL);

timerfd periodic timer

#include <sys/timerfd.h>

int tfd = timerfd_create(CLOCK_MONOTONIC, TFD_NONBLOCK);

struct itimerspec timer;
timer.it_value.tv_sec = 1;      // Initial expiration: 1 second
timer.it_value.tv_nsec = 0;
timer.it_interval.tv_sec = 1;   // Repeat every 1 second
timer.it_interval.tv_nsec = 0;

timerfd_settime(tfd, 0, &timer, NULL);

uint64_t expirations;
while (read(tfd, &expirations, sizeof(expirations)) > 0) {
    printf("Timer fired %llu times\n", expirations);
}

Testing

  • Absolute time sleep with TIMER_ABSTIME
  • clock_nanosleep() with different clocks
  • timerfd one-shot timers
  • timerfd periodic timers
  • timerfd with poll/select
  • Edge cases: past deadline, zero timeout
  • Interrupted sleep handling

Dependencies

  • #287 - nanosleep() and sleep queue (✅ complete)
  • #326 - Centralized timekeeper (new)
  • #96 - File descriptor management (✅ complete)

Parent Issue

  • #226 - RTC and time management

pbalduino avatar Oct 20 '25 15:10 pbalduino