Kernel timeouts with pthread_join()

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 sigeventTimerTimeout() 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));
}