26.02.2014 Views

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

Getting Started with QNX Neutrino - QNX Software Systems

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

Writing a resource manager<br />

© 2009, <strong>QNX</strong> <strong>Software</strong> <strong>Systems</strong> GmbH & Co. KG.<br />

Unfortunately, if someone forgot to obtain a mutex for each and every file descriptor<br />

operation, there’d be a possibility that such an “unprotected” access would cause a<br />

thread to read or write data to the wrong location.<br />

Let’s look at the C library call readblock() (from ):<br />

int<br />

readblock (int fd,<br />

size_t blksize,<br />

unsigned block,<br />

int numblks,<br />

void *buff );<br />

(The writeblock() function is similar.)<br />

You can imagine a fairly “simplistic” implementation for readblock():<br />

int<br />

readblock (int fd, size_t blksize, unsigned block,<br />

int numblks, void *buff)<br />

{<br />

lseek (fd, blksize * block, SEEK_SET); // get to the block<br />

read (fd, buff, blksize * numblks);<br />

}<br />

Obviously, this implementation isn’t useful in a multi-threaded environment. We’d<br />

have to at least put a mutex around the calls:<br />

int<br />

readblock (int fd, size_t blksize, unsigned block,<br />

int numblks, void *buff)<br />

{<br />

pthread_mutex_lock (&block_mutex);<br />

lseek (fd, blksize * block, SEEK_SET); // get to the block<br />

read (fd, buff, blksize * numblks);<br />

pthread_mutex_unlock (&block_mutex);<br />

}<br />

(We’re assuming the mutex is already initialized.)<br />

This code is still vulnerable to “unprotected” access; if some other thread in the<br />

process does a simple non-mutexed lseek() on the file descriptor, we’ve got a bug.<br />

The solution to this is to use a combine message, as we discussed above for the<br />

chown() function. In this case, the C library implementation of readblock() puts both<br />

the lseek() and the read() operations into a single message and sends that off to the<br />

resource manager:<br />

_IO_LSEEK<br />

_IO_READ<br />

The readblock() function’s combine message.<br />

The reason that this works is because message passing is atomic. From the client’s<br />

point of view, either the entire message has gone to the resource manager, or none of it<br />

has. Therefore, an intervening “unprotected” lseek() is irrelevant — when the<br />

readblock() operation is received by the resource manager, it’s done in one shot.<br />

218 Chapter 5 • Resource Managers April 30, 2009

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!