summaryrefslogtreecommitdiffstats
path: root/src/kernel
diff options
context:
space:
mode:
authordgilbert <dgilbert@us.ibm.com>2011-06-03 12:54:41 -0500
committerA. Patrick Williams III <iawillia@us.ibm.com>2011-06-17 12:23:52 -0500
commit609d6810b8bc92dc979f8bbb8e7e7d7b7b5d9490 (patch)
treecd517ec2e10a95638e675b037bb24e2d01296ef4 /src/kernel
parentf64ba52098e248e62b4ddb14c0a027c21066e9e2 (diff)
downloadtalos-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.C88
-rw-r--r--src/kernel/makefile2
-rw-r--r--src/kernel/syscall.C104
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);
+ }
};
OpenPOWER on IntegriCloud