fix lockups when a condvar signals while a task is being blocked
parent
66758fa1df
commit
1351ac14f6
|
@ -18,7 +18,8 @@ int main() {
|
||||||
spawn(sched, f, c, arr.slice(0, arr.size() / 2));
|
spawn(sched, f, c, arr.slice(0, arr.size() / 2));
|
||||||
spawn(sched, f, c, arr + (arr.size() / 2));
|
spawn(sched, f, c, arr + (arr.size() / 2));
|
||||||
|
|
||||||
int a = c.get(), b = c.get();
|
int a = c.get();
|
||||||
|
int b = c.get();
|
||||||
writefln("%s + %s = %s", a, b, a + b);
|
writefln("%s + %s = %s", a, b, a + b);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#ifndef OSTD_CHANNEL_HH
|
#ifndef OSTD_CHANNEL_HH
|
||||||
#define OSTD_CHANNEL_HH
|
#define OSTD_CHANNEL_HH
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
#include <list>
|
#include <list>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include <condition_variable>
|
#include <condition_variable>
|
||||||
|
|
|
@ -328,6 +328,12 @@ private:
|
||||||
|
|
||||||
template<typename L>
|
template<typename L>
|
||||||
void wait(L &l) noexcept {
|
void wait(L &l) noexcept {
|
||||||
|
/* lock until the task has been added to the wait queue,
|
||||||
|
* that ensures that any notify/notify_any has to wait
|
||||||
|
* until after the task has fully blocked... we can't
|
||||||
|
* use unique_lock or lock_guard because they're scoped
|
||||||
|
*/
|
||||||
|
p_sched.p_lock.lock();
|
||||||
l.unlock();
|
l.unlock();
|
||||||
task *curr = task::current();
|
task *curr = task::current();
|
||||||
curr->waiting_on = this;
|
curr->waiting_on = this;
|
||||||
|
@ -493,8 +499,8 @@ private:
|
||||||
task &c = *it;
|
task &c = *it;
|
||||||
l.unlock();
|
l.unlock();
|
||||||
c();
|
c();
|
||||||
l.lock();
|
|
||||||
if (c.dead()) {
|
if (c.dead()) {
|
||||||
|
l.lock();
|
||||||
p_running.erase(it);
|
p_running.erase(it);
|
||||||
/* we're dead, notify all threads so they can be joined
|
/* we're dead, notify all threads so they can be joined
|
||||||
* we check all three, saves the other threads some re-waiting
|
* we check all three, saves the other threads some re-waiting
|
||||||
|
@ -507,6 +513,7 @@ private:
|
||||||
}
|
}
|
||||||
} else if (!c.waiting_on) {
|
} else if (!c.waiting_on) {
|
||||||
/* reschedule to the end of the queue */
|
/* reschedule to the end of the queue */
|
||||||
|
l.lock();
|
||||||
p_available.splice(p_available.cend(), p_running, it);
|
p_available.splice(p_available.cend(), p_running, it);
|
||||||
l.unlock();
|
l.unlock();
|
||||||
p_cond.notify_one();
|
p_cond.notify_one();
|
||||||
|
@ -514,6 +521,8 @@ private:
|
||||||
p_waiting.splice(p_waiting.cbegin(), p_running, it);
|
p_waiting.splice(p_waiting.cbegin(), p_running, it);
|
||||||
c.next_waiting = c.waiting_on->p_waiting;
|
c.next_waiting = c.waiting_on->p_waiting;
|
||||||
c.waiting_on->p_waiting = &c;
|
c.waiting_on->p_waiting = &c;
|
||||||
|
/* wait locks the mutex, so manually unlock it here */
|
||||||
|
p_lock.unlock();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue