< 返回版块

Warrenren 发表于 2022-05-20 09:24

以下是标准库 library/std/src/sys/unix/locks/futex_rwlock.c中的一段代码。 因为使用futex的机制,所以在真正进入等锁阻塞时需要做很多冗余处理。 这里面感觉有一个bug,请大家也帮助看一下,是否真的是bug。

    //进入写等待队列的处理
    fn write_contended(&self) {
        let mut state = self.spin_write();

        //假定当前没有线程等待写, 后继处理如果更新,
        //则说明有两个以上的线程在竞争获取写锁,所以
        //设置state时需要同时更新写等待标志位
        let mut other_writers_waiting = 0;

        loop {
            //  如果unlocked,那试图获取写锁
            if is_unlocked(state) {
                match self.state.compare_exchange_weak(
                    state,
                    state | WRITE_LOCKED | other_writers_waiting,
                    Acquire,
                    Relaxed,
                ) {
                    //获取成功
                    Ok(_) => return, // Locked!
                    Err(s) => {
                        //获取失败,再次循环
                        state = s;
                        continue;
                    }
                }
            }

            // 不为unlock,进入写等待队列并更新写等待标志
            if !has_writers_waiting(state) {
                if let Err(s) =
                    self.state.compare_exchange(state, state | WRITERS_WAITING, Relaxed, Relaxed)
                {
                    //更新失败,说明有同时访问者,需要重新试图获取写锁
                    state = s;
                    continue;
                }
            }

            // 不为unlock,且写等待标志位已经设置
            // 已经有其他写线程在等待.
            other_writers_waiting = WRITERS_WAITING;

            // 获取写锁解除的通知变量
            let seq = self.writer_notify.load(Acquire);

            let s = self.state.load(Relaxed);

下面这段,"is_unlocked(state)"似乎应该是"is_unlocked(s)",前面的代码已经对state做过is_unlocked判断,且中间也没有更新过。

            //这个地方似乎错了,本意估计是is_unlocked(s), state此时已经确定
            //为lock了
            if is_unlocked(state) || !has_writers_waiting(s) {
                //这里如果又有变化,那么再次试图获得写锁
                state = s;
                continue;
            }

            // 阻塞,等待解锁通知 
            futex_wait(&self.writer_notify, seq, None);

            // 失败或者唤醒,重新再次试图获取写锁 
            state = self.spin_write();
        }
    }

评论区

写评论
作者 Warrenren 2022-05-24 09:10

已经在github提交issue并且被确认修改了

Grainspring 2022-05-21 11:12

这里应该也是一个冗余检查。毕竟前面load和compare_exchange操作中,都使用Relaxed,而不是Release.

Neutron3529 2022-05-20 15:32

建议去IRLO问一句

Grobycn 2022-05-20 11:07

感觉是 bug。

1 共 4 条评论, 1 页