BarryServer : Git

All the code for all my projects
// BarryServer : Git / Nucleus / commit / bb0cb7718204df7c0cbaf87484b1def3c4b2880f / include

// Related

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(&current->inCriticalSection, 1, __ATOMIC_RELAXED);
-}
-/* Exit a critical section */
-static inline void
-exit_critical_section(void)
-{
-	__atomic_sub_fetch(&current->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 */