An x86-64 operating system built from xv6, now largely rewritten: SMP, a copy-on-write root filesystem (SchFS), PCI/USB/virtio drivers, a TTF rasteriser, and a Linux-numbered syscall ABI. No history before this point -- the tree was never under version control. This commit exists so the rename that follows has something to undo to.
139 lines
3.3 KiB
C
139 lines
3.3 KiB
C
#include "types.h"
|
|
#include "defs.h"
|
|
#include "param.h"
|
|
#include "date.h"
|
|
#include "spinlock.h"
|
|
#include "proc.h"
|
|
#include "x86.h"
|
|
#include "syscall.h"
|
|
#include "posix.h"
|
|
#include "uaccess.h"
|
|
#include "errno.h"
|
|
|
|
addr_t
|
|
sys_alarm(void)
|
|
{
|
|
int seconds;
|
|
if (argint(0, &seconds) < 0)
|
|
return -1;
|
|
myproc()->alarm_ticks = seconds * 100;
|
|
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 * 100)) {
|
|
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 * 100 +
|
|
iv.it_value.tv_usec / 10000);
|
|
}
|
|
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 * 100)) {
|
|
if (myproc()->killed) { release(&tickslock); return -EINTR; }
|
|
sleep(&ticks, &tickslock);
|
|
}
|
|
release(&tickslock);
|
|
}
|
|
return 0;
|
|
}
|