Using the _NTO_MI_UNBLOCK_REQ
Luckily, the kernel keeps track of the flag for you as a single bit in the message info structure (the struct _msg_info that you pass as the last parameter to MsgReceive(), or that you can fetch later, given the receive ID, by calling MsgInfo()).
This flag is called _NTO_MI_UNBLOCK_REQ and is set if the client wishes to unblock (for example, after receiving a signal).
This means that in a multithreaded server, you'd typically have a worker
thread that's performing the client's work, and another thread that's going
to receive the unblock message (or some other message; we'll just focus on the
unblock message for now).
When you get the unblock message from the client, you'd set a flag to yourself,
letting your program know that the worker thread wishes to unblock.
There are two cases to consider:
- the
worker
thread is blocked; or - the
worker
thread is running.
If the worker thread is blocked, you'll need to have the thread that got the unblock message awaken it. It might be blocked if it's waiting for a resource, for example. When the worker thread wakes up, it should examine the _NTO_MI_UNBLOCK_REQ flag, and, if set, reply with an abort status. If the flag isn't set, then the thread can do whatever normal processing it does when it wakes up.
Alternatively, if the worker thread is running, it should periodically check
the flag to self
that the unblock thread may have set, and if
the flag is set, it should reply to the client with an abort status.
Note that this is just an optimization: in the unoptimized case, the worker
thread would constantly call MsgInfo
on the receive ID and
check the _NTO_MI_UNBLOCK_REQ bit itself.