diff options
author | Patrick Williams <iawillia@us.ibm.com> | 2010-06-11 21:40:31 -0500 |
---|---|---|
committer | Patrick Williams <iawillia@us.ibm.com> | 2010-06-11 21:40:31 -0500 |
commit | 24e81bc664f5cdbfc8be1badf00b025ec122af00 (patch) | |
tree | 2d41e3305fb903024541d105dfec6adf1824839a /src | |
parent | 165e6bed506f9fddd7e9da8ad1f4c7f186e29b00 (diff) | |
download | talos-hostboot-24e81bc664f5cdbfc8be1badf00b025ec122af00.tar.gz talos-hostboot-24e81bc664f5cdbfc8be1badf00b025ec122af00.zip |
Add mutex userspace / syscalls.
Diffstat (limited to 'src')
-rw-r--r-- | src/include/kernel/syscalls.H | 5 | ||||
-rw-r--r-- | src/include/kernel/usermutex.H | 16 | ||||
-rw-r--r-- | src/include/sys/mutex.h | 20 | ||||
-rw-r--r-- | src/include/sys/task.h | 8 | ||||
-rw-r--r-- | src/include/util/locked/lock.H | 20 | ||||
-rw-r--r-- | src/include/util/locked/queue.H | 33 | ||||
-rw-r--r-- | src/kernel/syscall.C | 66 | ||||
-rw-r--r-- | src/lib/makefile | 2 | ||||
-rw-r--r-- | src/lib/syscall_mutex.C | 33 | ||||
-rw-r--r-- | src/lib/syscall_task.C | 9 | ||||
-rw-r--r-- | src/sys/init/init_main.C | 9 |
11 files changed, 204 insertions, 17 deletions
diff --git a/src/include/kernel/syscalls.H b/src/include/kernel/syscalls.H index 826ac93b9..ebe7d0059 100644 --- a/src/include/kernel/syscalls.H +++ b/src/include/kernel/syscalls.H @@ -10,6 +10,11 @@ namespace Systemcalls TASK_END, TASK_GETTID, + MUTEX_CREATE, + MUTEX_DESTROY, + MUTEX_LOCK_CONTESTED, + MUTEX_UNLOCK_CONTESTED, + SYSCALL_MAX }; }; diff --git a/src/include/kernel/usermutex.H b/src/include/kernel/usermutex.H new file mode 100644 index 000000000..3dcd904b4 --- /dev/null +++ b/src/include/kernel/usermutex.H @@ -0,0 +1,16 @@ +#ifndef __KERNEL_USERMUTEX_H +#define __KERNEL_USERMUTEX_H + +#include <util/locked/queue.H> +#include <kernel/spinlock.H> +#include <kernel/task.H> + +struct UserMutex +{ + uint64_t value; + bool unlock_pend; + Spinlock lock; + Util::Locked::Queue<task_t> waiting; +}; + +#endif diff --git a/src/include/sys/mutex.h b/src/include/sys/mutex.h new file mode 100644 index 000000000..3eca65f06 --- /dev/null +++ b/src/include/sys/mutex.h @@ -0,0 +1,20 @@ +#ifndef __SYS_MUTEX_H +#define __SYS_MUTEX_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef void* mutex_t; + +mutex_t mutex_create(); +int mutex_destroy(mutex_t); + +int mutex_lock(mutex_t); +int mutex_unlock(mutex_t); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/src/include/sys/task.h b/src/include/sys/task.h index 84ddb10f9..fa9838723 100644 --- a/src/include/sys/task.h +++ b/src/include/sys/task.h @@ -1,18 +1,20 @@ #ifndef __SYS_TASK_H #define __SYS_TASK_H -#include <sys/syscall.h> +#include <stdint.h> #ifdef __cplusplus extern "C" { #endif +typedef uint64_t tid_t; + void task_yield(); -int task_create(void(*)(void*), void*); +tid_t task_create(void(*)(void*), void*); void task_end(); -uint64_t task_gettid(); +tid_t task_gettid(); #ifdef __cplusplus } diff --git a/src/include/util/locked/lock.H b/src/include/util/locked/lock.H index b5237276e..05da95900 100644 --- a/src/include/util/locked/lock.H +++ b/src/include/util/locked/lock.H @@ -14,6 +14,26 @@ namespace Util virtual void lock() = 0; virtual void unlock() = 0; }; + + template<bool _locked, typename _T> + class LockHelper + { + public: + inline LockHelper(_T& i) : l(i) {}; + inline void lock() { l.lock(); }; + inline void unlock() { l.unlock(); }; + private: + _T& l; + }; + + template<typename _T> + class LockHelper<false,_T> + { + public: + inline LockHelper(_T&i) {}; + inline void lock() {}; + inline void unlock() {}; + }; }; }; diff --git a/src/include/util/locked/queue.H b/src/include/util/locked/queue.H index 2f230819e..51d2c430e 100644 --- a/src/include/util/locked/queue.H +++ b/src/include/util/locked/queue.H @@ -1,6 +1,8 @@ #ifndef __UTIL_LOCKED_QUEUE_H #define __UTIL_LOCKED_QUEUE_H +#include <util/locked/lock.H> + namespace Util { namespace Locked @@ -21,6 +23,9 @@ namespace Util _S lock; + void __lock(); + void __unlock(); + }; template <typename _T, bool locked, typename _S> @@ -28,8 +33,7 @@ namespace Util { _T* item = NULL; - if (locked) - lock.lock(); + __lock(); if (tail != NULL) { @@ -40,17 +44,15 @@ namespace Util tail = item->prev; } - if (locked) - lock.unlock(); - + __unlock(); + return item; } template <typename _T, bool locked, typename _S> void Queue<_T,locked,_S>::insert(_T* item) { - if (locked) - lock.lock(); + __lock(); if (head == NULL) { @@ -63,10 +65,23 @@ namespace Util item->next = head; head = head->prev = item; } + + __unlock(); + } - if (locked) - lock.unlock(); + template <typename _T, bool locked, typename _S> + void Queue<_T,locked,_S>::__lock() + { + Util::Locked::LockHelper<locked,_S>(lock).lock(); + } + + template <typename _T, bool locked, typename _S> + void Queue<_T,locked,_S>::__unlock() + { + Util::Locked::LockHelper<locked,_S>(lock).unlock(); } + + }; }; diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index b993bf222..ce26970c7 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -6,6 +6,7 @@ #include <kernel/syscalls.H> #include <kernel/console.H> #include <kernel/pagemgr.H> +#include <kernel/usermutex.H> extern "C" void kernel_execute_decrementer() @@ -26,6 +27,10 @@ namespace Systemcalls void TaskStart(task_t*); void TaskEnd(task_t*); void TaskGettid(task_t*); + void MutexCreate(task_t*); + void MutexDestroy(task_t*); + void MutexLockCont(task_t*); + void MutexUnlockCont(task_t*); syscall syscalls[] = { @@ -33,6 +38,11 @@ namespace Systemcalls &TaskStart, &TaskEnd, &TaskGettid, + + &MutexCreate, + &MutexDestroy, + &MutexLockCont, + &MutexUnlockCont, }; }; @@ -103,4 +113,60 @@ namespace Systemcalls { TASK_SETRTN(t, t->tid); } + + void MutexCreate(task_t* t) + { + UserMutex * m = new UserMutex(); + TASK_SETRTN(t, (uint64_t)m); + } + + void MutexDestroy(task_t* t) + { + // TODO: Extra verification of parameter and mutex state. + + delete (UserMutex*) TASK_GETARG0(t); + TASK_SETRTN(t, 0); + } + + void MutexLockCont(task_t* t) + { + // TODO: Extra verification of parameter and mutex state. + + UserMutex* m = (UserMutex*) TASK_GETARG0(t); + m->lock.lock(); + if (m->unlock_pend) + { + // We missed the unlock syscall, take lock and return to userspace. + m->unlock_pend = false; + m->lock.unlock(); + + } + else + { + // Queue ourself to wait for unlock. + m->waiting.insert(TaskManager::getCurrentTask()); + m->lock.unlock(); + CpuManager::getCurrentCPU()->scheduler->setNextRunnable(); + } + TASK_SETRTN(t, 0); + } + + void MutexUnlockCont(task_t* t) + { + // TODO: Extra verification of parameter and mutex state. + + UserMutex* m = (UserMutex*) TASK_GETARG0(t); + m->lock.lock(); + task_t* wait_task = m->waiting.remove(); + if (NULL == wait_task) + { + m->unlock_pend = true; + } + else + { + wait_task->cpu->scheduler->addTask(wait_task); + } + m->lock.unlock(); + TASK_SETRTN(t, 0); + } }; diff --git a/src/lib/makefile b/src/lib/makefile index 1071dc75e..718a8219e 100644 --- a/src/lib/makefile +++ b/src/lib/makefile @@ -2,7 +2,7 @@ OBJDIR = ../../obj include ../../config.mk OBJS = string.o stdlib.o -OBJS += syscall_stub.o syscall_task.o +OBJS += syscall_stub.o syscall_task.o syscall_mutex.o OBJECTS = $(addprefix ${OBJDIR}/, ${OBJS}) all: ${OBJECTS} diff --git a/src/lib/syscall_mutex.C b/src/lib/syscall_mutex.C new file mode 100644 index 000000000..8ac392792 --- /dev/null +++ b/src/lib/syscall_mutex.C @@ -0,0 +1,33 @@ +#include <sys/mutex.h> +#include <sys/syscall.h> +#include <kernel/usermutex.H> + +using namespace Systemcalls; + +mutex_t mutex_create() +{ + return (mutex_t) _syscall0(MUTEX_CREATE); +} + +int mutex_destroy(mutex_t m) +{ + return (int64_t)_syscall1(MUTEX_DESTROY, m); +} + +int mutex_lock(mutex_t m) +{ + uint64_t oldvalue = __sync_fetch_and_add(&((UserMutex*)m)->value, 1); + if (0 == oldvalue) + return 0; + else + return (int64_t)_syscall1(MUTEX_LOCK_CONTESTED, m); +} + +int mutex_unlock(mutex_t m) +{ + uint64_t oldvalue = __sync_fetch_and_sub(&((UserMutex*)m)->value, 1); + if (1 == oldvalue) + return 0; + else + return (int64_t)_syscall1(MUTEX_UNLOCK_CONTESTED, m); +} diff --git a/src/lib/syscall_task.C b/src/lib/syscall_task.C index bfd522933..d07ea3f19 100644 --- a/src/lib/syscall_task.C +++ b/src/lib/syscall_task.C @@ -1,4 +1,5 @@ #include <sys/task.h> +#include <sys/syscall.h> #include <kernel/task.H> using namespace Systemcalls; @@ -9,9 +10,9 @@ void task_yield() return; } -int task_create(void(*fn)(void*), void* ptr) +tid_t task_create(void(*fn)(void*), void* ptr) { - return (int64_t) _syscall2(TASK_START, (void*)fn, ptr); + return (tid_t) _syscall2(TASK_START, (void*)fn, ptr); } void task_end() @@ -20,7 +21,7 @@ void task_end() return; } -uint64_t task_gettid() +tid_t task_gettid() { - return (uint64_t)_syscall0(TASK_GETTID); + return (tid_t)_syscall0(TASK_GETTID); } diff --git a/src/sys/init/init_main.C b/src/sys/init/init_main.C index 8be5ae6c3..efeddcafd 100644 --- a/src/sys/init/init_main.C +++ b/src/sys/init/init_main.C @@ -1,10 +1,15 @@ #include <kernel/console.H> // TODO : Remove this. #include <sys/task.h> +#include <sys/mutex.h> + +mutex_t global_mutex; void init_child(void* unused) { + mutex_lock(global_mutex); printk("Here I am %d\n", task_gettid()); + mutex_unlock(global_mutex); task_end(); } @@ -12,10 +17,14 @@ void init_main(void* unused) { printk("Starting init!\n"); + global_mutex = mutex_create(); + while(1) { + mutex_lock(global_mutex); int t = task_create(&init_child, NULL); printk("Created child %d\n", t); for (volatile int i = 0 ; i < 10000000; i++); + mutex_unlock(global_mutex); } } |