## mythryl-callable-c-library-interface.pkg
#
# See also:
# src/c/h/mythryl-callable-c-libraries.h
# Compiled by:
#
src/lib/std/src/standard-core.sublibstipulate
package it = inline_t; # inline_t is from
src/lib/core/init/built-in.pkg package rt = runtime; # runtime is from
src/lib/core/init/runtime.pkg package sg = string_guts; # string_guts is from
src/lib/std/src/string-guts.pkg package lst = list; # list is from
src/lib/std/src/list.pkg #
in = list::in;
herein
package mythryl_callable_c_library_interface
: Mythryl_Callable_C_Library_Interface # Mythryl_Callable_C_Library_Interface is from
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.api {
# for runtime see
#
src/lib/core/init/core.pkg #
src/lib/core/init/runtime.pkg # src/c/machine-dependent/prim.intel32.asm
Cfunction = rt::asm::Cfunction;
find_cfun = rt::asm::find_cfun; # Maps ultimately to find_cfun in src/c/lib/mythryl-callable-c-libraries.c
exception CFUN_NOT_FOUND String;
cfuns__local = REF ([]: List(String)); # See Note[1] at bottom of file.
redirected_cfuns__local = REF ([]: List(String)); # " ".
restore_syscalls__local = REF ([]: List(Void -> Void)); # A list of thunks which collectively restore all redirected syscalls to original direct form.
fun restore_redirected_syscalls_to_direct_form () # Restore all redirected syscalls to direct form by evaluating all thunks on restore_syscalls__local list.
=
{ apply' *restore_syscalls__local {. #f (); };
#
restore_syscalls__local := [];
};
stipulate
fun add_name_to_namelist namelist name # 'namelist' is either cfuns__local or redirected_cfuns__local;
= # 'name' is "posix_io::writebuf" or such.
if (not (name in *namelist)) # We don't do mutex-type locking here because we should only be called early in bootstrapping, in a single-hostthread/single-app-thread context.
#
namelist := name ! *namelist;
fi;
herein
fun note_cfun name = add_name_to_namelist cfuns__local name; # Track all cfuns active in the codebase.
fun note_redirected_cfun name = add_name_to_namelist redirected_cfuns__local name;
end;
fun find_c_function { lib_name, fun_name }
=
{ cfun = find_cfun (lib_name, fun_name);
#
if (it::cast cfun == 0)
print ("mythryl_callable_c_library_interface::find_c_function could not find " + lib_name + ":" + fun_name + "\n");
raise exception CFUN_NOT_FOUND (sg::cat [lib_name, "::", fun_name]);
fi;
\\ x = (rt::asm::call_cfun (cfun, x));
};
fun find_c_function' { lib_name, fun_name } # See background comments in
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.api =
(refcell, redirect_refcell)
where
function = find_c_function { lib_name, fun_name };
name = lib_name + "::" + fun_name;
refcell = REF function;
note_cfun name; # Track all cfuns active in the codebase.
fun redirect_refcell f
=
{ note_redirected_cfun name; # Track all redirected cfuns in the codebase.
refcell := f { lib_name, # Construct and install new implementation of this syscall.
fun_name,
io_call => function
};
};
end;
fun find_c_function'' { lib_name, fun_name } # See background comments in
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.api =
(function, refcell, redirect_refcell)
where
function = find_c_function { lib_name, fun_name };
name = lib_name + "::" + fun_name;
refcell = REF function;
note_cfun name; # Track all cfuns active in the codebase.
fun redirect_refcell f
=
{ note_redirected_cfun name; # Track all redirected cfuns in the codebase.
refcell := f { lib_name, # Construct and install new implementation of this syscall.
fun_name,
io_call => function
};
};
fun restore_syscall ()
=
refcell := function;
restore_syscalls__local
:=
restore_syscall ! *restore_syscalls__local;
end;
fun find_c_function''' { lib_name, fun_name } # See background comments in
src/lib/std/src/unsafe/mythryl-callable-c-library-interface.api =
(function, refcell, redirect_refcell, mailop_function, mailop_refcell, redirect_mailop_refcell)
where
function = find_c_function { lib_name, fun_name };
name = lib_name + "::" + fun_name;
refcell = REF function;
note_cfun name; # Track all cfuns active in the codebase.
fun redirect_refcell f
=
{ note_redirected_cfun name; # Track all redirected cfuns in the codebase.
refcell := f { lib_name, # Construct and install new implementation of this syscall.
fun_name,
io_call => function
};
};
fun restore_syscall ()
=
refcell := function;
restore_syscalls__local
:=
restore_syscall ! *restore_syscalls__local;
msg = "error: " + name + " not yet redirected.\n";
mailop_function = (\\ _ = raise exception DIE msg);
mailop_refcell = REF mailop_function;
fun redirect_mailop_refcell f
=
{ note_redirected_cfun name; # Track all redirected cfuns in the codebase.
mailop_refcell := f { lib_name, # Construct and install new implementation of this syscall.
fun_name,
io_call => function # NOT mailop_function!
};
};
fun restore_mailop_syscall ()
=
mailop_refcell := mailop_function;
restore_syscalls__local
:=
restore_mailop_syscall ! *restore_syscalls__local;
end;
System_Constant = { id: Int, name: String }; # This structure is exposed to clients.
exception SYSTEM_CONSTANT_NOT_FOUND String;
# Linear scan down list,
# checking for string equality
# on list_element.name:
#
fun find_system_constant (name, system_constants: List(System_Constant))
=
search system_constants
where
fun search (system_constant ! rest)
=>
if (system_constant.name == name) THE (system_constant: System_Constant);
else search rest;
fi;
search [] => NULL;
end;
end;
fun bind_system_constant (name, l)
=
case (find_system_constant (name, l))
#
THE sc => sc;
NULL => raise exception SYSTEM_CONSTANT_NOT_FOUND name;
esac;
}; # package mythryl_callable_c_library_interface
end;
############################################################
# Note[1] 2012-04-18
#
# There is a bootstrap problem in that the running Mythryl
# system starts with no application threads and one posix
# thread (i.e., a normal Unix process) but winds up as a
# dozen or so posix threads supporting possibly thousands
# of application threads.
#
# Stuff like disk I/O has to work in both contexts, but
# the multi-hostthread, multi-thread solution we use once
# fully booted clearly cannot be operational initially.
#
# Consequently to provide Mythryl-level access to C-level
# I/O (more generally, C-level syscalls to kernel services)
# we use two different implementations:
#
# o During initial bootstrap we just do vanilla
# single-hostthread single-thread syscalls -- trivial
# except for the usual issues of communicating
# between the Mythryl and C levels.
#
# o Once we have posix-thread and application-thread
# support fully booted, we switch over to indirecting
# all syscalls through that machinery. This means that
# when a Mythryl app-thread invokes a function which
# needs to perform a syscall to the kernel:
#
# 1) It calls a library fn which hides the following from it.
#
# 2) A message is sent to a separate posix-thread;
# the app-thread blocks waiting for a threadmail reply.
#
# 3) The sacrificial posix I/O thread does the actual
# syscall. This will block it dead for maybe milliseconds,
# but app-threads in the main hostthread will be able to
# keep running, since the main hostthread is not blocked.
#
# 4) After the syscall returns, the sacrificial posix I/O
# thread forwards the result to the main posix hostthread
# via posix-thread mutex/condvar mechanisms.
#
# 5) In due course the main posix hostthread then wakes up
# the original app-thread by forwarding the reply via
# the threadmail system.
#
# To make this bi-mode system work we indirect each syscall
# through a refcell which can initially point to a trivial
# fn which just directly invokes the syscall in question,
# but which higher-level libraries can later change to
# point to a closure which performs the indirect I/O instead.
#
# One possible engineering problem with this is making sure
# that every such refcell does get properly updated during
# bootstrap; there are quite a few of them and they are
# scattered through a number of files and then updated by
# various bits of logic scattered through yet other files.
#
# To track all Mythryl-visible syscalls in the codebase we use
#
# cfuns__local
#
# and then to track redirected syscalls we maintain the matching
#
# redirected_cfuns__local
#
# At the end of system bootstrap these lists should be identical
# up to ordering: If they are not something needs fixing.
#
# (It would be convenient to make these lists be redblack
# sets-of-strings, but we are a very low-level facility
# here and I don't want introduce a dependency upon
# higher-level packages like the redblack trees.)
## COPYRIGHT (c) 1994 AT&T Bell Laboratories.
## Subsequent changes by Jeff Prothero Copyright (c) 2010-2015,
## released per terms of SMLNJ-COPYRIGHT.