From Malcolm.Wallace at cs.york.ac.uk Wed Oct 8 06:06:03 2008 From: Malcolm.Wallace at cs.york.ac.uk (Malcolm Wallace) Date: Wed Oct 8 06:07:38 2008 Subject: [nhc-users] FFI "wrapper" In-Reply-To: <20080922063213.15DD5F3960@mail.avvanta.com> References: <20080922063213.15DD5F3960@mail.avvanta.com> Message-ID: <20081008110603.0a81c5d1.Malcolm.Wallace@cs.york.ac.uk> Donn, sorry I didn't see your message until now - it got filtered away to a different mailbox during ICFP. > Just this weekend I got nhc98 running on a platform where I've wanted > a Haskell compiler for a long time, very thrilling. But of course > nothing's ever perfect, and apparently there's no foreign import > "wrapper" support, which I think is what I would use to pass Haskell > functions to C. You are right, nhc98 does not support "foreign import wrapper". The main problem is generating machine code on-the-fly. One possibility would be to steal ghc's Adjustor code. Another route might be to change all the FFI backend code over to using libFFI, as yhc (based on nhc98) has already done, and as I think ghc has also done recently. (However, I believe yhc never attempted to implement "foreign import wrapper" either.) > While I'm at it - if I manage to get callbacks working - they'll be > coming from various different OS-level threads, so ... I will need to > protect against concurrent execution, right? nhc98's runtime system is single-threaded, but assuming that the functions you export are pure, I don't see how that is a problem. I suppose you would need somehow to route all callbacks into the OS thread that contained the (single) nhc98 runtime system? Yhc has concurrent Haskell-level threads, but again they are contained within a single OS-level thread. Regards, Malcolm From donn at avvanta.com Wed Oct 15 02:50:16 2008 From: donn at avvanta.com (Donn Cave) Date: Wed Oct 15 02:46:31 2008 Subject: [nhc-users] FFI "wrapper" Message-ID: <20081015065016.B88ACF393F@mail.avvanta.com> Quoth Malcolm Wallace : ... |> While I'm at it - if I manage to get callbacks working - they'll be |> coming from various different OS-level threads, so ... I will need to |> protect against concurrent execution, right? | | nhc98's runtime system is single-threaded, but assuming that the | functions you export are pure, I don't see how that is a problem. I | suppose you would need somehow to route all callbacks into the OS thread | that contained the (single) nhc98 runtime system? Well, I suppose that's a possibility, though it would further limit what I could do within Haskell of course. I'm working (or playing would be more accurate) with the Haiku operating system, essentially same API as BeOS from the '90s. Not yet even to the alpha release, so I'm not offended if you find the platform obscure. Its user interface uses threads, one per window, and sends messages to the window message port for user input etc. The API is C++. Just to see what would happen, I put together the trivial beginning of a hybrid C++/Haskell application, with roughly a 5 layer structure - 1 Haskell: trivial main, for runtime 2 C++: application main thread, and 1 window thread 3 Haskell: from window callback, and Haskell in independent thread 4 C: utility wrappers 5 C++: utility functions The window call back runs in the window thread, of course. The other Haskell thread handles "the configuration" - send it a message asking about some configuration attribute, it replies with value of that attribute. The configuration data accumulates in this thread's receive/send loop, avoiding the need for module-global, mutable configuration state that I don't know how to implement. If I wouldn't do that in a real application, I would sure do the same kind of thing with a service socket connection, for example - i.e., use a separate thread to avoid stalling the whole application waiting for network input, and use messages to communicate with it from other threads. It worked fine until I added that Haskell thread. The only problem then is that on normal termination of the application, the top level Haskell "main = cmain" will actually go on after "cmain" returns, jumping to where the configuration thread was, waiting for input from the message port, when it died. I can fix that by calling exit() from cmain(), rather than returning, so at this point it's just a curious behavior. But I'm probably asking for trouble, working the runtime concurrently from different threads, and the only reason it seems to work as well as it does is because there isn't any actual concurrent computation in this example program. So what I expected I would have to do, was something similar to what Python and I believe ocaml do, a thread interlock that serializes access from different threads to the runtime, The thread that holds the lock runs until an I/O operation, then releases the lock, and tries to get it back after the I/O completes. Now that I think about it, I guess that would mean among other things that I couldn't use much native Haskell I/O, but I'm not far away from that anyway. I'm thinking it doesn't matter if different threads are involved with the runtime, as long as it isn't concurrently. Donn Cave, donn@avvanta.com From Malcolm.Wallace at cs.york.ac.uk Thu Oct 16 11:08:19 2008 From: Malcolm.Wallace at cs.york.ac.uk (Malcolm Wallace) Date: Thu Oct 16 11:04:44 2008 Subject: [nhc-users] FFI "wrapper" In-Reply-To: <20081015065016.B88ACF393F@mail.avvanta.com> References: <20081015065016.B88ACF393F@mail.avvanta.com> Message-ID: <20081016160819.78f0c509.Malcolm.Wallace@cs.york.ac.uk> Donn, > a thread > interlock that serializes access from different threads to the > runtime, The thread that holds the lock runs until an I/O operation, > then releases the lock, Provided we are talking about a single sequential processor, then concurrent thread access to the heap should be largely OK I guess, because heap values are immutable. The only thing the RTS needs to be careful about is if one thread accesses a heap cell and finds it is blackholed (i.e. currently under evaluation by a different thread), then it should block until the cell is updated. I believe Yhc already does this. However, if there are multiple processors accessing the same shared memory containing the heap, then I suppose the RTS would additionally need to place a lock around an individual cell during the heap-update operation. The GC would also need to stop all threads whilst collecting. Regards, Malcolm