apoch / epoch-language

Home of the Epoch Programming Language Project
Other
72 stars 3 forks source link

Marshalling External Function Call Issues #177

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
Here's a fun one, been working on getting CreateThread to import. So far no 
luck at all. Below is my attempt. Simply silently dies after the first 
MessageBox call. Interestingly enough, it appears to NEVER CALL CreateThread 
(set a breakpoint, never gets invoked).

MessageBox : integer hwnd, string message, string caption, integer style -> 
integer ret = 0 [external("User32.dll", "MessageBoxW", "stdcall")]
CreateThread : integer threadAttributes, integer stackSize, (callback : integer 
ref -> integer), integer ref param, integer creationFlags, integer ref threadId 
-> integer ret = 0 [external("Kernel32.dll", "CreateThread", "stdcall")]

entrypoint :
{
    MessageBox(0, "Will reach", "test", 0)

    integer param = 0
    integer threadId = 0
    CreateThread(0, 0, callback, param, 0, threadId)

    MessageBox(0, "Will not reach", "test", 0)
}

callback : integer ref param -> integer ret = 0
{
    MessageBox(0, "Will not reach", "test", 0)
    return()
}

Original issue reported on code.google.com by ryoohki@gmail.com on 7 Oct 2014 at 3:31

GoogleCodeExporter commented 9 years ago

Original comment by ryoohki@gmail.com on 7 Oct 2014 at 3:31

GoogleCodeExporter commented 9 years ago
Bah.

LLVM sometimes generates stubs that JMP to the implementation of the actual 
function; this has something to do with the allocations it makes of RWX memory 
pages, but I haven't pinpointed what.

Anyways, long story short, the Epoch JIT is assuming the callback address is a 
stub instead of the actual function. So when it goes to create the marshaling 
wrapper for the callback, it can't find the appropriate code, and barfs.

This, coincidentally, is not a silent failure; it should be dumping a message 
(albeit a thoroughly unhelpful one) to stdout or stderr (I forget which) when 
run from a command line.

Original comment by don.ap...@gmail.com on 8 Oct 2014 at 4:55

GoogleCodeExporter commented 9 years ago
So, funny story...

I fixed the JIT bug (trivial) and this continued to crash, albeit in a very 
different way.

TLDR the runtime environment that does things like string resource management 
and general garbage collection is not thread-safe. To reflect this, the 
interface for the runtime context is thread-local.

This means that when CreateThread is used, it ends up launching a thread that 
is not allowed to ever read or write strings, or garbage collect. In other 
words, CreateThread is pretty much not gonna fly.

This pushes heavily on the need for first-class threading support I suppose, 
but that's a much bigger topic.

Original comment by don.ap...@gmail.com on 8 Oct 2014 at 5:26

GoogleCodeExporter commented 9 years ago
I figured the string and GC stuff wasn't thread safe yet, I don't even think it 
should be thread safe, i think it should be completely thread "contained" with 
full ownership transfer when messages are passed between threads...

Does this mean everything should be thread local? NO, not necessarily, I think 
some core pieces (like the string table, etc) should be thread safe, but i'm 
not certain where to draw the line.

Original comment by ryoohki@gmail.com on 8 Oct 2014 at 5:29