/************************************************************************/
/* Copyright 2002 MBARI							*/
/************************************************************************/
/* Summary  : Semaphore library for OASIS3				*/
/* Filename : sem.c							*/
/* Author   : Robert Herlien (rah)					*/
/* Project  : OASIS Mooring Replacement (OASIS3)			*/
/* Revision: 0.1							*/
/* Created  : 10/14/2002						*/
/*									    */
/* MBARI provides this documentation and code "as is", with no warranty,    */
/* express or implied, of its quality or consistency. It is provided without*/
/* support and without obligation on the part of the Monterey Bay Aquarium  */
/* Research Institute to assist in its use, correction, modification, or    */
/* enhancement. This information should not be published or distributed to  */
/* third parties without specific written permission from MBARI.            */
/*									    */
/************************************************************************/
/* Modification History:						*/
/* 10oct2002 rah - created from OASIS task.c				*/
/************************************************************************/
/************************************************************************/
/* This is a simple semaphore library to accompany the NON-PREEMPTIVE	*/
/* task scheduler contained in task.c for the Persistor CF2.		*/
/* This file implements counting semaphores.  Read the notes in task.c	*/
/* for cautions about using the non-preemptive task scheduler.		*/
/************************************************************************/

#include <mbariTypes.h>			/* MBARI type definitions	    */
#include <mbariConst.h>			/* MBARI constants		    */
#include <oasis.h>			/* OASIS controller definitions	    */
#include <io.h>				/* OASIS I/O definitions	    */
#include <list.h>			/* OASIS linked list definitions    */
#include <sem.h>			/* OASIS semaphore definitions	    */ 
#include <task.h>			/* OASIS linked list definitions    */


/************************************************************************/
/* Function    : sem_init						*/
/* Purpose     : Initialize a semaphore					*/
/* Inputs      : Semaphore ID, initial count				*/
/* Outputs     : None							*/
/************************************************************************/
	Void
sem_init( SemID sem, SemType semtype, Int16 count )
{
  list_init( &(sem->sem_list) );
  sem->sem_type = semtype;
  sem->sem_cnt = (semtype == COUNTING) ? count : 1;

} /* sem_init() */


/************************************************************************/
/* Function    : sem_take						*/
/* Purpose     : Take a semaphore					*/
/* Inputs      : Semaphore ID						*/
/* Outputs     : None							*/
/************************************************************************/
	Void
sem_take( Reg SemID sem )
{
  Reg TaskDesc	*td;

  if ( sem->sem_cnt > 0 )		/* If semaphore not exhausted	*/
    (sem->sem_cnt)--;			/*    take it			*/
  else
  {					/* Semaphore gone		*/
    td = unready();			/* Get our TaskDesc		*/
    td->td_state = PENDING;		/* Mark us pending		*/
    td->td_sem = sem;			/* Show which semaphore		*/
    list_add(&(sem->sem_list), (Node *)td); /* Put us on sempahore list*/
    do_dispatch( td );			/* Dispatch next task		*/
  }

} /* sem_take() */


/************************************************************************/
/* Function    : sem_give						*/
/* Purpose     : Give a semaphore					*/
/* Inputs      : Semaphore ID						*/
/* Outputs     : None							*/
/************************************************************************/
	Void
sem_give( Reg SemID sem )
{
    if ( sem->sem_list.lst_head == NULLNODE )
	sem->sem_cnt++;			/* If nobody waiting, incr count*/
    else				/* else ready top of wait list	*/
	ready( (TaskDesc *)list_head(&sem->sem_list) );

} /* sem_give() */
