/*
 * --  thread.c.4
 *     Test of pthread_cond_timedwait()
 */
#include <stdlib.h>
#include <stdio.h>
#include <dbgmem.h>
#include <pthread.h>
#include <signal.h>
#include "utils.h"

static int safe = FALSE;

static pthread_t *th;
static pthread_mutex_t mu;
static pthread_cond_t cv;

static void 
cv_timer( struct timespec *ts )
{
	int status, success = SUCCESS;

	status = pthread_mutex_lock( &mu );
	CHECK(status, "pthread_mutex_lock()" );

	while( safe == FALSE )
	{
		status = pthread_cond_timedwait( &cv, &mu, ts );
		CHECK( status, "pthread_cond_timedwait()" );
	}

	status = pthread_mutex_unlock( &mu );
	CHECK(status, "pthread_mutex_unlock()" );

	pthread_exit( (void *) success );
}

int 
main( int argc, char *argv[] )
{
	int i, st, exit_status, thread_count = 1;
	struct timespec *tspec;

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

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

	st = pthread_cond_init( &cv, NULL );
	CHECK( st, "pthread_cond_init()");

	th = malloc_r( thread_count * sizeof( pthread_t ) );
	tspec = malloc_r( thread_count * sizeof( struct timespec ) );

	for(i = 0; i < thread_count; i++ )
	{
		tspec[i].tv_sec = 1;
		tspec[i].tv_nsec = rand() % 9999;

		st =  create_joinable( &th[i], (thread_proc_t) cv_timer, &tspec[i] );
		CHECK( st, "create_joinable()");

		pthread_yield( NULL );
	}

	safe = TRUE;

	for(i = 0; i < thread_count; i++ )
	{
		st = pthread_join( th[i], (void **) &exit_status );
		CHECK( st, "pthread_join()");

		pthread_lock_global_np();
		if( exit_status != SUCCESS )
			fprintf( stderr, "Failed to join with th[%d]!", i);
		else
			printf("th[%d] complete!\n", i );
		pthread_unlock_global_np();
	}

	free_r( th );
	free_r( tspec );

	st = pthread_cond_destroy( &cv );
	CHECK( st, "pthread_cond_destroy()");

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

	print_system_counters();
	return( EXIT_SUCCESS );
}
