Nucleus
Barry Per-CPU Scheduler bb0cb77 (3 years, 2 months ago)
diff --git a/include/nucleus/cpu.h b/include/nucleus/cpu.h
index f4d7175..2a8c52b 100644
--- a/include/nucleus/cpu.h
+++ b/include/nucleus/cpu.h
@@ -2,14 +2,20 @@
#define _NUCLEUS_CPU_H
#include <stdint.h>
+#include <stddef.h>
#include <nucleus/types.h>
typedef unsigned int cpu_t;
+typedef struct Processor Processor;
/* Structure for CPU specific data */
-struct CPUData {
+struct Processor {
+ Processor *self;
cpu_t id;
- Task *task;
+ uint32_t inCriticalSection;
+ uint32_t critFlags;
+ Scheduler *scheduler;
+ struct IPIQueue *ipiq;
};
/* Structure for an Interrupt Frame */
@@ -20,12 +26,22 @@ struct InterruptFrame {
uint32_t eip, cs, eflags, useresp, ss;
};
-typedef void (*exc_handler_t)(struct InterruptFrame *);
-typedef void (*int_handler_t)(struct InterruptFrame *);
+/* Flags for IPI Queue Messages */
+enum IPIQFlag {
+ IPIQ_ASYNC,
+ IPIQ_SYNC,
+ IPIQ_DONE,
+};
-extern struct CPUData __seg_gs *cpu;
+typedef void (*int_handler_t)(struct InterruptFrame *);
+typedef void (*ipiq_func_t)(void *);
+extern Processor __seg_gs *const cpu;
+extern Processor *cpus[];
+extern size_t ncpus;
extern int apic;
+#define for_each_cpu(c) for (cpu_t __i_ ## c = 0; ((c) = cpus[__i_ ## c]) && \
+ __i_ ## c < ncpus; __i_ ## c++)
extern uintptr_t lapicPtr, ioapicPtr;
#define LAPIC(off) (*((uint32_t *) ((uint32_t) lapicPtr + (off))))
@@ -35,8 +51,38 @@ extern cpu_t lapicNums[];
#define CPUID (apic ? lapicNums[(cpu_t) (LAPIC(0x20) >> 24)] : 0)
#define MAX_CPUS 2
-void register_exception(int num, exc_handler_t addr);
-void register_interrupt(int num, int_handler_t addr);
+/* Enter a critical section */
+static inline void
+enter_critical_section(void)
+{
+ uint32_t *ics = &cpu->self->inCriticalSection;
+ if (__atomic_fetch_add(ics, 1, __ATOMIC_RELAXED) == 0)
+ asm volatile (
+ "pushf;"
+ "cli;"
+ "pop %0"
+ : "=r" (cpu->critFlags)
+ : : "memory"
+ );
+}
+/* Exit a critical section */
+static inline void
+exit_critical_section(void)
+{
+ uint32_t *ics = &cpu->self->inCriticalSection;
+ if (__atomic_sub_fetch(ics, 1, __ATOMIC_RELAXED) == 0)
+ asm volatile (
+ "push %0;"
+ "popf"
+ : : "rm" (cpu->critFlags)
+ : "memory","cc"
+ );
+}
+
+void register_exception(uint8_t num, int_handler_t addr);
+void register_interrupt(uint8_t num, int_handler_t addr);
+void register_ipi(uint8_t num, int_handler_t addr);
+void send_ipiq(cpu_t targid, ipiq_func_t func, void *arg, enum IPIQFlag flags);
void set_fs_base(uintptr_t base);
void set_gs_base(uintptr_t base);
diff --git a/include/nucleus/object.h b/include/nucleus/object.h
index 9683410..70e7bc1 100644
--- a/include/nucleus/object.h
+++ b/include/nucleus/object.h
@@ -49,6 +49,7 @@ struct Object {
enum ListMode {
LIST_NORMAL,
LIST_ORDERED,
+ LIST_LOCKLESS,
};
int check(void *addr);
@@ -80,6 +81,6 @@ void *prev(Iterator *iter);
int done_iterating(Iterator *iter);
#define foreach(l,i) for (Iterator *(__l_ ## i) = iterate(l); (__l_ ## i); \
done_iterating(__l_ ## i), (__l_ ## i) = NULL) \
- for (i = first(__l_ ## i); i; i = next(__l_ ## i))
+ for ((i) = first(__l_ ## i); (i); (i) = next(__l_ ## i))
#endif
diff --git a/include/nucleus/task.h b/include/nucleus/task.h
index 80a2a71..6212be0 100644
--- a/include/nucleus/task.h
+++ b/include/nucleus/task.h
@@ -18,6 +18,7 @@ enum Priority {
HIGH,
HIGHEST,
};
+#define PRIORITY_COUNT 6
/* Task states */
enum State {
@@ -34,11 +35,11 @@ struct Task {
uid_t uid, euid, suid;
gid_t gid, egid, sgid;
int status;
- enum Priority priority;
- enum State state;
- uint32_t inCriticalSection;
uint32_t inSyscall;
+ Scheduler *scheduler;
+ enum Priority priority;
+ enum State state;
uintptr_t esi, edi, ebx;
uintptr_t esp, ebp, eip;
page_dir_t pageDir;
@@ -55,9 +56,20 @@ struct Task {
Signals *signals;
};
-#define current cpu->task
+/* Structure for a Scheduler */
+struct Scheduler {
+ Object obj;
+ Processor *cpu;
+ Task *task;
+ ObjectList *queue[PRIORITY_COUNT];
+ uint32_t timeslice;
+ size_t tasks;
+};
+
+#define current cpu->scheduler->task
extern ObjectType taskType;
+extern ObjectType schedulerType;
extern ObjectType signalsType;
/* Check if super-user */
@@ -67,24 +79,11 @@ super_user(void)
return (current->euid == 0);
}
-/* Enter a critical section */
-static inline void
-enter_critical_section(void)
-{
- __atomic_add_fetch(¤t->inCriticalSection, 1, __ATOMIC_RELAXED);
-}
-/* Exit a critical section */
-static inline void
-exit_critical_section(void)
-{
- __atomic_sub_fetch(¤t->inCriticalSection, 1, __ATOMIC_RELAXED);
-}
-
/* Enter system call context */
static inline void
-enter_syscall_context(uint32_t syscall)
+enter_syscall_context(void)
{
- current->inSyscall = syscall;
+ current->inSyscall = 1;
}
/* Exit system call context */
static inline uint32_t
@@ -96,6 +95,7 @@ exit_syscall_context(void)
}
void init_tasking(void);
+void enqueue_task(Task *task);
void block_task(enum State reason, ObjectList *list);
void unblock_task(Task *task);
Task *find_task(pid_t tid);
diff --git a/include/nucleus/types.h b/include/nucleus/types.h
index d64d543..35132d8 100644
--- a/include/nucleus/types.h
+++ b/include/nucleus/types.h
@@ -11,6 +11,7 @@ typedef struct VMRegion VMRegion;
/* Task */
typedef struct Task Task;
+typedef struct Scheduler Scheduler;
typedef struct Signals Signals;
/* VFS */