   M/s runtime library
Benjamin Hanser (bwh2124)
=========================

To build and run the test, run test/test_all.sh.

To compile manually, first run make in this directory, and then in the test
directory.  This builds the runtime libraries and tests, and performs 
linking.  To test, run test/master [PORT] and test/slave [[HOST] PORT].

The runtime consists of two libraries, libmsmaster.a and libmsslave.a, 
against which user code will be linked.  

The code that links against libmaster.a must have no main and must instead 
supply void master().  Master may currently call two functions: 

    int start_job(uint32_t ord, uint8_t *data, uint32_t len)
    Starts a job given by ordinal ord, with serialized data of length len,
    and returns the jid of the created job.  This function does not block,
    but the job may not be sent to the slave right away. 

    void reap_job(int jid, uint8_t **data, uint32_t *len)
    Blocks until the job given by jid is terminated.  Returns serialized
    return data in *data, and returns its length in *len.  On error, *data
    is set to NULL and *len is set to 0.

The code that links against libslave.a must supply code for the jobs and
must supply the job table (called job_funcs).

Jobs have the following signature:
    void j(uint8_t *in_d, uint32_t in_l, uint8_t **out_d, uint32_t *out_l)
    Takes in serialized arguments pointed by in_d, of length in_l, and 
    returns its result in *out_d, of length *out_l.

The slave must declare the job table (job_funcs) as follows:
    void (*job_funcs [])(uint8_t *, uint32_t, uint8_t **, uint32_t *) 
        = {job_1, job_2, job_3, job_4};
    Each entry in the initializer list is the name of a job, ie a function
    pointer to that job, and the order in which they are given determines
    the ordinal of the job (starting at 1).

The slave must finally provide the number of jobs as follows:
    int num_jobs =  (sizeof(job_funcs) / sizeof(*job_funcs));

Note that the user is ENTIRELY responsible for all serialization code. This
is because serialization of data is intimately connected to actually 
gathering it from its various locations in memory, and so it makes sense
for the user compiler to generate this code.

