Repository navigation
thread park_event
ceragon edited this page Mar 30, 2022
·
2 revisions
void os::PlatformEvent::park() {
int v;
for (;;) {
// 当前线程的 ParkEvent 的 _event 变量
v = _event;
// cas 将 _event - 1
if (Atomic::cmpxchg(v - 1, &_event, v) == v) break;
}
if (v == 0) { // Do this the hard way by blocking ...
// 旧值为0 才会进入
// 锁住线程的 mutex,status == 0 表示成功
int status = pthread_mutex_lock(_mutex);
// park 次数 + 1
++_nParked;
while (_event < 0) {
// 当前值只要小于 0 就会进入等待状态,直到收到 _cond 信号后被唤醒
status = pthread_cond_wait(_cond, _mutex);
// 被唤醒的同时,还会把 _event 设置为1
}
// 次数 - 1
--_nParked;
// 只要被唤醒了 _event 就重置为 0
_event = 0;
// 解锁
status = pthread_mutex_unlock(_mutex);
// 编译器 和 CPU 指令双屏障
OrderAccess::fence();
}
}void os::PlatformEvent::unpark() {
// 将 _event 赋值为0,且返回 _event 旧值。如果旧值已经 >= 0,则无需唤醒
if (Atomic::xchg(1, &_event) >= 0) return;
// 线程加锁
int status = pthread_mutex_lock(_mutex);
// 获取等待者的数量
int anyWaiters = _nParked;
// 解锁
status = pthread_mutex_unlock(_mutex);
if (anyWaiters != 0) {
// 只要有等待者就唤醒等待者
status = pthread_cond_signal(_cond);
}
}