AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
sched.c
Go to the documentation of this file.
1
5
6#include <core/arch.h>
7#include <core/platform.h>
8#include <core/time.h>
9#include <mm/mm.h>
10#include <sys/proc.h>
11#include <sys/sched.h>
12#include <sys/lock.h>
13
14#include "sys.h"
15#include <platform/misc.h>
16
19
20/*
21 * Reads the CPU's cycle counter, the TSC, for randomness.
22 */
24{
25 uint32_t lo, hi;
26 asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
27 return ((uint64_t) hi << 32) | lo;
28}
29
33static void x86_sched_handler(void *arg __unused)
34{
35 struct x86_regs *r = curcpu()->arch.irq_regs;
36
37 if (curcpu()->id) {
38 sched_cpu_tick(timer_period, (r->cs & 3) == 3);
40 return;
41 }
42
43 /* set the wall clock from the real time clock again, every 2^16 ticks
44 * (about 2 minutes) */
45 if (timer_ticks && !(timer_ticks & 0xFFFF))
47
50 sched_timer_tick(timer_period, (r->cs & 3) == 3);
51
52 /* the running thread goes back to the ready list (with all its
53 * registers saved), once the controller is done with the interrupt
54 * (irq.c) */
56}
57
58/* Starts the clock and the tick, and wakes up the other CPUs to start
59 * theirs. */
61{
62 /* first the clock (the TSC or the HPET, else the ticks), then the
63 * tick, because the local APIC's timer is calibrated against the
64 * clock */
68
69 /* the other CPUs start their ticks when they are woken up */
70 for (int i = 1; i < cpus_count; ++i)
72}
73
76static void __arch_idle(void)
77{
78 if (kernel_lock_held())
80
81 for (;;) {
82 asm volatile("sti; hlt; cli;");
83 }
84}
85
86/* Makes the running CPU idle, on its idle stack. It doesn't return. */
87void arch_idle(void)
88{
90
91 uintptr_t esp = VMA(0x100000);
93 uintptr_t stack = curcpu()->arch.idle_stack;
94 extern void x86_goto(uintptr_t eip, uintptr_t ebp, uintptr_t esp) __attribute__((noreturn));
95 x86_goto((uintptr_t) __arch_idle, stack, stack);
96}
97
99static void __arch_cur_thread_kill(void)
100{
101 /* A thread that called thread_exit() is a zombie already: it stays
102 * on its process's list of threads, and is freed by thread_join(),
103 * or when the process exits. Otherwise the process is exiting, and
104 * proc_kill() took the thread off the list already. */
105 int keep = curthread->state == ZOMBIE;
106
108
109 if (!keep)
111
112 curthread = NULL;
113 kernel_idle();
114}
115
116/* Ends the current thread. Its kernel stack is freed, so this switches
117 * to the CPU's idle stack first. It doesn't return. */
119{
120 uintptr_t stack = curcpu()->arch.idle_stack;
121
122 extern void x86_goto(uintptr_t eip, uintptr_t ebp, uintptr_t esp) __attribute__((noreturn));
124}
125
126/* Puts the current thread at the end of the ready list, and runs the
127 * next one. */
128void arch_yield(void)
129{
130 extern void x86_preempt(void);
131 x86_preempt();
132}
133
134/* Switches away from the current thread, which sleeps: the next ready
135 * thread runs, or the CPU idles. It returns when the thread runs again. */
136void arch_sleep(void)
137{
138 extern void x86_sleep(void);
139 x86_sleep();
140}
void arch_cpu_kick(struct cpu *cpu)
Makes another CPU enter the kernel now, with an inter-processor interrupt: to run a thread that just ...
Definition smp.c:14
#define VMA(obj)
Definition mm.h:36
void arch_yield(void)
Puts the current thread at the end of the ready list, and runs the next ready thread.
Definition sched.c:94
void arch_idle(void)
Makes this CPU idle, on its idle stack, until an interrupt makes a thread ready.
Definition sched.c:62
static uint64_t timer_period
Definition sched.c:19
static void __arch_idle(void)
Runs the idle loop, on the CPU's idle stack.
Definition sched.c:51
void arch_sleep(void)
Puts the current thread to sleep.
Definition sched.c:101
static void __arch_cur_thread_kill(void)
Frees the running thread, from the CPU's idle stack, and idles.
Definition sched.c:69
void arch_cur_thread_kill(void)
Ends the current thread.
Definition sched.c:87
void arch_sched_init(void)
Starts the timer tick on every CPU, and the clock where it needs to be started.
Definition sched.c:43
static uint64_t timer_ticks
Definition sched.c:20
void x86_goto(uintptr_t eip, uintptr_t ebp, uintptr_t esp)
uint32_t platform_timer_setup(size_t period_ns, irq_handler_t handler)
Starts the scheduler's tick: the local APIC's timer if the APIC brings the interrupts,...
Definition init.c:84
static void x86_sched_handler(void *arg)
Handles the tick, on every CPU: it charges the running process, asks for a thread switch,...
Definition sched.c:33
void x86_clock_ticks(uint32_t period_ns)
Says how often the timer ticks, from now on: with neither TSC nor HPET, the ticks are the clock.
Definition clock.c:180
void x86_clock_init(void)
Chooses the clock's counter and calibrates it, at boot, before the timer ticks.
Definition clock.c:200
void x86_clock_tick(void)
Counts a tick of the timer, and moves the clock's base on to now.
Definition clock.c:130
void x86_kernel_stack_set(uintptr_t sp)
Sets the kernel stack that interrupts from user mode switch to, on the running CPU: the thread that i...
Definition gdt.c:152
struct cpu cpus[CPUS_MAX]
Definition sched.c:28
int cpus_count
Definition sched.c:29
void kfree(void *)
Frees an object that kmalloc() gave.
Definition kvmem.c:146
void kernel_unlock(void)
Lets go of the kernel lock, for the next CPU waiting for it.
Definition lock.c:46
int kernel_lock_held(void)
Says whether this CPU holds the kernel lock.
Definition lock.c:57
void x86_irq_tick_switch(void)
Asks for a thread switch once the current interrupt is done: the tick calls it.
Definition irq.c:169
void sched_cpu_tick(uint32_t period, int user)
Charges a timer tick to the process that was running on this CPU.
Definition sched.c:54
void kernel_idle(void)
Gives up the CPU when the current thread can't run anymore (it sleeps, or it exited): the next ready ...
Definition sched.c:332
#define curthread
Definition sched.h:12
void sched_timer_tick(uint32_t period, int user)
Runs the boot CPU's timer tick.
Definition sched.c:74
#define NULL
Definition stddef.h:27
__SIZE_TYPE__ uintptr_t
Definition stddef.h:12
unsigned int uint32_t
Definition stddef.h:22
unsigned long long int uint64_t
Definition stddef.h:23
The registers an interrupt or exception saved, on the kernel stack, as cpu.S's stubs push them: the g...
Definition cpu.h:12
uint64_t cs
Definition cpu.h:24
int thread_kill(struct thread *thread)
Releases what a thread holds (its poll() registrations, its CPU state and kernel stack) and makes it ...
Definition thread.c:59
@ ZOMBIE
Definition thread.h:19
void time_resync(void)
Sets the wall clock from the real time clock again, if they are 2 seconds or more apart.
Definition time.c:54
uint64_t arch_cycles(void)
Reads a counter that changes as fast as the CPU runs, which the kernel uses as a source of randomness...
Definition timer.c:82