Files
CervusOS/kernel/include/sched/sched.h
T
alexvoste 1a9fd27a31 push
2026-05-07 02:22:25 +03:00

184 lines
4.9 KiB
C

#ifndef TASK_H
#define TASK_H
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "capabilities.h"
#include "../memory/vmm.h"
#include "../smp/smp.h"
#ifndef __ATOMIC_RELAXED
#define __ATOMIC_RELAXED 0
#define __ATOMIC_ACQUIRE 2
#define __ATOMIC_RELEASE 3
#endif
typedef struct { volatile bool _val; } atomic_bool;
static inline void atomic_init_bool(atomic_bool *a, bool v) {
__atomic_store_n(&a->_val, v, __ATOMIC_RELAXED);
}
static inline bool atomic_load_bool_acq(const atomic_bool *a) {
return __atomic_load_n(&a->_val, __ATOMIC_ACQUIRE);
}
static inline void atomic_store_bool_rel(atomic_bool *a, bool v) {
__atomic_store_n(&a->_val, v, __ATOMIC_RELEASE);
}
static inline bool atomic_cas_bool(atomic_bool *a, bool *expected, bool desired) {
return __atomic_compare_exchange_n(
&a->_val, expected, desired,
false, __ATOMIC_ACQUIRE, __ATOMIC_RELAXED);
}
typedef struct fd_table fd_table_t;
typedef struct {
uint8_t data[512] __attribute__((aligned(16)));
} fpu_state_t;
typedef enum {
TASK_RUNNING = 0,
TASK_READY,
TASK_BLOCKED,
TASK_ZOMBIE,
TASK_DEAD,
} task_state_t;
typedef enum {
TASK_TYPE_KERNEL = 0,
TASK_TYPE_USER = 1,
} task_type_t;
#define MAX_PRIORITY 31
#define DEFAULT_PRIORITY 16
#define TASK_DEFAULT_TIMESLICE 10
typedef struct task {
uint64_t rsp;
uint64_t rip;
uint64_t rbp_save;
uint64_t cr3;
int priority;
bool runnable;
uint8_t is_userspace;
uint8_t _pad0[2];
uint32_t cpu_id;
char name[32];
uint32_t time_slice;
uint32_t time_slice_init;
uint8_t _pad1[4];
uint64_t total_runtime;
fpu_state_t* fpu_state;
bool fpu_used;
uint8_t _pad2[3];
uint32_t last_cpu;
uint64_t cpu_affinity;
void (*entry)(void*);
void *arg;
uintptr_t stack_base;
uint64_t user_rsp;
task_state_t state;
uint8_t _pad3[4];
struct task* next;
uint32_t pid;
uint32_t ppid;
uint32_t uid;
uint32_t gid;
uint64_t capabilities;
struct task* parent;
struct task* children;
struct task* sibling;
int exit_code;
volatile bool pending_kill;
uint8_t _pad4[3];
uintptr_t brk_start;
uintptr_t brk_current;
uintptr_t brk_max;
vmm_pagemap_t* pagemap;
uint32_t flags;
uint32_t wait_for_pid;
uint64_t wakeup_time_ns;
uint64_t user_saved_rip;
uint64_t user_saved_rbp;
uint64_t user_saved_rbx;
uint64_t user_saved_r12;
uint64_t user_saved_r13;
uint64_t user_saved_r14;
uint64_t user_saved_r15;
uint64_t user_saved_r11;
fd_table_t *fd_table;
atomic_bool on_cpu;
} task_t;
#define TASK_FLAG_TRACE (1 << 0)
#define TASK_FLAG_VFORK (1 << 1)
#define TASK_FLAG_FORK (1 << 2)
#define TASK_FLAG_STARTED (1 << 3)
#define TASK_FLAG_OWN_PAGEMAP (1 << 4)
#define TASK_FLAG_STACK_DEFERRED (1 << 5)
#define TASK_FLAG_DESTROYED (1U << 31)
_Static_assert(offsetof(task_t, rsp) == 0, "task_t: rsp");
_Static_assert(offsetof(task_t, entry) == 120, "task_t: entry — update TASK_ENTRY_OFFSET");
_Static_assert(offsetof(task_t, arg) == 128, "task_t: arg — update TASK_ARG_OFFSET");
_Static_assert(offsetof(task_t, stack_base) == 136, "task_t: stack_base");
_Static_assert(offsetof(task_t, user_rsp) == 144, "task_t: user_rsp — update TASK_USER_RSP_OFFSET");
_Static_assert(offsetof(task_t, user_saved_rip) == 272, "task_t: user_saved_rip");
_Static_assert(offsetof(task_t, user_saved_rbp) == 280, "task_t: user_saved_rbp — update TASK_USER_SAVED_RBP_OFFSET");
extern task_t* ready_queues[MAX_PRIORITY + 1];
extern task_t* current_task[MAX_CPUS];
void sched_init(void);
void sched_reschedule(void);
void sched_print_stats(void);
void task_yield(void);
task_t* task_create(const char* name, void (*entry)(void*), void* arg, int priority);
task_t* task_create_user(const char* name, uintptr_t entry, uintptr_t user_rsp, uint64_t cr3, int priority, vmm_pagemap_t* pagemap, uint32_t uid, uint32_t gid);
__attribute__((noreturn)) void task_exit(void);
void task_kill(task_t* task);
void task_destroy(task_t* task);
task_t* task_fork(task_t* parent);
task_t* task_find_by_pid(uint32_t pid);
uint32_t task_alloc_pid(void);
void task_reparent(task_t* child, task_t* new_parent);
#include "spinlock.h"
extern spinlock_t children_lock;
void task_wakeup_waiters(uint32_t pid);
void task_unblock(task_t* t);
void sched_wakeup_sleepers(uint64_t now_ns);
task_t* task_find_foreground(void);
extern volatile uint32_t g_foreground_pid;
void task_set_foreground(uint32_t pid);
extern void context_switch(task_t* old, task_t* next, task_t** current_task_slot, uint64_t new_cr3);
extern void first_task_start(task_t* task);
extern void task_trampoline(void);
extern void task_trampoline_user(void);
extern void task_trampoline_fork(void);
extern void fpu_save(fpu_state_t* state);
extern void fpu_restore(fpu_state_t* state);
#endif