chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Chicken-users] "Dynamically Loading" non-entry-point code


From: Felix Winkelmann
Subject: Re: [Chicken-users] "Dynamically Loading" non-entry-point code
Date: Wed, 23 Jun 2004 09:43:00 +0200
User-agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.6) Gecko/20040113

Daniel B. Faken wrote:

By what I can infer from your example, it should work. The important
issue is to make sure no calls from Scheme to C into Scheme happen, that might
trigger a garbage collection without saving some context data (like the
continuation of the outermost Scheme context).
The other important issue is that, for GC to work, a "restart" trampoline
has to be established, so that once a minor GC has been run, something
is there that can be longjmp'd to.
And yet another important issue is that a minor GC may not simply remove
live C stack frames.


Are you speaking in general, or are these GC concerns only for this library-initialization business?

The concerns apply both to entry-points into libraries and callbacks:
since the runtime-system allocates storage on the C stack and because
it will unwind the stack once it's full, we have to make sure something
has been set up to unwind to.


I should have added a __callback in front of the _scmif_run_toplevel function (eqv. of your run_foo_unit) -- does this address the concerns
you speak of?


__callback (or using foreign-callback-lambda[*]) just makes sure
the calling Scheme code saves it's continuation somewhere, so that,
should a GC occur inside a callback from C to Scheme, the continuation
will be properly scanned by the collector. So if no Scheme is calling
scmif_run_toplevel, nothing will have to be saved.

I guess I should Read The Fine Source; I was just hoping it would behave similarly to the other FFI mechanisms in Chicken..


Yeah, it's a little bit complicated, partly because Chicken does so
nasty things to the C stack (well, not really nasty, but nasty for
normal C code that has to coexist with it).
This should be documented much better than it is now, sorry.


Its very similar to the way I was calling the toplevel function:

#>!
__callback static int _scmif_do_C_cb(void *fn_ptr, void *data)
{
  int (*fn)(void *) = fn_ptr;
  assert(fn_ptr);
  return fn(data);
}
<#

(define-embedded "static"
  (scmif_ep_safe_callback (c-pointer fn) (c-pointer data)) int
  (_scmif_do_C_cb fn data))

#>
int scmif_safe_callback(int (*fn)(void *), void *data)
{
  assert(fn);

  if(CHICKEN_is_running())
    return fn(data);
  else
    return scmif_ep_safe_callback((void *)fn, data);
}
<#

..the idea is that if the user has a Scheme function thats been exported to C, s/he defines a wrapper for it:
static int call_my_scm_fn(void *data)
{
  mydata *d = (mydata *)data;
  special_scheme_function(d->name, d->rank, d->turkey);
}

..and then calls
  scmif_safe_callback(call_my_scm_fn, foo);

..and so the function is always called from within scheme (i.e. within a toplevel context).

Of course, I wish I didn't have to write a wrapper function - but this allows fairly general, efficient behaviour without more work on the FFI's part (like defining things such as a variant of scmif_safe_callback for each possible C function signature, or generating some wrapper code around each exported C function).

Thoughts?


Thanks! I have to dig into this some more, trying to understand
all possible implications.


cheers,
felix





reply via email to

[Prev in Thread] Current Thread [Next in Thread]