Skip to content

thread park_event

ceragon edited this page Mar 30, 2022 · 2 revisions

ParkEvent

park

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();
    }
}

unpark

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);
    }
}

Clone this wiki locally