/*------------------------------------------------------------------------
 *
 *  File:	o1k_thread.cc
 *  Revision:	1.4
 *  Last Mod:	17:13:24, 03/05/97
 *
 *  Description:
 *     Implementation of O1kThread object
 *     
 *----------------------------------------------------------------------*/
#pragma ident	"@(#)o1k_thread.cc	1.4\t97/03/05  "

#include <stdio.h>
#include <string.h>
#include <poll.h>

#include "o1k_thread.h"
#include "o1k_misc.h"

extern int verbose;

/*------------------------------------------------------------------------
 *
 *  Function:	O1kThread::O1kThread()
 *
 *  Description:
 *     Constructor for thread object
 *     
 *  Parameters:
 *     char* n  : name for thread
 *     
 *----------------------------------------------------------------------*/

O1kThread::O1kThread(char* n)
{
  handle = 0;
  enabled = FALSE;
  stopped = TRUE;

  strncpy(name, n, O1K_THREAD_NAME_SIZE);
}

/*------------------------------------------------------------------------
 *
 *  Function:	O1kThread::~O1kThread()
 *
 *  Description:
 *     Destructor for thread object
 *     
 *----------------------------------------------------------------------*/

O1kThread::~O1kThread()
{
  if (enabled && !stopped)
    stop();
}

/*------------------------------------------------------------------------
 *
 *  Function:	O1kThread::start()
 *
 *  Description:
 *     Start the thread. This routine waits until thread
 *     has started. When thread starts, it should set
 *     stopped to FALSE.
 *   
 *  Parameters:
 *     O1kThrdFunc func : thread start function
 *     void* arg        : thread arg
 *
 *
 *  Notes:
 *    There is no timeout on waiting for the thread to start.
 * 
 *----------------------------------------------------------------------*/

int O1kThread::start(O1kThrdFunc func, void* arg)
{
  int rval;

  if (verbose) printf("start thread %s\n",name);
  
  enabled = TRUE;
  stopped = TRUE;

  if ((rval = thr_create(NULL,            /* use default stack base */
                         NULL,            /* use default stack size */
                         func,            /* thread start function */
                         arg,             /* arg */
                         THR_NEW_LWP,     /* create a new lwp */
                         &handle          /* thread handle */
                         )) != 0){
    
    fprintf(stderr,"Create  thread %s failed %x\n",name, rval);
    enabled = FALSE;
    stopped = TRUE;
    return -1;
  }

  /* wait for thread to start */
  while (stopped)
    poll(0,0,5);

  return 0;
}

/*------------------------------------------------------------------------
 *
 *  Function:	O1kThread::stop()
 *
 *  Description:
 *     Stop thread. Set enabled flag to false, this will cause
 *     thread to exit. When thread exits, it should set stopped
 *     to true.
 *   
 *----------------------------------------------------------------------*/

int O1kThread::stop()
{
  double timeout_time = o1k_msec_time() + 5000;
  
  if (verbose) printf("stop thread %s\n",name);

  enabled = FALSE;
  while (!stopped && (o1k_msec_time() < timeout_time)){
    o1k_msec_sleep(5); /* suspend this thread */
  }

  if (!stopped){
    fprintf(stderr,"========= Thread %s Failed To Stop =========\n",name);
    return -1;
  }
  
  if (verbose) printf("+++++++++ Thread %s Stopped Ok +++++++++\n",name);
  
  return 0;
}
