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