Add synchornization primitives, `waiting` to task
diff --git a/include/kernel/sync.h b/include/kernel/sync.h
new file mode 100644
index 0000000..3fbe209
--- /dev/null
+++ b/include/kernel/sync.h
@@ -0,0 +1,23 @@
+#pragma once
+
+#include <kint.h>
+
+// Synchronization primitives
+
+/// Spinlock
+typedef volatile int spinlock_t;
+
+void sl_acquire(spinlock_t *sl);
+void sl_release(spinlock_t *sl);
+spinlock_t sl_new();
+
+/// Semaphore
+typedef volatile int semaphore_t;
+
+void sm_wait(semaphore_t sm);
+void sm_signal(semaphore_t sm);
+semaphore_t sm_new();
+
+/// Initialize synchronization primitives, only call this once after the
+/// scheduler has been initialized.
+void init_sync();
diff --git a/include/kernel/task.h b/include/kernel/task.h
index b0d0f97..83e7fd0 100644
--- a/include/kernel/task.h
+++ b/include/kernel/task.h
@@ -29,6 +29,8 @@
 struct task
 {
 	int id;
+	/// Is this task waiting for I/O?
+	bool waiting;
 	struct process *proc;
 	/// Physical address of the top of the stack.
 	uint stack_top_p;
@@ -60,6 +62,8 @@
 
 void spawn_thread(task_function_t function, void *data);
 
+void set_waiting(int tid, bool waiting);
+
 /**
  * Halt the current thread.
  */
diff --git a/include/sys.h b/include/sys.h
new file mode 100644
index 0000000..0a7044e
--- /dev/null
+++ b/include/sys.h
@@ -0,0 +1,16 @@
+#pragma once
+
+// Bluejay System Calls
+
+#define SYS_GIVEUP 0x100
+
+/// Bluejay interrupt number
+#define SYS_INT 0x80
+
+/**
+ * @brief Gives up the current threads remaining CPU time. Unless you have set
+ * the thread to waiting, it will resume next time the scheduler decides it's
+ * its turn. The behaviour is identical to if the thread had just run out of
+ * time naturally.
+ */
+extern void sys_giveup();