CODSYS.DOC - Information on writing USYS routines. Writing USYS routines: USYS Header Files T20 Defs for USYS I/O routines. T20 Defs for USYS Signal stuff. T20 Defs for USYS TTY stuff. In order to implement signal handling correctly, we have to ensure that no USYS routine has control wrested away from it, leaving internal data in an inconsistent state. For this reason certain rules must be followed: [1] At the START of a USYS routine, invoke the macro USYS_BEG(). This and other USYS_ macros are defined in . [2] When RETURNING from a USYS routine, invoke one of the following macros: USYS_RET(val); Return a local variable or constant value. USYS_RETVOLATILE(val); Return a volatile (global or function) value. USYS_RETERR(err); Return -1, setting errno to "err". USYS_RETINT(); Return -1, setting errno to EINTR. Each of the USYS_RETxxx macros serves as a "return" statement, and each takes care to process any pending signals. If a signal occurred during the USYS routine, it is deferred until the USYS_RETxxx happens, and is then handled just before returning to the user's program. The reason for distinguishing RETVOLATILE from simple RET is because the former case must save the return value in a temporary local-scope location while any pending interrupts are processed. Otherwise, by the time the actual return took place, the return value may have changed from what it should have been! Non-interference: USYS routines are assumed not to interfere in any way with non-USYS library functions. Thus, it is very, VERY bad for a USYS routine to call a C library function which changes static data; the user program will not be expecting this. Note that signal handlers must be able to execute system calls, and any normal C library function could be interrupted. malloc(), in particular, cannot be used by a USYS routine for this reason! JSYS calls: When making a JSYS call, "fast" and "slow" calls need to be distinguished. "fast" calls are those which never block or hang, and for which no asynchronous PSI interrupts are expected to happen; "slow" calls are those which have the potential to hang for indefinite amounts of time, and should be considered interruptible. If using a "slow" call, the JSYS_INTERRUPTABLE flag should be added to the JSYS-number argument in the call to jsys(). The latter will return -1 if the call was interrupted, and in this case the USYS routine should return with USYS_RETINT(). Things are actually a little more complicated than this, as certain calls such as read() and write() must check to see whether they should really be interrupted or if the signal handler permits them to continue what they were doing. This is done by invoking USYS_END() and examining its return value to see what happened. Look at the existing code for read(), write(), and ioctl() for examples.