/*

sem.c - Semaphores

*/

/*...sincludes:0:*/
#include <stdlib.h>
#include "sem.h"

/*...vsem\46\h:0:*/
/*...e*/

/*...sesem_init:0:*/
void esem_init(ESEM *esem)
	{
	list_init(&(esem->waiting));
	}
/*...e*/
/*...sesem_sleep:0:*/
void esem_sleep(ESEM *esem, FIBER *fiber, NF nf, void *nfp)
	{
	fiber->nf  = nf;
	fiber->nfp = nfp;
	list_add_last(&(esem->waiting), fiber);
	}
/*...e*/
/*...sesem_wake:0:*/
void esem_wake(ESEM *esem)
	{
	FIBER *fiber;
	while ( (fiber = (FIBER *) list_remove_first(&(esem->waiting))) != NULL )
		fiber_enqueue(fiber);
	}
/*...e*/

/*...scsem_init:0:*/
void csem_init(CSEM *csem, unsigned count)
	{
	list_init(&(csem->waiting));
	csem->count = count;
	}
/*...e*/
/*...scsem_request:0:*/
void csem_request(CSEM *csem, FIBER *fiber, NF nf, void *nfp)
	{
	if ( csem->count > 0 )
		{
		--(csem->count);
		nf(nfp);
		}
	else
		{
		fiber->nf  = nf;
		fiber->nfp = nfp;
		list_add_last(&(csem->waiting), fiber);
		}
	}
/*...e*/
/*...scsrm_release:0:*/
void csem_release(CSEM *csem)
	{
	FIBER *fiber;
	if ( (fiber = (FIBER *) list_remove_first(&(csem->waiting))) != NULL )
		fiber_enqueue(fiber);
	else
		++(csem->count);
	}
/*...e*/

/*...szsem_init:0:*/
void zsem_init(ZSEM *zsem, unsigned count)
	{
	list_init(&(zsem->waiting));
	zsem->count = count;
	}
/*...e*/
/*...szsem_sleep:0:*/
void zsem_sleep(ZSEM *zsem, FIBER *fiber, NF nf, void *nfp)
	{
	if ( zsem->count == 0 )
		nf(nfp);
	else
		{
		fiber->nf  = nf;
		fiber->nfp = nfp;
		list_add_last(&(zsem->waiting), fiber);
		}
	}
/*...e*/
/*...szsem_dec:0:*/
void zsem_dec(ZSEM *zsem)
	{
	if ( --(zsem->count) == 0 )
		{
		FIBER *fiber;
		while ( (fiber = (FIBER *) list_remove_first(&(zsem->waiting))) != NULL )
			fiber_enqueue(fiber);
		}
	}
/*...e*/
