@node syscalls,machine,reentrancy,Top @chapter NEC V70 system calls The library needs a certain amount of system-specific support in order to operate. These routines have to be written for each unique target environment. For testing purposes, a set of system calls specific to an NEC V70 Unix PC running AT&T Unix System V R2 are included. These files are in the @file{sys/sysvnecv70} directory. All the calls have to be implemented in order to avoid link time errors, but the implementation need not include all possible functionality; in general, for any functionality that isn't available, returning an error code is sufficient. @section Input/Output The V70 target may not have any character I/O devices. In this case, the @code{fstat}, @code{ioctl}, @code{isatty}, @code{lseek}, @code{read} and @code{write} routines may all return @code{-1}, to signal failure (inspect @file{cerror.s} to see how to do this). Sometimes it is correct to implement the functions in a very simple and machine specific way. For instance, the target board may have one serial line. In this case, the @code{write} system call can be ``hard-wired'' to always print to the serial device, no matter what the supplied file handle says. Similarly, the other I/O system calls can be written to take advantage of a known configuration. Note that the library starts up assuming that three files are already open. File handles used are: @table @code @item 0 Is used for all input from @code{stdin}. @item 1 Is used for all output to @code{stdout}. This includes functions like @code{putc} and @code{printf}. @item 2 Is used for all output to @code{stderr}. The library will use this file to print error messages from the math functions. Output can also be sent to @code{stderr} by @code{fprintf(stderr,@dots{})} @end table @section Example @code{write} routine On a board with a very simple I/O structure, this would be adequate: @example @group char *duart_status = DUART_ADDR; void poll() @{ /* Dummy function to fool optimizer */ @} int write(fd, string, len) int fd; char *string; int len; @{ int i; for (i = 0; i < len; i++) @{ while (*duart_status & DUART_BUSY) poll(); *duart_port = string[i]; @} return len; @} @end group @end example @section Memory allocation The library allocates memory from the heap either for its own use, or when you explicitly call @code{malloc}. It asks the system for memory by calling the @code{sbrk} function. On a Unix system, @code{sbrk} keeps track of the heap's extent by keeping a pointer to the end of the @code{bss} section. Unix linkers traditionaly mark the end of @code{bss} by creating a symbol @code{_end}. When the library wants more memory, it calls @code{sbrk} with the size of the request. @code{sbrk} must then perform an operation specific to the target environment, and return a pointer to the new area. For a simple application, the following fragment may be sufficient: @example @group char *moving_end = &end; char *sbrk(request) int request; @{ char *return_address; return_address = moving_end; moving_end += request; return return_address; @} @end group @end example @section Initialization and termination The system dependent support routines are responsible for initializing the library for use by an application, and cleaning up when the application is complete. This functionality is traditionally provided in @code{crt0} and @code{_exit}. The @code{crt0} function usually contains the instructions first run by the operating system when an application starts. The @code{crt0} function can take advantage of this and prepare the way for the libary. Another task for @code{crt0} is to call the @code{main} function provided by the application writer, and also to call @code{exit} if the main function ever returns. @code{exit} tells the operating system that the application has finished.