The library's combine-message handling
The resource manager library handles combine messages by presenting each component of the message to the appropriate handler routines. For example, if we get a combine message that has an _IO_LSEEK and _IO_READ in it (e.g., readblock()), the library will call our io_lseek and io_read handlers for us in turn.
But let's see what happens in the resource manager when it's
handling these messages. With multiple threads, both of the
client's threads may very well have sent in their
atomic
combine messages. Two threads in the
resource manager will now attempt to service those two
messages. We again run into the same synchronization problem
as we originally had on the client end—one thread
can be partway through processing the message and can then
be preempted by the other thread.
The solution? The resource manager library provides callouts to lock the OCB while processing any message (except _IO_CLOSE and _IO_UNBLOCK—we'll return to these). As an example, when processing the readblock() combine message, the resource manager library performs callouts in this order:
- lock_ocb handler
- _IO_LSEEK message handler
- _IO_READ message handler
- unlock_ocb handler
Therefore, in our scenario, the two threads within the resource manager would be mutually exclusive to each other by virtue of the lock—the first thread to acquire the lock would completely process the combine message, unlock the lock, and then the second thread would perform its processing.
Let's examine several of the issues that are associated with handling combine messages.