About Signals
In order to support real-time applications that require fast notifications, similar to interrupts, the signal system has been adapted as a way for device drivers and programs to signal other processes.
Signals in particular are rather tricky to implement. They work a lot like interrupts but they're actually emulated. With real interrupts the processor stacks registers and jumps as a response to some event by itself. With signals the context switcher is responsible for stacking the registers and manipulating the program state so that it executes the signal handler instead. In order to return from a signal handler a special syscall is used that makes the kernel restore the programs context to what is was before which is what the trampoline syscall is for.
Userspace Quirks
Signals within the embedded OS works just like their Linux counterparts for the most part with a notable exception: although a program may use multiple different signals, only one handler may be registered at any given time. This is to save space within the process control structures. As a consequence the signal handler in the user application must handle all signal types used either with an if-else or switch-case.
Kernel Implementation
Supporting signals are a combined effort between the scheduler (in scheduler.c) and the process code (in process.c). Device drivers that wish to signal a user program when something happens may do so using either the pid (more versatile) or the ProcessControl pointer (faster).