在过去的问题中,我询问了如何在不破坏种族的情况下实现pthread屏障:
从迈克尔·伯尔(Michael Burr)那里获得了针对过程本地障碍的完美解决方案,但是对于过程共享的障碍却没有。我们后来研究了一些想法,但从未得出令人满意的结论,甚至没有开始涉及资源故障案例。
在Linux上能否制造出满足以下条件的障碍:
Michael尝试解决共享过程的案例(请参阅链接的问题),不幸的是,必须在等待时分配某种系统资源,这意味着等待会失败。尚不清楚在屏障等待失败时调用方可以采取何种合理措施,因为屏障的全部意义在于,在其余N-1线程到达该线程之前,继续进行操作是不安全的…
N-1
内核空间解决方案可能是唯一的方法,但即使这样也很困难,因为信号可能会中断等待,而没有可靠的方法来恢复等待。
与bdonlan在SO聊天上进行了长时间的讨论之后,我想我有一个解决方案。基本上,我们将问题分为两个自同步释放问题:销毁操作和取消映射。
处理破坏很容易:只需使pthread_barrier_destroy函数等待所有服务员停止检查障碍即可。这可以通过在屏障中使用计数,在进入/退出等待函数时原子递增/递减以及使destroy函数旋转以使计数达到零来完成。(如果您在使用计数的高位或类似位置贴上一个服务员标志,则也可以在此处使用futex,而不仅仅是旋转)。
pthread_barrier_destroy
处理取消映射也很容易,但也可以是非本地的:通过在syscall包装器中添加锁定,确保在屏障侍者退出过程中不会出现munmap或mmap带有MAP_FIXED标志。这需要一种特殊的读写器锁。最后一个到达障碍的服务员应抓住munmaprw锁上的读锁,当最后一个服务员退出时(当减少用户计数时,计数为0时),该锁将被释放。munmap并且mmap可以通过使Writer锁递归来使其成为可重入的(如某些程序可能期望的那样,即使POSIX不需要它)。实际上,一种读写器是完全对称的,并且每种类型的锁都排除相反类型的锁,但不是同一类型的锁应该是最好的。
munmap
mmap
MAP_FIXED