I spoke before of using global locks in Haskell to protect a thread-unsafe C library. And I wrote about a GHC bug which breaks the most straightforward way to get a global lock.
My new solution is to store an MVar
lock in a C global variable via StablePtr
. I've implemented this, and it seems to work. I'd appreciate if people could bang on this code and report any issues.
You can get the library from Hackage or browse the source, including a test program. You can also use this code as a template for including a similar lock in your own Haskell project.
The C code
On the C side, we declare a global variable and a function to read that variable.
static void* global = 0;
void* hs_globalzmlock_get_global(void) {
return global;
}
To avoid name clashes, I gave this function a long name based on the z-encoding of my package's name. The variable named global
will not conflict with another compilation unit, because it's declared static
.
Another C function will set this variable, if it was previously 0. Two threads might execute this code concurrently, so we use a GCC built-in for atomic memory access.
int hs_globalzmlock_set_global(void* new_global) {
void* old = __sync_val_compare_and_swap(&global, 0, new_global);
return (old == 0);
}
If old
is not 0, then someone has already set global
, and our assignment was dropped. We report this condition to the caller.
Foreign imports
On the Haskell side, we import these C functions.
foreign import ccall unsafe "hs_globalzmlock_get_global"
c_get_global :: IO (Ptr ())
foreign import ccall "hs_globalzmlock_set_global"
c_set_global :: Ptr () -> IO CInt
The unsafe
import of c_get_global
demands justification. This wrinkle arises from the fact that GHC runs many Haskell threads on the same OS thread. A long-running foreign call from that OS thread might block unrelated Haskell code. GHC prevents this by moving the foreign call and/or other Haskell threads to a different OS thread. This adds latency to the foreign call — about 100 nanoseconds in my tests.
In most cases a 100 ns overhead is negligible. But it matters for functions which are guaranteed to return in a very short amount of time. And blocking other Haskell threads during such a short call is fine. Marking the import unsafe
tells GHC to ignore the blocking concern, and generate a direct C function call.
Our function c_get_global
is a good use case for unsafe
, because it simply returns a global variable. In my tests, adding unsafe
decreased the overall latency of locking by about 50%. We cannot use unsafe
with c_set_global
because, in the worst case, GCC implements atomic operations with blocking library functions. That's okay because c_set_global
will only be called a few times anyway.
The Haskell code
Now we have access to a C global of type void*
, and we want to store a Haskell value of type MVar ()
. The StablePtr
module is just what we need. A StablePtr
is a reference to some Haskell expression, which can be converted to Ptr ()
, aka void*
. There is no guarantee about this Ptr ()
value, except that it can be converted back to the original StablePtr
.
Here's how we store an MVar
:
set :: IO ()
set = do
mv <- newMVar ()
ptr <- newStablePtr mv
ret <- c_set_global (castStablePtrToPtr ptr)
when (ret == 0) $
freeStablePtr ptr
It's fine for two threads to enter set
concurrently. In one thread, the assignment will be dropped, and c_set_global
will return 0. In that case we free the unused StablePtr
, and the MVar
will eventually be garbage-collected. StablePtr
s must be freed manually, because the GHC garbage collector can't tell if some C code has stashed away the corresponding void*
.
Now we can retrieve the MVar
, or create it if necessary.
get :: IO (MVar ())
get = do
p <- c_get_global
if p == nullPtr
then set >> get
else deRefStablePtr (castPtrToStablePtr p)
In the common path, we do an unsynchronized read on the global variable. Only if the variable appears to contain NULL
do we allocate an MVar
, perform a synchronized compare-and-swap, etc. This keeps overhead low, and makes this library suitable for fine-grained locking.
All that's left is the user-visible locking interface:
lock :: IO a -> IO a
lock act = get >>= flip withMVar (const act)
Inspecting the machine code
Just for fun, let's see how GCC implements __sync_val_compare_and_swap
on the AMD64 architecture.
$ objdump -d dist/build/cbits/global.o
...
0000000000000010 <hs_globalzmlock_set_global>:
10: 31 c0 xor %eax,%eax
12: f0 48 0f b1 3d 00 00 lock cmpxchg %rdi,0x0(%rip)
19: 00 00
....
This lock cmpxchg
is the same instruction used by the GHC runtime system for its own atomic compare-and-swap. The offset on the operand 0x0(%rip)
will be relocated to point at global
.
Insight into the cool points Manchester United Football News. เจาะลึกประเด็นเด็ด ข่าวกีฬาลูกหนัง แมนเชสเตอร์ ยูไนเต็ด
ReplyDeleteSuggest good information in this message, click here.
ReplyDeleteedizenco.com
emeraldgardensnw.com
Easyworship Crack
ReplyDeleteCracked Here is a useful place where you can easily find Activators, Patch, Full version software Free Download, License key, serial key, keygen, Activation Key and Torrents.
Get all of these by easily just on a single click.
Your website, especially this blog page, has recently provided me with lots of useful information. Your articles have received numerous comments as well. Thanks for sharing. This is a very popular platform and it is a topic of discussion among people. This article can help you get more likes and popularity for your Instagram post if you want more likes and popularity. To learn more, read the whole profile Generate Fake Instagram Post
ReplyDeleteเหตุผลที่ควรสมัครเดิมพันออนไลน์กับ Ufabet
ReplyDelete1. เว็บพนันออนไลน์ Ufabet เว็บตรง เป็นเว็บพนันที่ถูกกฎหมายจดทะเบียนจริงมีสำนักงานจริงในหลายประเทศ จึงทำให้คุณเชื่อถือบริการของที่นี่ได้
2. บริการเกมพนันที่นี่มีให้ครบแน่นอน เดิมพันกีฬา เดิมพันคาสิโน และ ยังอัพเดทบริการเกมใหม่ ๆ ทันสมัยแปลกใหม่มากมาย เอาใจคอพนันชาวไทยตลอดทั้งปี ทุกบริการเล่นง่ายผ่านระบบออนไลน์ เป็นสมาชิกที่นี่ได้สิทธิประโยชน์อื่น ๆ ที่พร้อมให้สมาชิกเลือกได้
3. มีพนักงานพร้อมดูแลสมาชิกมีตลอด 24 ชั่วโมง ติดต่อได้ง่าย บริการข้อมูลข่าวสารและสูตรการเดิมพันต่าง ๆ มากมายให้สมาชิกได้เล่นเดิมพันตลอดทั้งปี เล่นบริการเดิมพันทำเงินเลือกที่นี่ย้ำว่าเป็นบริการสุดพิเศษ ทำเงินได้ทำกำไรได้จริง
เล่นเดิมพันได้ลื่นไหล ทำเงินได้จริง เกมใหม่มีตลอดเวลาแน่นอน การันตีเลยว่า Ufabet ทำให้คุณไม่พลาดที่จะทำเงินกับเกมพนันทันสมัย พนันออนไลน์ ทุกบริการที่คุณต้องการมีให้ที่นี่แน่นอน ย้ำว่าอย่าพลาดหากกำลังมองหาการเดิมพันออนไลน์ดี ๆ เชื่อถือได้จ่ายจริง แนะนำเลือกที่นี่ไม่พลาดแน่นอน ก่อนตัดสินใจเลือกอ่านคำแนะนำของเราได้และเหตผลที่เราอยากบอกคือ
ReplyDeleteเว็บไซต์เดิมพันออนไลน์ที่ครบวงจรที่สุด ต้องยกนิ้วให้ SA Gaming เจ้าแห่งคาสิโนออนไลน์ดีที่สุด เล่นง่ายได้เงินจริง https://sagameallinone.com/ เว็บไซต์เดิมพันออนไลน์ ที่ครบวงจรที่สุด เกมเดิมพันออนไลน์ครบวงจร ตอบโจทย์ทุกความต้องการของผู้เล่น เพราพว่าเราได้รวบรวมเกมเดิมพันออนไลน์ทุกค่าย ทุกเกม ทุกเเขนงไว้ในเว็บไซต์เดียว เข้าถึงง่าย ใช้งานสะดวก เว็บเดียวจบครบทุกบริการ.
ReplyDeleteGutt Websäit : Zonahobisaya
ReplyDeleteGutt Websäit : Sinopsis Film Terbaru
Gutt Websäit : Zonahobisaya
Gutt Websäit : Zonahobisaya
Gutt Websäit : Profil
Gutt Websäit : Zonahobisaya
Gutt Websäit : Zonahobisaya
Gutt Websäit : Zonahobisaya
I like your post and everything you share with is extremely informative. Keep sharing informative posting here.
ReplyDeleteC programming is a general-purpose, procedural, imperative computer programming language developed in 1972 by Dennis M.
ReplyDeleteThank you for posting a lot of interesting posts.
ReplyDeleteI wanted to thank you for this excellent read.
ReplyDeleteI definitely loved every little bit of it.
ReplyDeletehere, but I thought this submit used to be good
ReplyDeleteYou really amazed me with your writing talent. Thank you for sharing again.
ReplyDeleteThis web site truly has all the information
ReplyDeleteThanks and Best of luck to your next Blog in future.
ReplyDeleteI appreciate you sharing the helpful information in this article. Check out this article Farnsworth Lantern Test. For prospective recruits, understanding the restrictions and exclusions is essential.
ReplyDeleteGreetings! Your blog is very interesting! Please check my website I have a recommendation for you.
ReplyDeleteAfter all I will be subscribing to your feed and I hope you write again very soon!
ReplyDeleteI am really impressed by reading the information content you provided.
ReplyDeleteA debt of gratitude is in order for sharing this helpful information..
ReplyDelete