diff options
author | Doug Gilbert <dgilbert@us.ibm.com> | 2012-01-12 10:32:19 -0600 |
---|---|---|
committer | Douglas R. Gilbert <dgilbert@us.ibm.com> | 2012-01-25 10:54:55 -0600 |
commit | c4f6f3ee887c0fa89c4ed5c311410363f6d61cb4 (patch) | |
tree | e309f1aaef54ba14d38bd7d09c63e456edd7a612 /src/kernel/futexmgr.C | |
parent | cad6f41c5ceb5affe968a32618e4cf5d53cb7554 (diff) | |
download | talos-hostboot-c4f6f3ee887c0fa89c4ed5c311410363f6d61cb4.tar.gz talos-hostboot-c4f6f3ee887c0fa89c4ed5c311410363f6d61cb4.zip |
Conditional Variable support
Change-Id: Ib715b3a4e775ef183244e8769c6560a85ac19104
Reviewed-on: http://gfw160.austin.ibm.com:8080/gerrit/612
Tested-by: Jenkins Server
Reviewed-by: A. Patrick Williams III <iawillia@us.ibm.com>
Diffstat (limited to 'src/kernel/futexmgr.C')
-rw-r--r-- | src/kernel/futexmgr.C | 54 |
1 files changed, 45 insertions, 9 deletions
diff --git a/src/kernel/futexmgr.C b/src/kernel/futexmgr.C index 606e26c8c..f66452543 100644 --- a/src/kernel/futexmgr.C +++ b/src/kernel/futexmgr.C @@ -42,9 +42,11 @@ uint64_t FutexManager::wait(task_t* i_task, uint64_t * i_addr, uint64_t i_val) //----------------------------------------------------------------------------- -uint64_t FutexManager::wake(uint64_t * i_addr, uint64_t i_count) +uint64_t FutexManager::wake(uint64_t * i_futex1, uint64_t i_count1, + uint64_t * i_futex2, uint64_t i_count2) { - return Singleton<FutexManager>::instance()._wake(i_addr, i_count); + return Singleton<FutexManager>::instance()._wake(i_futex1, i_count1, + i_futex2, i_count2); } //----------------------------------------------------------------------------- @@ -57,7 +59,7 @@ uint64_t FutexManager::_wait(task_t* i_task, uint64_t * i_addr, uint64_t i_val) if(unlikely(*i_addr != i_val)) { - // some other thread has modified the futex + // some other task has modified the futex // bail-out retry required. iv_lock.unlock(); rc = EWOULDBLOCK; @@ -81,18 +83,22 @@ uint64_t FutexManager::_wait(task_t* i_task, uint64_t * i_addr, uint64_t i_val) return rc; } -//----------------------------------------------------------------------------- -uint64_t FutexManager::_wake(uint64_t * i_addr, uint64_t i_count) +// Wake processes. Any number of processes in excess of count1 are not +// woken up but moved to futex2. the number of processes to move +// is capped by count2. +uint64_t FutexManager::_wake(uint64_t * i_futex1, uint64_t i_count1, + uint64_t * i_futex2, uint64_t i_count2 + ) { uint64_t started = 0; - // Remove task(s) from futex queue - // Put it/them on the run queue iv_lock.lock(); - while(started < i_count) + + // First start up to i_count1 task(s) + while(started < i_count1) { - _FutexWait_t * waiter = iv_list.find(i_addr); + _FutexWait_t * waiter = iv_list.find(i_futex1); if(waiter == NULL) { break; @@ -109,6 +115,36 @@ uint64_t FutexManager::_wake(uint64_t * i_addr, uint64_t i_count) wait_task->cpu->scheduler->addTask(wait_task); ++started; } + + if(i_futex2 && i_count2) + { + uint64_t moved = 0; + + // Move up to i_count2 tasks to futex2 + while(moved < i_count2) + { + // What if *i_futex2 got modified !!!! TODO + // Do we need a safety check here (another val param) ???? + _FutexWait_t * waiter = iv_list.find(i_futex1); + if(waiter == NULL) + { + break; + } + + task_t * wait_task = waiter->task; + iv_list.erase(waiter); + + kassert(wait_task != NULL); // should never happen, but... + + waiter->key = i_futex2; + wait_task->state_info = i_futex2; + + iv_list.insert(waiter); + ++moved; + } + } + + iv_lock.unlock(); return started; |