The FreeBSD C library is provided as an alternative to the OSKit’s minimal C library (see Section 14) so that more sophisicated applications can be built. It is derived from version 2.2.2. In addition to the standard single threaded version of the library, a multi threaded version is also built which relies on the pthread library (see Section 29) to supply the locking primitives. Both of these libraries can be found in the lib directory as oskit_freebsd_c.a and oskit_freebsd_c_r.a. In order to link with the FreeBSD C library, the application must be compiled against the FreeBSD C header files. Example kernels that are built with the FreeBSD libraries can be found in the examples/extended and examples/threads directories.
The following sections briefly describe the OSKit’s implementation of the FreeBSD C library. Not all of the library is built since some parts do not make sense in the OSKit’s basic environment. Those functions are listed below, as well as a list of the extended initialization functions.
Like the minimal C library, the FreeBSD C library depends on the POSIX library (see Section 20) to provide mappings to the appropriate OSKit COM interfaces. For example, fopen in the C library will chain to open in the POSIX library, which in turn will chain to the appropriate oskit_dir and oskit_file COM operations. Applications that link with the FreeBSD C library must also link with the COM library (but not the POSIX library since that is included as part of the FreeBSD C library archive file). A multi-threaded version of the POSIX library is also provided for applications that link with the multi-threaded version of the FreeBSD C library.
The FreeBSD malloc has been completely replaced with the OSKit’s basic memory allocator. Please refer to to Section 14.5 for a description of the OSKit’s allocator interface. This is a temporary measure; a future release will include a more traditional “fast” memory allocator.
Rudimentary signal support is provided in both the single and multi-threaded versions of the library. As part of the C library initialization, a delivery handler is provided to the kernel library that is used to pass up hardware exceptions (see Section 15.21). Assuming the application has made the necessary calls to sigaction (see Section 20.4 in the POSIX library documentation) to arrange for catching signals, an exception causes the delivery function to be invoked, which converts the machine trap state into a more standard sigcontext structure, and passes that to the application via the signal handler. The application can freely modify the sigcontext structure; the sigcontext is copied back into the trap state when the handler returns, which then becomes the new machine state. Use caution! Note that the default action for all signals is to call panic and reboot the machine. Any hardware exception that that results in a signal that is blocked, also generates a panic and reboot.
Not all of the FreeBSD C library has been compiled. In some cases, the functions missing simply cannot be implemented in the OSKit’s basic environment. In other cases, they are on the yet to be done list, and will eventually be added. The list of the missing functions follows is:
All of the external data representation (xdr) functions, all of the remote procedure call (rpc) functions, gethostid, sethostid, getwd, killpg, setpgrp, setrgid, setruid, sigvec, sigpause, catopen, catclose, catgets, clock, confstr, crypt, ctermid, daemon, devname, errlst, execve, execl, execlp, execle, exect, execv, execvp, getfsent, getfsspec, getfsfile, setfsent, endfsent, getbootfile, getbsize, cgetent, cgetset, cgetmatch, cgetcap, cgetnum, cgetstr, cgetustr, cgetfirst, cgetnext, cgetclose getcwd, getdomainname, getgrent, getgrnam, getgrgid, setgroupent, setgrent, endgrent, getlogin, getmntinfo, getnetgrent, innetgr, setnetgrent, endnetgrent getosreldate, getpass, getpwent, getpwnam, getpwuid, setpassent, setpwent, endpwent, getttyent, getttynam, setttyent, endttyent, getusershell, setusershell, endusershell, getvfsbyname, getvfsbytype, getvfsent, setvfsent, endvfsent, vfsisloadable, vfsload, glob, globfree, initgroups, msgctl, msgget, msgrcv, msgsnd, nice, nlist, ntp_gettime, pause, popen, psignal, user_from_uid, group_from_gid, scandir, seekdir, semconfig, semctl, semget, semop, setdomainname, sethostname, longjmperror, setmode, getmode, shmat, shmctl, shmdt, shmget, siginterrupt, siglist, sleep, sysconf, sysctl, times, timezone, ttyname, ttyslot, ualarm, unvis, usleep, valloc, vis, wait, wait3, and waitpid.
The symbolic constants defined in errno.h have been redefined with the corresponding symbols defined in oskit/error.h (see 4.6.2), which are the error codes used through the OSKit’s COM interfaces; this way, error codes from arbitrary OSKit components can be used directly as errno values at least by programs that use the FreeBSD C library. The main disadvantage of using COM error codes as errno values is that, since they don’t start from around 0 like typical Unix errno values, it’s impossible to provide a traditional Unix-style sys_errlist table for them. However, they are fully compatible with the strerror and perror routines.
The FreeBSD C library (and by extension the POSIX library) derive a number of its external interfaces from the client OS (see Section 13). Rather than relying on linktime dependencies for these interfaces, the C library uses a services database (see Section 5.1) that was provided when it was initialized. This services database is pre-loaded (by the client OS when the kernel boots) with certain COM objects that make the C library functional. One such interface object is the oskit_libcenv_t COM interface, which provides hooks that are very specific to the POSIX and C libraries. This, and other interfaces, are looked up in the database as required. For example, the malloc implementation depends on a lower level “memory object” to satisfy memory requests. The first call to malloc will result in a lookup in the services database for the oskit_mem_t COM object. The malloc routines then use this lower level allocator interface. The intent of this “indirection” is to reduce (eventually to zero) the number of linktime dependencies between the C/Posix library and the rest of the OSKit libraries.
Typically, the C library is initialized by the Client OS library when the kernel boots (See Section 13.) The initialization function is passed a reference to an oskit_services_t COM object (see Section 5.1), which is a services database that has been preloaded with a number of interface objects that the C library needs to operate properly.
oskit_load_libc allows for internal initializatons to be done. This routine must be called when the operating system is initialized, typically from the Client OS library. The services database is used to lookup other interfaces required by the C library, and is maintained as internal state to the library.
oskit_init_libc allows for secondary initializations to be performed by the C library, in cases where lazy initialization is not appropriate. It must be called sometime after oskit_load_libc.