Listing 3 (lidar_acq.c)
/* ---
   lidar_acq task.  This is the task synchronization task.
   This program initialiazes shared memory and the message
   queues for the real-time portion of the lidar program.
--- */

#include    "lidar.h"

main()
{
    int     i, j, trigger_fd, alive_sem, shm_seg_id;
    int     avail_qid, graph_qid, read_qid, write_qid;
    message mptr;
    trigger_clock cycles;

    /* --- set routine priority --- */
    setpriority (PRIO_PROCESS, 0, LIDAR_ACQ);

    /* --- open task alive semaphore --- */
    alive_sem = sem_get(ALIVE_KEY, 0); 

    /* --- open message queues --- */
    avail_qid = msgget (AVAILABLE_Q, 0666 | IPC_CREAT);
    graph_qid = msgget (GRAPHICS_Q, 0666 | IPC_CREAT);
    read_qid = msgget (READ_Q, 0666 | IPC_CREAT);
    write_qid = msgget (WRITE_Q, 0666 | IPC_CREAT);

    /* --- create shared memory segment ids --- */
    shm_seg_id = shmget (FB_KEY, FRAME_SIZE * N_FRAMES, 
                         0666 | IPC_CREAT);

    /* --- create messages for shared memory 
           indexing  and place them in the available
           message queue --- */
    for (i = 0; i < N_FRAMES; i++) {
        mptr.key = i;
        if (msgsnd (avail_qid, &mptr, MSG_SIZE, 0) < 0) {
           printf ("Queue problem.\n");
           exit (1);
           }
        }

    /* --- wait for the read, write, and graph 
           tasks to check in --- */
    sem_wait (alive_sem);
    sem_wait (alive_sem);
    sem_wait (alive_sem);

    /* --- open trigger timing device and set to
           10 Hz for N_RUNS pulses --- */
    trigger_fd = open("/dev/tclock", O_RDWR);
    cycles.count = 250;         /* 250 cycles = .1 sec */
    cycles.int_count = N_RUNS;  /* number of pulses    */
    i = write (trigger_fd, &cycles, 4);

    /* --- real time data acquisition loop --- */
    for (i = 0; i < N_RUNS; i++) {
        /* --- wait for trigger --- */
        if (read (trigger_fd, &cycles, 2)) {
            printf ("Missed a pulse. Fatal Error\n");
            break;
            }

        /* --- get a free frame buffer --- */
        j = msgrcv (avail_qid, &mptr, MSG_SIZE, 0, IPC_NOWAIT);

        /* --- if there aren't any available buffers --- */
        if (j < 0) {
            /* --- remove all of the frame buffers
                   from the graph message queue and
                   place them in the available queue  --- */
            while (msgrcv(graph_qid, &mptr, MSG_SIZE, 
                   ANYTYPE, IPC_NOWAIT) >= 0) 
               msgsnd (avail_qid, &mptr, MSG_SIZE, 0);

            /* --- if there still are no buffers,
                   fatal error has occured -- */
            if (msgrcv (avail_qid, &mptr, MSG_SIZE,
                        ANYTYPE, IPC_NOWAIT) == -1) {
               printf ("Fatal queue problem. Terminating\n");
               break;
               }
            }

        /* --- start the acquisition process --- */
        msgsnd (read_qid, &mptr, MSG_SIZE, IPC_NOWAIT);
        }
   
    /* --- terminate data acquisition --- */
    close(trigger_fd);

    /* --- signal other processes to quit --- */
    mptr.key = QUIT;
    msgsnd (read_qid, &mptr, MSG_SIZE, NOFLAGS);

    /* --- wait for all messages to be placed
            on available Q and retire --- */ 
    for (i = 0; i < N_FRAMES; i++) 
       msgrcv(avail_qid, &mptr, MSG_SIZE, ANYTYPE, NOFLAGS);

    /* --- and the terminate message --- */
    msgrcv (avail_qid, &mptr, MSG_SIZE, ANYTYPE, NOFLAGS);

    /* --- delete queues --- */
    msgctl (avail_qid, IPC_RMID, 0);
    msgctl (read_qid, IPC_RMID, 0);
    msgctl (write_qid, IPC_RMID, 0);
    msgctl (graph_qid, IPC_RMID, 0);

    /* --- release semaphore --- */
    sem_delete (ALIVE_KEY);

    /* --- delete shared memory segments --- */
    shmctl (shm_seg_id, IPC_RMID, 0);
}
