# include <ucr/fault.h> extern void set_fault(unsigned num, ucr_fault_handler, void*arg); extern const FAULT_RECORD* get_fault(THREAD*tid);
When a thread faults for any reason, uCR saves a pointer to the FAULT_RECORD in the THREAD structure, and tries to dispatch the fault to a fault handler. If no handler exists, the default behavior for the fault is invoked, usually an abort. The application uses the set_fault() function to install a fault handler.
The FAULT_RECORD and the fault codes depend on the target at hand, so writing portable fault handlers may be difficult. All the definitions of the record and codes are in the TARGET/include/ucr/fault_asm.h header file.
Fault handlers are special in that they can be called at almost any time like interrupt handlers, but are natural parts of a thread. A faulting thread pushes the fault stack frame on its own stack and calls the service routine. The service routine, being part of the thread, can do anything that the thread can do, including call blocking operations such as ISync::sleep().
However, the fault handler can be asynchronous enough to cause synchronization problems with the current thread, and there is no way to block faults. Therefore, fault handlers cannot safely share resources with the thread that it is interrupting, except the THREAD struct and the FAULT_RECORD of the thread itself. After all, as long as the fault hander is in progress the thread cannot do anything.