Simple demo of pthread, including a mutex

/* simple pthread demo, including a mutex
*
*/
#include <stdio.h>
#include <stdlib.h>     // atoi()
#include <string.h>     // strncpy(), strncat(), strlen()
#include <pthread.h>
#include <unistd.h>       // usleep()

struct ThreadInfo {
    int value;
    char *name;
    //unsigned ymin, ymax, xsize;
    //char *current, *next;
} ;

// Global, shared memory:
char message[1000];
pthread_mutex_t msg_mutex;

// the worker function - runs in each thread
void *ftn(void *vp)
{
    struct ThreadInfo *tip = vp;
    for (int j = tip->value; j >= 0; j--)
        printf("%s sez: %d\n", tip->name, j);

    /*
    * mutex protects a critical section:
    */
    pthread_mutex_lock( &msg_mutex );
    strncat(message, tip->name, 1000-strlen(message));

    /*
    * Illustrate the need for a critical section:
    * comment out the mutex lock and unlock, and see what happens
    */
    usleep(100000);

    strncat(message, "!\n", 1000-strlen(message));
    pthread_mutex_unlock( & msg_mutex );

    return NULL;
}


int main(int argc, char **argv)
{
    if (argc < 2) {
        fprintf(stderr, "oops\n");
        return 1;
    }
    int counter = atoi(argv[1]);

    sprintf(message, "main %d\n", counter);

    /*
    * Make some threads --- could also make an array of threads,
    * then start them (and join them) using a for loop.
    */
    pthread_t pa, pb, pc;

    // Set up the arguments to each thread's function:
    struct ThreadInfo tia, tib, tic;    // objects

    tia.value = counter;
    tia.name = "Larry";

    tib.value = counter+1;
    tib.name = "Curly";

    tic.value = counter+2;
    tic.name = "Moe";

    // Set up the mutex.  No special attributes needed...
    pthread_mutex_init( &msg_mutex, NULL );

    // Fire off the threads.  Could also be done with a loop.
    pthread_create(&pa, NULL, ftn, &tia);
    pthread_create(&pb, NULL, ftn, &tib);
    pthread_create(&pc, NULL, ftn, &tic);

    // Wait for all the threads to finish.  Could also be done with a loop.
    pthread_join(pc, NULL);
    pthread_join(pa, NULL);
    pthread_join(pb, NULL);

    // Clean up...
    pthread_mutex_destroy( &msg_mutex );

    // Show the contents of the critical section:
    printf("-->%s<--\n", message);

    printf("main() is done.\n");
    return 0;
}