/*
 *
 * Author: Tero Kivinen <kivinen@iki.fi>
 *
 * Copyright (c) 2000 SSH Communications Security Oy <info@ssh.fi>
 */
/*
 *        Program: Util Lib
 *        $Source: /ssh/CVS/src/lib/sshutil/ssheloop/unix/sshmt_pthreads.c,v $
 *        $Author: kivinen $
 *
 *        Creation          : 21:21 Feb 19 2000 kivinen
 *        Last Modification : 00:21 Feb 24 2000 kivinen
 *        Last check in     : $Date: 2000/02/24 01:01:14 $
 *        Revision number   : $Revision: 1.1 $
 *        State             : $State: Exp $
 *        Version           : 1.166
 *
 *        Description       : Posix mutexes and multithread
 *                            environment support. 
 *
 *
 *        $Log: sshmt_pthreads.c,v $
 *        $EndLog$
 */

/* Tru64 pthreads does not work if XOPEN_SOURCE is defined. */

#ifdef _XOPEN_SOURCE_EXTENDED
#undef _XOPEN_SOURCE_EXTENDED
#define SAVED_XOPEN_SOURCE_EXTENDED
#endif /* _XOPEN_SOURCE_EXTENDED */

#ifdef _XOPEN_SOURCE
#undef _XOPEN_SOURCE
#define SAVED_XOPEN_SOURCE
#endif /* _XOPEN_SOURCE */

#include <pthread.h>
/* We must include strings.h here because otherwise we get conflict later */
#include <strings.h>

#ifdef SAVED_XOPEN_SOURCE_EXTENDED
#undef _XOPEN_SOURCE_EXTENDED
#define _XOPEN_SOURCE_EXTENDED 1
#undef SAVED_XOPEN_SOURCE_EXTENDED
#endif /* SAVED_XOPEN_SOURCE_EXTENDED */

#ifdef SAVED_XOPEN_SOURCE
#undef _XOPEN_SOURCE
#define _XOPEN_SOURCE 1
#undef SAVED_XOPEN_SOURCE
#endif /* SAVED_XOPEN_SOURCE */

#include "sshincludes.h"
#include "ssheloop.h"
#include "sshtimeouts.h"
#include "sshmutex.h"

/* NOTE: Do not use debug prints here, because the debugging system might be
   using mutexes to protect itself. */

#undef SSH_DEBUG_MODULE

/* Mutex type, the actual contents is system dependent */
struct SshMutexRec {
  char *name; 
  pthread_mutex_t mutex;
};

/* Allocate mutex and initialize it to unlocked state. Currently no flags
   defined. Name is the name of the mutex, it is only used for debugging. This
   function will take a copy of the name. The name can also be NULL. */
SshMutex ssh_mutex_create(const char *name, SshUInt32 flags)
{
  SshMutex mutex;
  int err;
  mutex = ssh_xcalloc(1, sizeof(*mutex));
  if (name)
    mutex->name = ssh_xstrdup(name);
  err = pthread_mutex_init(&(mutex->mutex), NULL);
  if (err != 0)
    ssh_fatal("Mutex init failed: %s", strerror(err));
  return mutex;
}

/* Destroy mutex. It is fatal error to call this if mutex is locked. */
void ssh_mutex_destroy(SshMutex mutex)
{
  int err;
  err = pthread_mutex_destroy(&(mutex->mutex));
  if (err != 0)
    ssh_fatal("Mutex destroy failed: %s", strerror(err));
  ssh_xfree(mutex->name);
  ssh_xfree(mutex);
}

/* Locks the mutex. If the mutex is already locked then this will block until
   the mutex is unlocked. */
void ssh_mutex_lock(SshMutex mutex)
{
  int err;

  err = pthread_mutex_lock(&(mutex->mutex));
  if (err != 0)
    ssh_fatal("Mutex lock failed: %s", strerror(err));
}

/* Unlocks the mutex. It is fatal error to call this function if the mutex is
   already unlocked. Also only the original thread that took the lock is
   allowed to unlock it. */
void ssh_mutex_unlock(SshMutex mutex)
{
  int err;

  err = pthread_mutex_unlock(&(mutex->mutex));
  if (err != 0)
    ssh_fatal("Mutex lock failed: %s", strerror(err));
}

/* Returns the name of the mutex. This returns NULL if the mutex does not have
   name. */
const char *ssh_mutex_get_name(SshMutex mutex)
{
  return mutex->name;
}

