mirror of
https://github.com/Mathewnd/Astral.git
synced 2026-10-27 12:48:22 +00:00
syscalls: fchdir, setitimer, getitimer
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
#include <kernel/itimer.h>
|
||||
#include <logging.h>
|
||||
|
||||
static void itimer_dpc(context_t *context, dpcarg_t arg) {
|
||||
itimer_t *itimer = arg;
|
||||
spinlock_acquire(&itimer->lock);
|
||||
if (itimer->paused)
|
||||
goto leave;
|
||||
|
||||
itimer->remainingus = itimer->repeatus ? itimer->repeatus : 0;
|
||||
itimer->paused = itimer->repeatus == 0;
|
||||
itimer->fn(context, itimer->arg);
|
||||
if (itimer->repeatus) {
|
||||
timer_insert(_cpu()->timer, &itimer->entry, itimer_dpc, itimer, itimer->remainingus, false);
|
||||
}
|
||||
|
||||
leave:
|
||||
spinlock_release(&itimer->lock);
|
||||
}
|
||||
|
||||
void itimer_init(itimer_t *itimer, dpcfn_t fn, dpcarg_t arg) {
|
||||
memset(itimer, 0, sizeof(itimer_t));
|
||||
itimer->fn = fn;
|
||||
itimer->arg = arg;
|
||||
itimer->paused = true;
|
||||
SPINLOCK_INIT(itimer->lock);
|
||||
}
|
||||
|
||||
void itimer_pause(itimer_t *itimer, uintmax_t *remainingus, uintmax_t *repeatus) {
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
|
||||
while (itimer->cpu && itimer->cpu != _cpu()) {
|
||||
// schedule on the itimer cpu
|
||||
sched_targetcpu(itimer->cpu);
|
||||
spinlock_release(&itimer->lock);
|
||||
sched_yield();
|
||||
sched_targetcpu(NULL);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
}
|
||||
|
||||
if (itimer->paused)
|
||||
goto cleanup;
|
||||
|
||||
itimer->cpu = NULL;
|
||||
itimer->remainingus = timer_remove(_cpu()->timer, &itimer->entry);
|
||||
if (itimer->remainingus == 0) {
|
||||
// while we were running in the cpu, the timer fired.
|
||||
// the dpc won't be handled because the timer entry
|
||||
// has already been removed from the queue.
|
||||
// this will be handled as a ''timer was one microsecond away from firing''
|
||||
// situation as its the cleanest way of doing this.
|
||||
itimer->remainingus = 1;
|
||||
}
|
||||
itimer->paused = true;
|
||||
cleanup:
|
||||
|
||||
spinlock_release(&itimer->lock);
|
||||
interrupt_set(intstatus);
|
||||
if (remainingus)
|
||||
*remainingus = itimer->remainingus;
|
||||
if (repeatus)
|
||||
*repeatus = itimer->repeatus;
|
||||
}
|
||||
|
||||
void itimer_set(itimer_t *itimer, uintmax_t timerus, uintmax_t repeatus) {
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
|
||||
itimer->remainingus = timerus;
|
||||
itimer->repeatus = repeatus;
|
||||
|
||||
spinlock_release(&itimer->lock);
|
||||
interrupt_set(intstatus);
|
||||
}
|
||||
|
||||
void itimer_resume(itimer_t *itimer) {
|
||||
bool intstatus = interrupt_set(false);
|
||||
spinlock_acquire(&itimer->lock);
|
||||
|
||||
__assert(itimer->paused && itimer->remainingus);
|
||||
itimer->cpu = _cpu();
|
||||
itimer->paused = false;
|
||||
timer_insert(_cpu()->timer, &itimer->entry, itimer_dpc, itimer, itimer->remainingus, false);
|
||||
|
||||
spinlock_release(&itimer->lock);
|
||||
interrupt_set(intstatus);
|
||||
}
|
||||
Reference in New Issue
Block a user