/*
 * Define substitutes for 'pthread' function that were extensions for
 * DECthreads (_np suffix):
 *
 *     pthread_[un]lock_global_np()  Provides a common recursive lock for
 *                                   syncrhonizing entry into unsafe code.
 *
 *     pthread_get_expiration_np()   Initialized a timespec struct for use
 *                                   with pthread_cond_timedwait given a
 *                                   time offset to apply to the current time.
 *
 * This module is not need on Digital UNIX (TRU64) or VMS since they have
 * the DECthreads functions.
 *
 * Author:	David Jones
 * Date:	4-MAR-2000
 */
#define _GNU_SOURCE
#define _UNIX98_SOURCE
#include <sys/time.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
/*
 * Define global lock/unlock functions.  Lock is implemented as a recursive
 * mutex.
 */
static pthread_mutex_t global_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;

extern int pthread_lock_global_np(void)
{
    return pthread_mutex_lock ( &global_lock );
}
extern int pthread_unlock_global_np(void)
{
    return pthread_mutex_unlock ( &global_lock );
}
/***************************************************************************/
/* Define replacement for the pthread_get_expriation_np function, which
 * returns a timespec structure suitable for use with pthread_cond_timedait.
 *
 * The abstime structure will be returned with the current time plus
 * an offset of delta.tv_sec seconds and delta.tv_nsec nanoseconds.
 * Delta must express a positive value, tv_nsec must be in the range
 * 0-999999999.
 */
extern int pthread_get_expiration_np ( 
	    const struct timespec *delta, struct timespec *abstime )
{
    struct timeval now;
    struct timezone tz;
    /*
     * Get the current GMT time and add the offset.
     */
    tz.tz_minuteswest = 0;
    tz.tz_dsttime = 0;
    if ( 0 == gettimeofday ( &now, &tz ) ) {
      abstime->tv_sec = now.tv_sec + delta->tv_sec;
      abstime->tv_nsec = (now.tv_usec*1000) + delta->tv_nsec;
      if ( abstime->tv_nsec > 1000000000 ) {
	/* Carry nanon-second field into seconds field */
	abstime->tv_sec++;
	abstime->tv_nsec = abstime->tv_nsec - (1000000000);
      }
    } else {
      printf("error returned from gettimofday: %d\n", errno );
      return errno;
    }
    return 0;
}
