SchOS/kernel/sys/sys_time.c
Nexoniarz a1c965da1e include: one folder per subsystem, and includes that name it
Sixty-five headers sat side by side in include/, so `#include "irq.h"`
said nothing about where irq.h was or what it belonged to, and errno.h,
stat.h and fcntl.h at the top shadowed the system's for any host tool
built with -I./include. They are in folders now -- arch/ core/ fs/
dev/ gfx/ net/ uapi/ (and ldls/ for the Linux driver layer) -- and
every include names the folder, as Linux's do: "core/proc.h".

Done mechanically and checked the hard way: the kernel built from this
tree disassembles identically to the one built from the tree before
it. The full image boots, and userland is the same set of programs.
Paths in docs and comments follow; docs/guides/layout.md has a table
of what is where, and tools/fix-includes.py rewrites old-style
includes from the folders in the tree, for code written before this.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01S1giNvrHTrPMPw7V6x1kQ4
2026-10-23 15:05:12 +02:00

139 lines
3.4 KiB
C

#include "core/types.h"
#include "core/defs.h"
#include "core/param.h"
#include "core/date.h"
#include "core/spinlock.h"
#include "core/proc.h"
#include "arch/x86.h"
#include "core/syscall.h"
#include "uapi/posix.h"
#include "core/uaccess.h"
#include "uapi/errno.h"
addr_t
sys_alarm(void)
{
int seconds;
if (argint(0, &seconds) < 0)
return -1;
myproc()->alarm_ticks = seconds * HZ;
return 0;
}
addr_t
sys_gettimeofday(void)
{
struct timeval *tv;
if (argptr(0, (char**)&tv, sizeof(*tv)) < 0)
return -1;
if (tv) {
// Real time, from the hardware clock read at boot plus uptime -- not
// uptime alone, which is what this used to return and why every machine
// thought it was 1970. See kernel/core/time.c.
uint64 sec, usec;
wallclock(&sec, &usec);
tv->tv_sec = (long)sec;
tv->tv_usec = (long)usec;
}
return 0;
}
addr_t
sys_nanosleep(void)
{
addr_t tsaddr, raw;
if (argaddr(0, &tsaddr) < 0 || fetchaddr(tsaddr, &raw) < 0)
return -1;
int64 sec = (int64)raw;
if (sec > 0) {
acquire(&tickslock);
uint t0 = ticks;
while (ticks - t0 < (uint)(sec * HZ)) {
if (myproc()->killed) { release(&tickslock); return -EINTR; }
sleep(&ticks, &tickslock);
}
release(&tickslock);
}
return 0;
}
addr_t
sys_clock_gettime(void)
{
int clkid;
struct timespec *tp;
argint(0, &clkid);
if (argptr(1, (char**)&tp, sizeof(*tp)) < 0)
return -1;
// CLOCK_MONOTONIC (1) counts from boot; everything else is treated as a
// realtime clock and counts from the epoch. Returning boot-relative values
// for CLOCK_REALTIME is what made timestamps land in 1970.
uint64 sec, usec;
wallclock(&sec, &usec);
if (clkid == 1)
sec -= boot_epoch;
tp->tv_sec = (long)sec;
tp->tv_nsec = (long)(usec * 1000);
return 0;
}
addr_t sys_getitimer(void) { return 0; } // stub
addr_t
sys_setitimer(void)
{
int which;
addr_t newp;
argint(0, &which); argaddr(1, &newp);
// We don't implement interval timers; just track the alarm if it's ITIMER_REAL.
if (which == 0 && newp) {
struct itimerval iv;
if (copy_from_user(&iv, newp, sizeof(iv)) == 0)
myproc()->alarm_ticks = (int)(iv.it_value.tv_sec * HZ +
iv.it_value.tv_usec / USEC_PER_TICK);
}
return 0;
}
addr_t
sys_time(void)
{
addr_t tloc;
argaddr(0, &tloc);
uint64 sec;
wallclock(&sec, 0);
long t = (long)sec;
if (tloc)
put_user(t, tloc);
return (addr_t)t;
}
addr_t
sys_clock_getres(void)
{
struct timespec *tp;
if (argptr(1, (char**)&tp, sizeof(*tp)) < 0) return 0;
if (tp) { tp->tv_sec = 0; tp->tv_nsec = 10000000L; } // 10ms resolution
return 0;
}
addr_t
sys_clock_nanosleep(void)
{
// Treat the same as nanosleep: arg2 is the timespec, arg1 is flags.
// Linux: clock_nanosleep(clockid, flags, rqtp, rmtp)
addr_t tsaddr, raw;
if (argaddr(2, &tsaddr) < 0 || fetchaddr(tsaddr, &raw) < 0)
return -1;
int64 sec = (int64)raw;
if (sec > 0) {
acquire(&tickslock);
uint t0 = ticks;
while (ticks - t0 < (uint)(sec * HZ)) {
if (myproc()->killed) { release(&tickslock); return -EINTR; }
sleep(&ticks, &tickslock);
}
release(&tickslock);
}
return 0;
}