Redesign of our initialization path for libs (XCC)
authorKevin Klues <klueska@cs.berkeley.edu>
Thu, 25 Jun 2015 22:32:04 +0000 (15:32 -0700)
committerKevin Klues <klueska@cs.berkeley.edu>
Fri, 26 Jun 2015 04:36:28 +0000 (21:36 -0700)
commit0aec214ff62e1b42cdc949a9255dbbb80d292b4c
tree3c909a3c79b57019aeab485dae9ff17338ade5e8
parentdf4ae5573f29e3b578ca430cab1a8676b8172f05
Redesign of our initialization path for libs (XCC)

Previously there was a big mismatch of how we performed various
initialization for our various libraries, such as vcores, uthreads,
pthreads, etc.

We now do initialization based on libc *constructors* functions as
defined with an __attribute__((constructor)) attribute.  Doing
initalizaton this way makes things more consistent, as well as ensures
that evertything we want to have initialized gets initialized early on in
the lifetime of an application, while at the same time allowing us to
easily add per-library initialization simply by linking in some extra
libraries.

We previously had a hodgepodge of workarounds to essentially try and
give us this functionality, none of which worked very well (mostly based
on overwriting weak symbols and/or calling certain functions (i.e.
vcore_event_init()) in places that made following the logic of
initialization confusing).  Now all startup initialization occurs via
*constructor* functions with the name '*_lib_init()' and depenencies are
preserved using 'init_once_racy()' calls as the very first call in each
of these functions, followed by calls to the specific *_lib_init()
functions they depend on. Following this discipline, all *_lib_init()
functions will be called *exactly* once, and all of them will be called
in the proper order (even if they get called multiple times, they will
only execute once due to the init_once_racy() call). The hacky call to
vcore_event_init() in _start is now completely eliminated with this
design.

As part of this redesign, a few modifications were also made to separate
out what it really means to "initailize" a uthread and "initialize" a
pthread vs. both intitializing these constructs as well as transitioning
into an MCP. Previously, initializing the uthread library implicitly
turned you into an MCP.  Now there is an explicit call for
uthread_mcp_init() (which is also wrapped by pthread_mcp_init()), who's
sole purpose is to transition a process into an MCP that is
uthread/pthread ready. It is this functionality that we *actually*
needed to ensure was executed whenever we first call pthread_create()
and friends, not the simple initialization of thread0 to become a
uthread/pthread (that now happens inside our new constructor
functions at startup time).  Moreover, the old uthread_lib_init() is now
called uthread_2ls_init() in order to accommodate the new naming
convention, and it does essentially the same thing it did before (minus
the automatic transition into an MCP).

Because of this change in semantics, all tests that were previously
calling pthread_lib_init() explicitly (rather than relying on
pthread_create() to call it implicitly) must now call pthread_mcs_init()
instead.  This is actually more intuitive, given what its purpose is.
24 files changed:
tests/lock_test.c
tests/mcp_halt.c
tests/mhello.c
tests/old/condvar_test.c
tests/old/fpperf.cc
tests/old/syscall.c
tests/pthread_barrier_test.c
tests/pthread_switch.c
tests/pthread_test.c
tests/vmm/virtioconsole.c
tests/vmm/virtiopiocons.c
tests/vmm/virtiostress.c
tests/vmm/vmmcp.c
tests/vmm/vmmcpkernel.c
tests/vmm/vmrunkernel.c
tests/vmm/vmrunkernelmmap.c
tools/compilers/gcc-glibc/glibc-2.19-akaros/sysdeps/akaros/start.c
user/parlib/include/uthread.h
user/parlib/include/vcore.h
user/parlib/uthread.c
user/parlib/vcore.c
user/pthread/pthread.c
user/pthread/pthread.h
user/utest/pvcalarm.c