diff --git a/sortix/Makefile b/sortix/Makefile
index 487c4154..eb99894f 100644
--- a/sortix/Makefile
+++ b/sortix/Makefile
@@ -93,6 +93,7 @@ HEADERS:=$(shell find include -type f)
OBJS=$(CPUOBJS) \
kernel.o \
interrupt.o \
+worker.o \
time.o \
log.o \
utf8.o \
diff --git a/sortix/include/sortix/kernel/worker.h b/sortix/include/sortix/kernel/worker.h
new file mode 100644
index 00000000..23aa741b
--- /dev/null
+++ b/sortix/include/sortix/kernel/worker.h
@@ -0,0 +1,39 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of Sortix.
+
+ Sortix is free software: you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+ Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ Sortix. If not, see .
+
+ worker.h
+ Kernel worker thread.
+
+*******************************************************************************/
+
+#ifndef SORTIX_WORKER_H
+#define SORTIX_WORKER_H
+
+namespace Sortix {
+namespace Worker {
+
+void Init();
+void Schedule(void (*func)(void*), void* user = NULL);
+bool TrySchedule(void (*func)(void*), void* user = NULL);
+void Thread(void* user = NULL);
+
+} // namespace Worker
+} // namespace Sortix
+
+#endif
diff --git a/sortix/worker.cpp b/sortix/worker.cpp
new file mode 100644
index 00000000..51163042
--- /dev/null
+++ b/sortix/worker.cpp
@@ -0,0 +1,107 @@
+/*******************************************************************************
+
+ Copyright(C) Jonas 'Sortie' Termansen 2012.
+
+ This file is part of Sortix.
+
+ Sortix is free software: you can redistribute it and/or modify it under the
+ terms of the GNU General Public License as published by the Free Software
+ Foundation, either version 3 of the License, or (at your option) any later
+ version.
+
+ Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
+ WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+ FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
+ details.
+
+ You should have received a copy of the GNU General Public License along with
+ Sortix. If not, see .
+
+ worker.cpp
+ Kernel worker thread.
+
+*******************************************************************************/
+
+#include
+#include
+#include
+
+namespace Sortix {
+namespace Worker {
+
+struct Job
+{
+ void (*func)(void*);
+ void* user;
+};
+
+static kthread_mutex_t jobslock;
+static kthread_cond_t jobsready;
+static kthread_cond_t jobsfree;
+static size_t jobsused;
+static size_t jobsoff;
+static size_t jobslen;
+static Job* jobs;
+
+void Init()
+{
+ jobslock = KTHREAD_MUTEX_INITIALIZER;
+ jobsready = KTHREAD_COND_INITIALIZER;
+ jobsfree = KTHREAD_COND_INITIALIZER;
+ const size_t NUM_JOBS = 128UL;
+ jobslen = NUM_JOBS;
+ jobs = new Job[jobslen];
+ if ( !jobs )
+ Panic("Unable to allocate worker thread job queue");
+ jobsused = 0;
+ jobsoff = 0;
+}
+
+static bool _Schedule(void (*func)(void*), void* user, bool retry)
+{
+ ScopedLock lock(&jobslock);
+ if ( jobsused == jobslen && !retry )
+ return false;
+ while ( jobsused == jobslen )
+ kthread_cond_wait(&jobsfree, &jobslock);
+ if ( !jobsused )
+ kthread_cond_signal(&jobsready);
+ size_t index = (jobsoff + jobsused++) % jobslen;
+ jobs[index].func = func;
+ jobs[index].user = user;
+ return true;
+}
+
+void Schedule(void (*func)(void*), void* user)
+{
+ _Schedule(func, user, true);
+}
+
+bool TrySchedule(void (*func)(void*), void* user)
+{
+ return _Schedule(func, user, false);
+}
+
+static void PerformJob(Job* job)
+{
+ job->func(job->user);
+}
+
+void Thread(void* /*user*/)
+{
+ while ( true )
+ {
+ kthread_mutex_lock(&jobslock);
+ while ( !jobsused )
+ kthread_cond_wait(&jobsready, &jobslock);
+ Job job = jobs[jobsoff];
+ jobsoff = (jobsoff+1) % jobslen;
+ if ( jobsused-- == jobslen )
+ kthread_cond_signal(&jobsfree);
+ kthread_mutex_unlock(&jobslock);
+ PerformJob(&job);
+ }
+}
+
+} // namespace Worker
+} // namespace Sortix