#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include "error_msg.h"

#define DEFAULT_ITERATIONS ((int) 1)

static void    init_mu( pthread_mutex_t *mu );
static void    destroy_mu( pthread_mutex_t *mu );
static void    lock( void );

static pthread_mutex_t mutex;
static pthread_t       th;

int 
main( int argc, char *argv[] )
{
   int i, st, iterations = DEFAULT_ITERATIONS;

   if( argc == 2 )
       iterations = atoi( argv[1] );

   init_mu( &mutex );

   /*
    *  --  Test the lock and unlock services
    */
   for(i = 0; i < iterations; i++ )
   {
       st = pthread_mutex_lock( &mutex );
       CHECK(st, "pthread_mutex_lock()");

       st = pthread_mutex_unlock( &mutex );
       CHECK(st, "pthread_mutex_unlock()");
   }

   /*
    *  --  Lock the mutex, then create a thread that attempts to
    *      lock the mutex.  Release the mutex and allow the child
    *      thread to proceed.
    */
   st = pthread_mutex_lock( &mutex );
   CHECK(st, "pthread_mutex_lock()");

   st = pthread_create( &th, NULL, (thread_proc_t) lock, NULL );
   CHECK(st, "pthread_create()");

   st = pthread_mutex_unlock( &mutex );
   CHECK(st, "pthread_mutex_unlock()");

   sched_yield();
   destroy_mu( &mutex );
   return( EXIT_SUCCESS );
}

static void
init_mu( pthread_mutex_t *mu )
{
   int st;

   st = pthread_mutex_init( mu, NULL );
   CHECK( st, "pthread_mutex_init()");
}

static void
destroy_mu( pthread_mutex_t *mu )
{
   int st;

   st = pthread_mutex_destroy( mu );
   CHECK(st, "pthread_mutex_destroy()");
}

static void 
lock( void )
{
   int st;

   st = pthread_mutex_lock( &mutex );
   CHECK(st, "pthread_mutex_lock()");

   st = pthread_mutex_unlock( &mutex );
   CHECK(st, "pthread_mutex_unlock()");

   pthread_exit( (void *) SUCCESS );
}
