内存屏障和 TLB

内存屏障保证数据缓存是一致的。但是,它是否保证 TLB 是一致的?

我看到一个问题,JVM(java 7 update 1)在线程之间传递MappedByteBuffer时有时会因内存错误(SIGBUS,SIGSEG)而崩溃。

例如:

final AtomicReference<MappedByteBuffer> mbbQueue = new AtomicReference<>();

// in a background thread.
MappedByteBuffer map = raf.map(MapMode.READ_WRITE, offset, allocationSize);
Thread.yield();
while (!inQueue.compareAndSet(null, map));


// the main thread. (more than 10x faster than using map() in the same thread)
MappedByteBuffer mbb = inQueue.getAndSet(null);

如果没有 Thread.yield(),我偶尔会在 force()、put() 和 C 的 memcpy() 中崩溃,这一切都表明我试图非法访问内存。使用Thread.yield()我没有遇到问题,但这听起来不像是一个可靠的解决方案。

有没有人遇到过这个问题?是否有关于 TLB 和内存屏障的任何保证?


编辑:操作系统是Centos 5.7,我已经在i7和Dual Xeon机器上看到了行为。

我为什么要这样做?因为写入消息的平均时间为35-100 ns,具体取决于长度,并且使用普通speat()的速度并不快。如果我在当前线程中进行内存映射和清理,则需要50-130微秒,使用后台线程进行操作,主线程交换缓冲区大约需要3-5微秒。为什么我需要交换缓冲区?因为我正在写入许多GB的数据,而ByteBuffer的大小不能超过2 GB。


答案 1

映射是通过mmap64(FileChannel.map)完成的。当访问地址时,将出现页面错误,内核将为您读/写。TLB 在 mmap 期间不需要更新。

TLB(所有cpu)在munmap期间未经验证,由MappedByteBuffer的终结处理,因此munmap成本很高。

映射涉及大量同步,因此地址值不会损坏。

你有没有机会通过不安全尝试花哨的东西?


答案 2

推荐