1 use std::ffi::c_void;
2 use std::io::Error;
3 use windows_sys::Win32::System::Diagnostics::Debug::FlushInstructionCache;
4 use windows_sys::Win32::System::Threading::FlushProcessWriteBuffers;
5 use windows_sys::Win32::System::Threading::GetCurrentProcess;
6 
7 pub use std::io::Result;
8 
9 /// See docs on [crate::pipeline_flush_mt] for a description of what this function is trying to do.
10 #[inline]
pipeline_flush_mt() -> Result<()>11 pub(crate) fn pipeline_flush_mt() -> Result<()> {
12     // If we are here, it means that the user has already called [cache_clear] for all buffers that
13     // are going to be holding code. We don't really care about flushing the write buffers, but
14     // the other guarantee that microsoft provides on this API. As documented:
15     //
16     // "The function generates an interprocessor interrupt (IPI) to all processors that are part of
17     // the current process affinity. It guarantees the visibility of write operations performed on
18     // one processor to the other processors."
19     //
20     // This all-core IPI acts as a core serializing operation, equivalent to a "broadcast" `ISB`
21     // instruction that the architecture does not provide and which is what we really want.
22     //
23     // See: https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-flushprocesswritebuffers
24     if cfg!(target_arch = "aarch64") {
25         unsafe {
26             FlushProcessWriteBuffers();
27         }
28     }
29 
30     Ok(())
31 }
32 
33 /// See docs on [crate::clear_cache] for a description of what this function is trying to do.
34 #[inline]
clear_cache(ptr: *const c_void, len: usize) -> Result<()>35 pub(crate) fn clear_cache(ptr: *const c_void, len: usize) -> Result<()> {
36     // See:
37     //   * https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-flushinstructioncache
38     //   * https://devblogs.microsoft.com/oldnewthing/20190902-00/?p=102828
39     unsafe {
40         let res = FlushInstructionCache(GetCurrentProcess(), ptr, len);
41         if res == 0 {
42             return Err(Error::last_os_error());
43         }
44     }
45 
46     Ok(())
47 }
48