//	Semesterarbeit Topsy TCP/IP
//	Reto Gaehler, Toni Kaufmann
//	Semaphore Module with the following limitations:
//	- smWait tmYield only needed for cooperative environment
//	- smSignal does only increment and not signal any waiting processes

#include "Semaphore.h"

//	semInit
//	initializes a semaphore
//
int semInit(SemaphorePtr pSem,int nsCount)
{
  if (pSem!=NULL)
  {
    lockInit(&pSem->recLock);
    lock(&pSem->recLock);
    pSem->nsCount = nsCount;
    unlock(&pSem->recLock);
    return SEM_OK;
  }
  return SEM_FAILED;
}

//	semReset
//	resets the semaphore counter
//
int semReset(SemaphorePtr pSem,int nsCount)
{
  if (pSem!=NULL)
  {
    lock(&pSem->recLock);
    pSem->nsCount = nsCount;
    unlock(&pSem->recLock);
    return SEM_OK;
  }
  return SEM_FAILED;
}

//	semCount
//	returns the semaphore counter
//
int semCount(SemaphorePtr pSem)
{
  if (pSem!=NULL)
  {
    return pSem->nsCount;
  }
  return SEM_FAILED;
}

//	semWait
//	decrements counter and waits until counter >= 0
//
int semWait(SemaphorePtr pSem)
{
  if (pSem!=NULL)
  {
    lock(&pSem->recLock);
    pSem->nsCount--;
    while (pSem->nsCount<0)
    {
      pSem->nsCount++;
      unlock(&pSem->recLock);
      tmYield();
      lock(&pSem->recLock);
      pSem->nsCount--;
    }
    unlock(&pSem->recLock);
    return SEM_OK;
  }
  return SEM_FAILED;
}

//	semSignal
//	increments counter
//
int semSignal(SemaphorePtr pSem)
{
  if (pSem!=NULL)
  {
    lock(&pSem->recLock);
    pSem->nsCount++;
    unlock(&pSem->recLock);
    return SEM_OK;
  }
  return SEM_FAILED;
}

//	semSignalIfLess
//	special signal for tcp implementation
//
int semSignalIfLess(SemaphorePtr pSem,int cmpValue)
{
  if (pSem!=NULL)
  {
    lock(&pSem->recLock);
    if (semCount(pSem)<cmpValue)
    {
      unlock(&pSem->recLock);
      return semSignal(pSem);
    }
    unlock(&pSem->recLock);
  }
  return SEM_FAILED;
}
