fifo.c 4.4 KB
Newer Older
Benoit Steiner's avatar
Benoit Steiner committed
1 2 3 4 5 6 7 8 9
/* VideoLAN VLANbridge: fifo for thread communication
 *
 * Benoit Steiner, ECP, <benny@via.ecp.fr>
 *
 * To-do-list : Create a FIFO for communications with others threads
                Make a database that holds the state of each computer
*/


10 11 12 13
/* For Solaris */
#include <sys/types.h>
#include <sys/socket.h>

Benoit Steiner's avatar
Benoit Steiner committed
14
#include <stdlib.h>
15
#include <stdio.h>
Benoit Steiner's avatar
Benoit Steiner committed
16
#include <pthread.h>
17
#include <string.h>
Benoit Steiner's avatar
Benoit Steiner committed
18 19 20
#include <net/if.h>
#include <netinet/in.h>

21
#include "debug.h"
Benoit Steiner's avatar
Benoit Steiner committed
22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
#include "log.h"
#include "fifo.h"
#include "define.h"

#define MOD_NAME MOD_VLANBRIDGE



/***************************************************************************/
/* Create the FIFO							   */
/***************************************************************************/
struct s_Fifo* FifoCreate()
{
  /* Create the structure used to describe the fifo state */
  struct s_Fifo* psfFifo = malloc(sizeof(struct s_Fifo));

  if (psfFifo != NULL)
  {
    /* Initialise the fifo */
    psfFifo->psrWhereToPull = psfFifo->asrData;
    psfFifo->psrWhereToPush = psfFifo->asrData;
    psfFifo->iSize = 0;

    /* Initialise the mutex used to access the data */
    pthread_mutex_init(&psfFifo->FifoLock, NULL);
47
    pthread_cond_init(&psfFifo->FifoSignal, NULL);
Benoit Steiner's avatar
Benoit Steiner committed
48 49
  }
  else
50
    Log(LOG_ERROR, MOD_NAME, "Could not create FIFO");
Benoit Steiner's avatar
Benoit Steiner committed
51 52 53 54 55 56 57 58

  return psfFifo;
}


/***************************************************************************/
/* Destroy the FIFO							   */
/***************************************************************************/
59
int FifoDestroy(struct s_Fifo* psfFifo)
Benoit Steiner's avatar
Benoit Steiner committed
60
{
61
  int iRc = pthread_mutex_destroy(&psfFifo->FifoLock);
62
//  printf("FIFO mutex destruction: %s\n", strerror(iRc));
63

64
  iRc |= pthread_cond_destroy(&psfFifo->FifoSignal);
65
//  printf("FIFO cond destruction: iRc %d, %s\n", iRc, strerror(iRc));
66

67
  free(psfFifo);
Benoit Steiner's avatar
Benoit Steiner committed
68

69
  return iRc;
Benoit Steiner's avatar
Benoit Steiner committed
70 71 72 73 74 75 76 77 78 79 80 81
}


/***************************************************************************/
/* Add an element in the FIFO						   */
/* Two thread can push something at the the same time			   */
/***************************************************************************/
int FifoPush(struct s_Fifo* psfFifo, struct s_Request* psrToStore)
{
  /* Keep the lock during the complete operation */
  int iRc = pthread_mutex_lock(&psfFifo->FifoLock);

82 83 84
  ASSERT(psfFifo);
  ASSERT(psrToStore);

Benoit Steiner's avatar
Benoit Steiner committed
85 86 87 88
  if (!iRc)
  {
//    printf ("fifo Size: %d\n", psfFifo->iSize);
    
89
    if (psfFifo->iSize < FIFO_SIZE)
Benoit Steiner's avatar
Benoit Steiner committed
90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
    {
      /* Add the element: no lock is needed, for readed data are not the ones we write */
      *(psfFifo->psrWhereToPush) = psrToStore;
      
      /* Update the WhereToPush pointer */
      if (++(psfFifo->psrWhereToPush) > psfFifo->asrData + FIFO_SIZE-1)
      {
	/* We must roll to the 1st element of the array */
	psfFifo->psrWhereToPush = psfFifo->asrData;
      }
          
      /* The buffer has now grown */
      psfFifo->iSize++;
 
      /* Wake up any thread waiting by a call to pull */
      iRc = pthread_cond_signal(&psfFifo->FifoSignal);
    }
    else
    {
#ifdef DEBUG
      Log(LOG_NOTE, MOD_NAME, "FIFO full");
#endif
      iRc = BUFFER_FULL;
    }
  }

  /* Unlock te mutex for we have finished */
  iRc |= pthread_mutex_unlock(&psfFifo->FifoLock);

  return iRc;
}


/***************************************************************************/
/* Get 1st element of the FIFO						   */
/* Be carefull not to pull two at the same time, it won't work		   */
/***************************************************************************/
int FifoPull(struct s_Fifo* psfFifo, struct s_Request** psrTask)
{
  int iRc = pthread_mutex_lock(&psfFifo->FifoLock);

131 132 133
  ASSERT(psfFifo); 
  ASSERT(psrTask);

Benoit Steiner's avatar
Benoit Steiner committed
134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
  if (!iRc)
  {
    if (psfFifo->iSize == 0)
    {
      /* Wait for something to be pushed in the stack */
      iRc = pthread_cond_wait(&psfFifo->FifoSignal, &psfFifo->FifoLock);
    }
    
    /* Release the lock */
    iRc |= pthread_mutex_unlock(&psfFifo->FifoLock);
 
    if (!iRc)
    {
      /* Read the element: no lock is needed, for written data are not the ones we read */
      *psrTask = *(psfFifo->psrWhereToPull);

      /* Update the WhereToPull pointer */
      if (++(psfFifo->psrWhereToPull) > psfFifo->asrData + FIFO_SIZE-1)
      {
	/* We must roll to the 1st element of the array */
	psfFifo->psrWhereToPull = psfFifo->asrData;
      }
      
      /* The iSize member can also be accessed by a push, so lock it */
      pthread_mutex_lock(&psfFifo->FifoLock);
      psfFifo->iSize--;
      pthread_mutex_unlock(&psfFifo->FifoLock);
    }
  }

  return iRc;
}