Implementing Semaphores in Cyclone
For this project, it should be reasoanble to implement the semaphores
part in Cyclone. I've set up the kernel
to include a Cyclone file called cycsem.cyc in the src/geekos
directory, along with sem.h in the include/geekos directory. You
can implement your code within these files, and then call it from
geekos/syscall.c.
Calling Cyclone code from C
To call a Cyclone function from C code, we must take
into account that
the Cyclone function might throw an exception (like an array bounds
violation or a null pointer exception, as in Java). We have therefore
provided two macros to simplify calling Cyclone from C. These are
provided in geekos/cyclone.h. To call a Cyclone function
f(es) which returns void, use the syntax
void_cyc_call(f(es)). If the Cyclone function throws an
exception, then void_cyc_call will return its name, as a
string. Otherwise it will return NULL. For example, to call the
Cyclone function foo with argument arg, we would
do:
#include <geekos/cyclone.h> // for void_cyc_call
#include <geekos/screen.h> // for Print
...
char *exn = void_cyc_call(foo(arg));
if (exn)
Print("Oops! Cyclone function threw an exception %s!\n",exn);
Note that the Cyclone compiler, when compiling Cyclone code to C code
(which is then compiled to assembly), it prepends every Cyclone
function with the prefix Cyc_. Therefore, the
void_cyc_call and cyc_call macros prepend this
prefix to the function call provided. This also means that when
writing headers for Cyclone routines called by C, you need to put the
Cyc_ in front of each routine declared in the header. Look at geekos/sem.h as an example.
The cyc_call macro is similar, except that you must also
provide it with a variable to store the value returned from the
Cyclone function. For example, if the Cyclone function
foo returns an integer, then we would call it as follows:
#include <geekos/cyclone.h> // for void_cyc_call
#include <geekos/screen.h> // for Print
...
int ret = 0;
char *exn = cyc_call(ret,foo(arg));
if (exn)
Print("Oops! Cyclone function threw an exception %s!\n",exn);
At the conclusion of this code, if exn is NULL, then
ret contains the value returned from the Cyclone code,
otherwise it will contain 0.
An example of how this is used is in
the Sys_P function in geekos/syscall.c, to call the P() function
defined within your cycsem.cyc file.
Calling C code from Cyclone
Calling C functions from Cyclone is
straightforward, and is described in the Cyclone manual. You will
need to do this to, among other things, call kthread functions from
cycsem.cyc to implement semaphores. There are two choices for
creating a "conduit" to call C code from Cyclone:
Use buildlib.
This is a tool that sucks in a C header file, and based on a
specification that you provide, generates a Cyclone version of the
header. This Cyclone version is then included by a Cyclone file,
and calls to functions defined in that header are as if to other
Cyclone functions. We use buildlib during the build process of
the Cyclone kernel. Look at the headers placed in the include/libc/cyclone directory
to see what is generated, and look at include/libc/cyclone/cyclib.cys
to see the specification file. More details about buildlib are in
the manual.
Use extern "C
include". This facility allows you to
declare C code within your Cyclone file, and make its functions
available to be called from Cyclone code. Note that C code can
always be called directly from Cyclone code (you do not need to use
macros like cyc_call). You
can see some examples in the Cyclone
manual. For
this project, you'd do something like:
extern "C include" {
#include <geekos/kthread.h>
} export { fun1, fun2, ...; }
The code inside the first set of braces is regular C code, and the
export statement indicates that it should be callable from
Cyclone. Note that all typedefs,
struct definitions, #defines,
etc. are exported by default; you do not need to put them in the export
list. In
general, it may turn out that the C type in the geekos file you are
including does not correspond to the Cyclone type that you need.
For example, C does not specify zero-termination or other qualifiers
that Cyclone does. There is a facility for defining Cyclone types
to override the C codes, called cyclone_override,
that is described in
the manual. Beware that you should not #include geekos/string.h or
geekos/malloc.h, since
these could result in problematic types (but
your mileage may vary). Instead, include libc/cyclone/string.h as
shown in the sample cycsem.cyc file, and core.h.
Web Accessibility