setjmpx, longjmpx, and clrjmpx Kernel Services
The setjmpx kernel service provides a way to save the following portions of the program state at the point of a call:
- Nonvolatile general registers
- Stack pointer
- TOC pointer
- Interrupt priority number (intpri)
- Ownership of kernel-mode lock
This state can be restored later by calling the longjmpx kernel service, which accomplishes the following tasks:
- Reloads the registers (including TOC and stack pointers)
- Enables or disables to the correct interrupt level
- Conditionally acquires or releases the kernel-mode lock
- Forces a branch back to the point of original return from the setjmpx kernel service
The setjmpx kernel service takes the address of a jump buffer (a label_t structure) as an explicit parameter. This structure can be defined anywhere including on the stack (as an automatic variable). After noting the state data in the jump buffer, the setjmpx kernel service pushes the buffer onto the top of a stack that is maintained in the machine-state save structure.
The longjmpx kernel service is used to return to the point in the code at which the setjmpx kernel service was called. Specifically, the longjmpx kernel service returns to the most recently created jump buffer, as indicated by the top of the stack anchored in the machine-state save structure.
The parameter to the longjmpx kernel service is an exception code that is passed to the resumed program as the return code from the setjmp kernel service. The resumed program tests this code to determine the conditions under which the setjmpx kernel service is returning. If the setjmpx kernel service has just saved its jump buffer, the return code is 0. If an exception has occurred, the program is entered by a call to the longjmpx kernel service, which passes along a return code that is not equal to 0.
If the exception handler stack is empty when the longjmpx kernel service is issued, there is no place to jump to and the system default exception-handling mechanism is used. If the stack is not empty, the context that is defined by the topmost jump buffer is reloaded and resumed. The topmost buffer is then removed from the stack.
The clrjmpx kernel service removes the top element from the stack as placed there by the setjmpx kernel service. The caller to the clrjmpx kernel service is expected to know exactly which jump buffer is being removed. This should have been established earlier in the code by a call to the setjmpx kernel service. Accordingly, the address of the buffer is required as a parameter to the clrjmpx kernel service. It can then perform consistency checking by asserting that the address passed is indeed the address of the top stack element.