


# pthread.pkg
#
# For background, see "Overview" comments in src/lib/std/src/pthread.api#
# Mythryl-level interface to support for parallel computation
# via kernel threads (on Linux, Posix threads).
#
# We are the Mythryl side of the
#
# src/c/lib/pthread/libmythryl-pthread.c
#
# interface to functionality defined in the pthread section of
#
# src/c/h/runtime-base.h
#
# and implemented in
#
# src/c/pthread/pthread-on-posix-threads.c # pthread build on top of modern posix threads interface.
# Compiled by:
# src/lib/std/src/standard-core.sublibstipulate
package ci = mythryl_callable_c_library_interface; # mythryl_callable_c_library_interface is from src/lib/std/src/unsafe/mythryl-callable-c-library-interface.pkg package fat = fate; # fate is from src/lib/std/src/nj/fate.pkg package psx = posix_1003_1b; # posix_1003_1b is from src/lib/std/src/posix-1003.1b/posix-1003-1b.pkg package w1u = one_word_unt_guts; # one_word_unt_guts is from src/lib/std/src/one-word-unt-guts.pkg #
fun cfun fun_name
=
ci::find_c_function { lib_name => "pthread", fun_name };
herein
package pthread
: (weak) Pthread # Pthread is from src/lib/std/src/pthread.api {
# We allocate our pthread, mutex, condvar and barrier values
# on the C heap because having the Mythryl garbage
# collector moving them around seems like a really
# really bad idea -- see src/c/lib/pthread/libmythryl-pthread.c
#
# At the Mythryl level we represent them as C
# addresses encoded as unsigned integer values:
#
Barrier = tagged_int::Int;
Condvar = tagged_int::Int;
Mutex = tagged_int::Int;
Pthread = tagged_int::Int;
#
# In practice Pthread is currently implemented as an index into
# our pthread_table__global[] table which is
# declared in src/c/h/runtime-base.h
# defined in src/c/main/runtime-state.c
# and used mostly by
# pth__pthread_create and
# pth__pthread_exit in src/c/pthread/pthread-on-posix-threads.c
Try_Mutex_Result = ACQUIRED_MUTEX | MUTEX_WAS_UNAVAILABLE;
exception MAKE_PTRHEAD;
# Return number of cores on host CPU,
# for use in deciding how many posix
# threads to run in parallel when
# doing cpu-bound computations:
#
fun get_cpu_core_count () # We support this fn in this api partly to put it where it is expected
= # and partly because we may need this call on platforms (Windows?) where
w1u::to_int (psx::sysconf "NPROCESSORS_ONLN"); # sysconf "NPROCESSORS_ONLN" is not supported -- if so, at that point
# we can switch to per-platform drivers without breaking client code.
# Here we're looking up fns in
# the table constructed in
#
# src/c/lib/pthread/libmythryl-pthread.c
#
join_pthread = cfun "join_pthread": Pthread -> Void;
spawn_pthread' = cfun "spawn_pthread": fat::Fate(Void) -> Pthread; # Private to this file.
#
fun spawn_pthread void_to_void
=
spawn_pthread' (fat::make_isolated_fate void_to_void); # Hide the "fate::" stuff because for almost all users it will just be distracting clutter.
stipulate # We need this little two-step because we'll get complaints
foo = cfun "pthread_exit"; # from the typechecker (due to the "value restriction")
herein # if we just do my pthread_exit: Void -> X = cfun "release_pthread" here.
pthread_exit = (unsafe::cast foo): Void -> X ;
end;
get_pthread_id = cfun "get_pthread_id": Void -> Int;
make_mutex = cfun "mutex_make": Void -> Mutex;
free_mutex = cfun "mutex_free": Mutex -> Void;
acquire_mutex = cfun "mutex_lock": Mutex -> Void;
release_mutex = cfun "mutex_unlock": Mutex -> Void;
try_mutex' = cfun "mutex_trylock": Mutex -> Bool; # This is not exported to clients -- we export try_mutex (below) instead.
make_barrier = cfun "barrier_make": Void -> Barrier;
free_barrier = cfun "barrier_free": Barrier -> Void;
set_barrier' = cfun "barrier_init": (Barrier, Int) -> Void; # 'Int' is number of threads which must arrive at barrier before it will release them.
wait_on_barrier = cfun "barrier_wait": Barrier -> Bool; # Exactly one pthread waiting on barrier gets a TRUE return value.
make_condvar = cfun "condvar_make": Void -> Condvar;
free_condvar = cfun "condvar_free": Condvar -> Void;
wait_on_condvar = cfun "condvar_wait": (Condvar, Mutex) -> Void;
signal_condvar = cfun "condvar_signal": Condvar -> Void;
broadcast_condvar = cfun "condvar_broadcast": Condvar -> Void;
fun try_mutex mutex # Returning a Bool is too confusing, so we use a custom datatype for clarity.
=
if (try_mutex' mutex) MUTEX_WAS_UNAVAILABLE; # I got these two backwards the first time around, confirming that the Bool value is confusing. :-) -- 2011-12-05 CrT
else ACQUIRED_MUTEX;
fi;
fun with_mutex_do mutex thunk
=
{ acquire_mutex mutex;
#
result = thunk ();
#
release_mutex mutex;
#
result;
}
except x = { release_mutex mutex;
#
raise exception x;
};
fun set_barrier { barrier, threads }
=
set_barrier' (barrier, threads); # We do not actually need to repackage the record
# as a tuple -- they have the same heap structure anyhow.
# But for clarity we do so anyway, for the moment at least.
};
end;
## Code by Jeff Prothero: Copyright (c) 2010-2012,
## released under Gnu Public Licence version 3.


