The simplest case to consider is a kernel timeout used with the pthread_join() call. Here's how you'd set it up:
/* * part of tt1.c */ #include <sys/neutrino.h> // 1 billion nanoseconds in a second #define SEC_NSEC 1000000000LL int main (void) // ignore arguments { uint64_t timeout; struct sigevent event; int rval; … // set up the event -- this can be done once // This or event.sigev_notify = SIGEV_UNBLOCK: SIGEV_UNBLOCK_INIT (&event); // set up for 10 second timeout timeout = 10LL * SEC_NSEC; TimerTimeout (CLOCK_MONOTONIC, _NTO_TIMEOUT_JOIN, &event, &timeout, NULL); rval = pthread_join (thread_id, NULL); if (rval == ETIMEDOUT) { printf ("Thread %d still running after 10 seconds!\n", thread_id); } …
(You'll find the complete version of tt1.c in the Sample Programs appendix.)
We used the SIGEV_UNBLOCK_INIT() macro to initialize the event structure, but we could have set the sigev_notify member to SIGEV_UNBLOCK ourselves. Even more elegantly, we could pass NULL as the struct sigevent—TimerTimeout() understands this to mean that it should use a SIGEV_UNBLOCK.
If the thread (specified in thread_id) is still running after 10 seconds, then the kernel call will be timed out—pthread_join() will return with an errno of ETIMEDOUT.
You can use another shortcut—by specifying a NULL for the timeout value (ntime in the formal declaration above), this tells the kernel not to block in the given state. This can be used for polling. (While polling is generally discouraged, you could use it quite effectively in the case of the pthread_join()—you'd periodically poll to see if the thread you're interested in was finished yet. If not, you could perform other work.)
Here's a code sample showing a non-blocking pthread_join():
int pthread_join_nb (int tid, void **rval) { TimerTimeout (CLOCK_MONOTONIC, _NTO_TIMEOUT_JOIN, NULL, NULL, NULL); return (pthread_join (tid, rval)); }