diff options
author | dgilbert <dgilbert@us.ibm.com> | 2011-06-03 12:54:41 -0500 |
---|---|---|
committer | A. Patrick Williams III <iawillia@us.ibm.com> | 2011-06-17 12:23:52 -0500 |
commit | 609d6810b8bc92dc979f8bbb8e7e7d7b7b5d9490 (patch) | |
tree | cd517ec2e10a95638e675b037bb24e2d01296ef4 /src/kernel | |
parent | f64ba52098e248e62b4ddb14c0a027c21066e9e2 (diff) | |
download | talos-hostboot-609d6810b8bc92dc979f8bbb8e7e7d7b7b5d9490.tar.gz talos-hostboot-609d6810b8bc92dc979f8bbb8e7e7d7b7b5d9490.zip |
Initial futex support
Change-Id: I51a4f1117085ce23c7993c1a38e4124596636726
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/141
Tested-by: Jenkins Server
Reviewed-by: Douglas R. Gilbert <dgilbert@us.ibm.com>
Reviewed-by: Thi N. Tran <thi@us.ibm.com>
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel')
-rw-r--r-- | src/kernel/futexmgr.C | 88 | ||||
-rw-r--r-- | src/kernel/makefile | 2 | ||||
-rw-r--r-- | src/kernel/syscall.C | 104 |
3 files changed, 127 insertions, 67 deletions
diff --git a/src/kernel/futexmgr.C b/src/kernel/futexmgr.C new file mode 100644 index 000000000..aaae95b53 --- /dev/null +++ b/src/kernel/futexmgr.C @@ -0,0 +1,88 @@ +/** + * @file futexmgr.C + * @brief Definition for kernel side futex management + */ +#include <assert.h> +#include <errno.h> +#include <kernel/task.H> +#include <kernel/cpumgr.H> +#include <kernel/scheduler.H> +#include <kernel/futexmgr.H> +#include <util/singleton.H> + + +//----------------------------------------------------------------------------- + +uint64_t FutexManager::wait(task_t* i_task, uint64_t * i_addr, uint64_t i_val) +{ + return Singleton<FutexManager>::instance()._wait(i_task, i_addr, i_val); +} + +//----------------------------------------------------------------------------- + +uint64_t FutexManager::wake(uint64_t * i_addr, uint64_t i_count) +{ + return Singleton<FutexManager>::instance()._wake(i_addr, i_count); +} + +//----------------------------------------------------------------------------- + +uint64_t FutexManager::_wait(task_t* i_task, uint64_t * i_addr, uint64_t i_val) +{ + uint64_t rc = 0; + + iv_lock.lock(); + + if(*i_addr != i_val) + { + // some other thread has modified the futex + // bail-out retry required. + iv_lock.unlock(); + rc = EWOULDBLOCK; + } + else + { + _FutexWait_t * waiter = new _FutexWait_t(); + waiter->key = i_addr; + waiter->task = i_task; + + // Now add the futex/task it to the wait queue + iv_list.insert(waiter); + iv_lock.unlock(); + CpuManager::getCurrentCPU()->scheduler->setNextRunnable(); + } + + return rc; +} + +//----------------------------------------------------------------------------- + +uint64_t FutexManager::_wake(uint64_t * i_addr, uint64_t i_count) +{ + uint64_t started = 0; + + // Remove task(s) from futex queue + // Put it/them on the run queue + iv_lock.lock(); + while(started < i_count) + { + _FutexWait_t * waiter = iv_list.find(i_addr); + if(waiter == NULL) + { + break; + } + + task_t * wait_task = waiter->task; + iv_list.erase(waiter); + + // This means we had a waiter in the queue, but that waiter had + // a Null task assigned to it. This should NEVER happen + assert(wait_task != NULL); + + wait_task->cpu->scheduler->addTask(wait_task); + ++started; + } + iv_lock.unlock(); + + return started; +} diff --git a/src/kernel/makefile b/src/kernel/makefile index 057552b9d..4f100c660 100644 --- a/src/kernel/makefile +++ b/src/kernel/makefile @@ -1,7 +1,7 @@ ROOTPATH = ../.. OBJS = start.o kernel.o console.o pagemgr.o heapmgr.o taskmgr.o cpumgr.o -OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o timemgr.o +OBJS += syscall.o scheduler.o spinlock.o exception.o vmmmgr.o timemgr.o futexmgr.o include ${ROOTPATH}/config.mk diff --git a/src/kernel/syscall.C b/src/kernel/syscall.C index 837ed3d21..85252a408 100644 --- a/src/kernel/syscall.C +++ b/src/kernel/syscall.C @@ -6,9 +6,9 @@ #include <kernel/syscalls.H> #include <kernel/console.H> #include <kernel/pagemgr.H> -#include <kernel/usermutex.H> #include <kernel/msg.H> #include <kernel/timemgr.H> +#include <kernel/futexmgr.H> extern "C" void kernel_execute_decrementer() @@ -26,10 +26,6 @@ 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*); void MsgQCreate(task_t*); void MsgQDestroy(task_t*); void MsgQRegisterRoot(task_t*); @@ -41,6 +37,8 @@ namespace Systemcalls void MmioMap(task_t*); void MmioUnmap(task_t*); void TimeNanosleep(task_t*); + void FutexWait(task_t *t); + void FutexWake(task_t *t); syscall syscalls[] = { @@ -48,11 +46,6 @@ namespace Systemcalls &TaskStart, &TaskEnd, - &MutexCreate, - &MutexDestroy, - &MutexLockCont, - &MutexUnlockCont, - &MsgQCreate, &MsgQDestroy, &MsgQRegisterRoot, @@ -67,6 +60,9 @@ namespace Systemcalls &MmioUnmap, &TimeNanosleep, + + &FutexWait, + &FutexWake, }; }; @@ -133,62 +129,6 @@ namespace Systemcalls delete t; } - 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); - } - void MsgQCreate(task_t* t) { TASK_SETRTN(t, (uint64_t) new MessageQueue()); @@ -349,5 +289,37 @@ namespace Systemcalls s->setNextRunnable(); } + /** + * Put task on wait queue based on futex + * @param[in] t: The task to block + */ + void FutexWait(task_t * t) + { + uint64_t * uaddr = (uint64_t *) TASK_GETARG0(t); + uint64_t val = (uint64_t) TASK_GETARG1(t); + + //TODO translate uaddr from user space to kernel space + // Right now they are the same. + + uint64_t rc = FutexManager::wait(t,uaddr,val); + TASK_SETRTN(t,rc); + } + + /** + * Wake tasks on futex wait queue + * @param[in] t: The current task + */ + void FutexWake(task_t * t) + { + uint64_t * uaddr = (uint64_t *) TASK_GETARG0(t); + uint64_t count = (uint64_t) TASK_GETARG1(t); + + // TODO translate uaddr from user space to kernel space + // Right now they are the same + + uint64_t started = FutexManager::wake(uaddr,count); + + TASK_SETRTN(t,started); + } }; |