Adding FFI polling mode

With this option, FFI calls always block until scheme_check_foreign_work
is called by the program embedding Racket.

This is needed for embedding Racket into contexts where you do not
control the event loop, need Racket to make FFI calls, and those FFI
calls must occur on a thread within the event loop. A good example of
this is with OpenGL FFI calls that require the current thread to hold
the OpenGL/EGL context.

An important point about this is that scheme_check_foreign_work will
only execute a single FFI call. So if this is used for OpenGL rendering,
you'll want to run it a lot.
This commit is contained in:
Jay McCarthy 2016-08-03 21:53:22 -04:00
parent 4716a6eb00
commit 96d212d376
5 changed files with 47 additions and 5 deletions

16
racket/src/configure vendored
View File

@ -823,6 +823,7 @@ enable_backtrace
enable_pthread enable_pthread
enable_stackup enable_stackup
enable_bigendian enable_bigendian
enable_ffipoll
enable_gprof enable_gprof
enable_gcov enable_gcov
enable_noopt enable_noopt
@ -1475,6 +1476,7 @@ Optional Features:
--enable-pthread link with pthreads (usually auto-enabled if needed) --enable-pthread link with pthreads (usually auto-enabled if needed)
--enable-stackup assume "up" if stack direction cannot be determined --enable-stackup assume "up" if stack direction cannot be determined
--enable-bigendian assume "big" if endianness cannot be determined --enable-bigendian assume "big" if endianness cannot be determined
--enable-ffipoll only make FFI calls if embedding program explicitly polls
--enable-gprof compile for profiling with gprof (gcc only) --enable-gprof compile for profiling with gprof (gcc only)
--enable-gcov compile to gather gcov statistics (gcc3 only) --enable-gcov compile to gather gcov statistics (gcc3 only)
--enable-strip strip debug on install (usually enabled by default) --enable-strip strip debug on install (usually enabled by default)
@ -2792,6 +2794,11 @@ if test "${enable_bigendian+set}" = set; then :
enableval=$enable_bigendian; enableval=$enable_bigendian;
fi fi
# Check whether --enable-ffipoll was given.
if test "${enable_ffipoll+set}" = set; then :
enableval=$enable_ffipoll;
fi
# AC_ARG_ENABLE(oskit, [ --enable-oskit compile OSKit-based Racket kernel]) # AC_ARG_ENABLE(oskit, [ --enable-oskit compile OSKit-based Racket kernel])
# AC_ARG_ENABLE(smalloskit, [ --enable-smalloskit compile small OSKit-based Racket kernel]) # AC_ARG_ENABLE(smalloskit, [ --enable-smalloskit compile small OSKit-based Racket kernel])
@ -3060,6 +3067,7 @@ show_explicitly_enabled "${enable_extflonum}" "Extflonums"
show_explicitly_disabled "${enable_extflonum}" "Extflonums" show_explicitly_disabled "${enable_extflonum}" "Extflonums"
show_explicitly_enabled "${enable_pthread}" "pthreads" show_explicitly_enabled "${enable_pthread}" "pthreads"
show_explicitly_enabled "${enable_ffipoll}" "ffipoll"
show_explicitly_enabled "${enable_oskit}" "OSKit" show_explicitly_enabled "${enable_oskit}" "OSKit"
show_explicitly_enabled "${enable_smalloskit}" "OSKit small mode" show_explicitly_enabled "${enable_smalloskit}" "OSKit small mode"
@ -6508,6 +6516,14 @@ $as_echo "#define MZ_USE_FUTURES 1" >>confdefs.h
enable_mzrt=yes enable_mzrt=yes
fi fi
############### ffipoll ###################
if test "${enable_ffipoll}" = "yes" ; then
$as_echo "#define MZ_USE_FFIPOLL 1" >>confdefs.h
fi
############## compare-and-swap ################ ############## compare-and-swap ################
if test "${enable_mzrt}" = "yes" ; then if test "${enable_mzrt}" = "yes" ; then

View File

@ -12,6 +12,12 @@
#include <errno.h> #include <errno.h>
#ifdef MZ_USE_FFIPOLL
# define MZ_USE_FFIPOLL_COND 1
#else
# define MZ_USE_FFIPOLL_COND 0
#endif
#ifndef SIZEOF_BOOL #ifndef SIZEOF_BOOL
# define SIZEOF_BOOL 0 # define SIZEOF_BOOL 0
#endif /* SIZEOF_BOOL */ #endif /* SIZEOF_BOOL */
@ -3505,7 +3511,10 @@ static void ffi_call_in_orig_place(ffi_cif *cif, void *c_func, intptr_t cfoff,
to handle those anyway, since the call in the original to handle those anyway, since the call in the original
place may lead to a callback that should run in place may lead to a callback that should run in
this place. */ this place. */
# ifdef MZ_USE_FFIPOLL
# else
check_foreign_work(0); check_foreign_work(0);
# endif
} }
} }
} }
@ -3580,7 +3589,7 @@ static Scheme_Object *ffi_do_call(int argc, Scheme_Object *argv[], Scheme_Object
int i; int i;
intptr_t basetype, offset, *offsets; intptr_t basetype, offset, *offsets;
#ifdef MZ_USE_PLACES #ifdef MZ_USE_PLACES
if (orig_place && (scheme_current_place_id == 0)) if (orig_place && ((scheme_current_place_id == 0) && !MZ_USE_FFIPOLL_COND))
orig_place = 0; orig_place = 0;
#endif #endif
if (!cif) { if (!cif) {
@ -3722,7 +3731,7 @@ static Scheme_Object *foreign_ffi_call(int argc, Scheme_Object *argv[])
int i, nargs, save_errno; int i, nargs, save_errno;
Scheme_Object *lock = scheme_false; Scheme_Object *lock = scheme_false;
# ifdef MZ_USE_PLACES # ifdef MZ_USE_PLACES
int orig_place; int orig_place = MZ_USE_FFIPOLL_COND;
# define FFI_CALL_VEC_SIZE 9 # define FFI_CALL_VEC_SIZE 9
# else /* MZ_USE_PLACES undefined */ # else /* MZ_USE_PLACES undefined */
# define FFI_CALL_VEC_SIZE 8 # define FFI_CALL_VEC_SIZE 8
@ -3757,7 +3766,7 @@ static Scheme_Object *foreign_ffi_call(int argc, Scheme_Object *argv[])
} }
} else } else
save_errno = 0; save_errno = 0;
# ifdef MZ_USE_PLACES # if defined(MZ_USE_PLACES) && !defined(MZ_USE_FFIPOLL)
if (argc > 5) orig_place = SCHEME_TRUEP(argv[5]); if (argc > 5) orig_place = SCHEME_TRUEP(argv[5]);
else orig_place = 0; else orig_place = 0;
# endif /* MZ_USE_PLACES */ # endif /* MZ_USE_PLACES */
@ -3899,6 +3908,9 @@ static Scheme_Object *callback_thunk(void *_qc, int argc, Scheme_Object *argv[])
} }
static void check_foreign_work(int check_for_in_original) static void check_foreign_work(int check_for_in_original)
#ifdef MZ_USE_FFIPOLL
XFORM_SKIP_PROC
#endif
{ {
GC_CAN_IGNORE Queued_Callback *qc; GC_CAN_IGNORE Queued_Callback *qc;
ffi_callback_struct *data; ffi_callback_struct *data;
@ -3933,7 +3945,7 @@ static void check_foreign_work(int check_for_in_original)
} }
#ifdef MZ_USE_PLACES #ifdef MZ_USE_PLACES
if (check_for_in_original && (scheme_current_place_id == 0) && orig_place_mutex) { if (check_for_in_original && ((scheme_current_place_id == 0) || MZ_USE_FFIPOLL_COND) && orig_place_mutex) {
FFI_Orig_Place_Call *todo; FFI_Orig_Place_Call *todo;
void *sh; void *sh;
@ -3967,6 +3979,9 @@ static void check_foreign_work(int check_for_in_original)
} }
void scheme_check_foreign_work(void) void scheme_check_foreign_work(void)
#ifdef MZ_USE_FFIPOLL
XFORM_SKIP_PROC
#endif
{ {
check_foreign_work(1); check_foreign_work(1);
} }

View File

@ -76,6 +76,7 @@ AC_ARG_ENABLE(backtrace, [ --enable-backtrace 3m: support GC backtrace dum
AC_ARG_ENABLE(pthread, [ --enable-pthread link with pthreads (usually auto-enabled if needed)]) AC_ARG_ENABLE(pthread, [ --enable-pthread link with pthreads (usually auto-enabled if needed)])
AC_ARG_ENABLE(stackup, [ --enable-stackup assume "up" if stack direction cannot be determined]) AC_ARG_ENABLE(stackup, [ --enable-stackup assume "up" if stack direction cannot be determined])
AC_ARG_ENABLE(bigendian, [ --enable-bigendian assume "big" if endianness cannot be determined]) AC_ARG_ENABLE(bigendian, [ --enable-bigendian assume "big" if endianness cannot be determined])
AC_ARG_ENABLE(ffipoll, [ --enable-ffipoll only make FFI calls if embedding program explicitly polls])
# AC_ARG_ENABLE(oskit, [ --enable-oskit compile OSKit-based Racket kernel]) # AC_ARG_ENABLE(oskit, [ --enable-oskit compile OSKit-based Racket kernel])
# AC_ARG_ENABLE(smalloskit, [ --enable-smalloskit compile small OSKit-based Racket kernel]) # AC_ARG_ENABLE(smalloskit, [ --enable-smalloskit compile small OSKit-based Racket kernel])
@ -328,6 +329,7 @@ show_explicitly_enabled "${enable_extflonum}" "Extflonums"
show_explicitly_disabled "${enable_extflonum}" "Extflonums" show_explicitly_disabled "${enable_extflonum}" "Extflonums"
show_explicitly_enabled "${enable_pthread}" "pthreads" show_explicitly_enabled "${enable_pthread}" "pthreads"
show_explicitly_enabled "${enable_ffipoll}" "ffipoll"
show_explicitly_enabled "${enable_oskit}" "OSKit" show_explicitly_enabled "${enable_oskit}" "OSKit"
show_explicitly_enabled "${enable_smalloskit}" "OSKit small mode" show_explicitly_enabled "${enable_smalloskit}" "OSKit small mode"
@ -1427,6 +1429,12 @@ if test "${enable_futures}" = "yes" ; then
enable_mzrt=yes enable_mzrt=yes
fi fi
############### ffipoll ###################
if test "${enable_ffipoll}" = "yes" ; then
AC_DEFINE(MZ_USE_FFIPOLL,1,[FFIPoll enabled])
fi
############## compare-and-swap ################ ############## compare-and-swap ################
if test "${enable_mzrt}" = "yes" ; then if test "${enable_mzrt}" = "yes" ; then

View File

@ -82,6 +82,9 @@ typedef unsigned long uintptr_t;
#undef MZ_USE_PLACES #undef MZ_USE_PLACES
#endif #endif
/* Enable FFI polling: */
#undef MZ_USE_FFIPOLL
/* Whether __sync_bool_compare_and_swap() works: */ /* Whether __sync_bool_compare_and_swap() works: */
#undef MZ_CAS_AVAILABLE #undef MZ_CAS_AVAILABLE

View File

@ -5010,7 +5010,7 @@ void scheme_thread_block(float sleep_time)
if (!do_atomic) if (!do_atomic)
scheme_check_future_work(); scheme_check_future_work();
#endif #endif
#if defined(MZ_USE_MZRT) && !defined(DONT_USE_FOREIGN) #if defined(MZ_USE_MZRT) && !defined(DONT_USE_FOREIGN) && !defined(MZ_USE_FFIPOLL)
if (!do_atomic) if (!do_atomic)
scheme_check_foreign_work(); scheme_check_foreign_work();
#endif #endif