A significant advance in the kernel design for BlackBerry 10 OS is the event-handling subsystem. POSIX and its realtime extensions define a number of asynchronous notification methods (for example, UNIX signals that don't queue or pass data, POSIX realtime signals that may queue and pass data, and so on). The kernel also defines additional, BlackBerry 10 OS-specific notification techniques such as pulses. Implementing all of these event mechanisms could have consumed significant code space, so our implementation strategy was to build all of these notification methods over a single, rich, event subsystem.
A benefit of this approach is that capabilities exclusive to one notification technique can become available to others. For example, an application can apply the same queueing services of POSIX realtime signals to UNIX signals. This can simplify the robust implementation of signal handlers within applications.
The events encountered by an executing thread can come from any of three sources:
- A MsgDeliverEvent() kernel call invoked by a thread
- An interrupt handler
- The expiry of a timer
The event itself can be any of a number of different types: BlackBerry 10 OS pulses, interrupts, various forms of signals, and forced unblock events. Unblock is a means by which a thread can be released from a deliberately blocked state without any explicit event actually being delivered.
Given this multiplicity of event types, and applications needing the ability to request whichever asynchronous notification technique best suits their needs, it would be awkward to require that server processes (the higher-level threads from the previous section) carry code to support all these options.
Instead, the client thread can give a data structure, or cookie, to the server to hang on to until later. When the server needs to notify the client thread, it invokes MsgDeliverEvent() and the microkernel sets the event type encoded within the cookie upon the client thread.
The ionotify() function is a means by which a client thread can request asynchronous event delivery. Many of the POSIX asynchronous services (for example, the client-side of the select()) are built on top of ionotify(). When performing I/O on a file descriptor (fd), the thread may choose to wait for an I/O event to complete (for the write() case), or for data to arrive (for the read() case). Rather than have the thread block on the resource manager process that's servicing the read/write request, ionotify() can allow the client thread to post an event to the resource manager that the client thread would like to receive when the indicated I/O condition occurs. Waiting in this manner allows the thread to continue executing and responding to event sources other than just the single I/O request.
The select() call is implemented using I/O notification and allows a thread to block and wait for a mix of I/O events on multiple fd's while continuing to respond to other forms of IPC.
Here are the conditions upon which the requested event can be delivered:
- _NOTIFY_COND_OUTPUT—there's room in the output buffer for more data.
- _NOTIFY_COND_INPUT—resource-manager-defined amount of data is available to read.
- _NOTIFY_COND_OBAND—resource-manager-defined out of band data is available.
Last modified: 2015-03-31