diff options
| author | Eric Holk <eric.holk@gmail.com> | 2012-07-02 17:42:58 -0700 |
|---|---|---|
| committer | Eric Holk <eric.holk@gmail.com> | 2012-07-06 10:42:39 -0700 |
| commit | e5c9cb2b3df91df4207d63611a1918e461219456 (patch) | |
| tree | 2b01aa2534ed3bbfe645093e83b3ac2586acf337 /src/rt/rust_task.cpp | |
| parent | a4838c93aadf4dbc32e71ddff19c6ecb6a95a66d (diff) | |
| download | rust-e5c9cb2b3df91df4207d63611a1918e461219456.tar.gz rust-e5c9cb2b3df91df4207d63611a1918e461219456.zip | |
Pipes sleep and wake properly.
Diffstat (limited to 'src/rt/rust_task.cpp')
| -rw-r--r-- | src/rt/rust_task.cpp | 53 |
1 files changed, 50 insertions, 3 deletions
diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index d7d43bcd27d..6a9f5cf5001 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -36,6 +36,8 @@ rust_task::rust_task(rust_sched_loop *sched_loop, rust_task_state state, state(state), cond(NULL), cond_name("none"), + event_reject(false), + event(NULL), killed(false), reentered_rust_stack(false), disallow_kill(0), @@ -407,13 +409,20 @@ rust_task::free(void *p) void rust_task::transition(rust_task_state src, rust_task_state dst, rust_cond *cond, const char* cond_name) { + scoped_lock with(state_lock); + transition_locked(src, dst, cond, cond_name); +} + +void rust_task::transition_locked(rust_task_state src, rust_task_state dst, + rust_cond *cond, const char* cond_name) { + state_lock.must_have_lock(); sched_loop->transition(this, src, dst, cond, cond_name); } void rust_task::set_state(rust_task_state state, rust_cond *cond, const char* cond_name) { - scoped_lock with(state_lock); + state_lock.must_have_lock(); this->state = state; this->cond = cond; this->cond_name = cond_name; @@ -422,7 +431,11 @@ rust_task::set_state(rust_task_state state, bool rust_task::block(rust_cond *on, const char* name) { scoped_lock with(kill_lock); + return block_locked(on, name); +} +bool +rust_task::block_locked(rust_cond *on, const char* name) { if (must_fail_from_being_killed_unlocked()) { // We're already going to die. Don't block. Tell the task to fail return false; @@ -433,19 +446,25 @@ rust_task::block(rust_cond *on, const char* name) { assert(cond == NULL && "Cannot block an already blocked task."); assert(on != NULL && "Cannot block on a NULL object."); - transition(task_state_running, task_state_blocked, on, name); + transition_locked(task_state_running, task_state_blocked, on, name); return true; } void rust_task::wakeup(rust_cond *from) { + scoped_lock with(state_lock); + wakeup_locked(from); +} + +void +rust_task::wakeup_locked(rust_cond *from) { assert(cond != NULL && "Cannot wake up unblocked task."); LOG(this, task, "Blocked on 0x%" PRIxPTR " woken up on 0x%" PRIxPTR, (uintptr_t) cond, (uintptr_t) from); assert(cond == from && "Cannot wake up blocked task on wrong condition."); - transition(task_state_blocked, task_state_running, NULL, "none"); + transition_locked(task_state_blocked, task_state_running, NULL, "none"); } void @@ -693,6 +712,34 @@ rust_task::allow_kill() { disallow_kill--; } +void * +rust_task::wait_event() { + scoped_lock with(state_lock); + + if(!event_reject) { + block_locked(&event_cond, "waiting on event"); + bool killed = false; + state_lock.unlock(); + yield(&killed); + state_lock.lock(); + // TODO: what is the right thing to do if we are killed? + } + + event_reject = false; + return event; +} + +void +rust_task::signal_event(void *event) { + scoped_lock with(state_lock); + + this->event = event; + event_reject = true; + if(task_state_blocked == state) { + wakeup_locked(&event_cond); + } +} + // // Local Variables: // mode: C++ |
