Multi-ApplicationOnlineProfiling  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Buffered_FIFO.c
Go to the documentation of this file.
1 /* ############################ MALP License ############################## */
2 /* # Fri Jan 18 14:00:00 CET 2013 # */
3 /* # Copyright or (C) or Copr. Commissariat a l'Energie Atomique # */
4 /* # # */
5 /* # This software is governed by the CeCILL-C license under French law # */
6 /* # and abiding by the rules of distribution of free software. You can # */
7 /* # use, modify and/ or redistribute the software under the terms of # */
8 /* # the CeCILL-C license as circulated by CEA, CNRS and INRIA at the # */
9 /* # following URL http://www.cecill.info. # */
10 /* # # */
11 /* # The fact that you are presently reading this means that you have # */
12 /* # had knowledge of the CeCILL-C license and that you accept its # */
13 /* # terms. # */
14 /* # # */
15 /* # Authors: # */
16 /* # - BESNARD Jean-Baptiste jean-baptiste.besnard@cea.fr # */
17 /* # # */
18 /* ######################################################################## */
19 #include "Buffered_FIFO.h"
20 #include <stdlib.h>
21 #include <string.h>
22 
23 uint64_t Buffered_FIFO_count(struct Buffered_FIFO *fifo)
24 {
25  uint64_t ret = 0;
26 
27  MALP_Spinlock_lock( &fifo->lock );
28  ret = fifo->elem_count;
29  MALP_Spinlock_unlock( &fifo->lock );
30 
31  return ret;
32 }
33 
35  uint64_t chunk_size, uint64_t elem_size )
36 {
37  ch->lock = 0;
38  ch->chunk_size = chunk_size;
39  ch->elem_size = elem_size;
40  ch->start_offset = 0;
41  ch->end_offset = 0;
42 
43  ch->payload = malloc( chunk_size * elem_size );
44 
45  if( !ch->payload )
46  {
47  perror( "malloc" );
48  exit(1);
49  }
50 
51  ch->prev = NULL;
52 }
53 
55 {
56  struct Buffered_FIFO_chunk *ret = malloc( sizeof( struct Buffered_FIFO_chunk ) );
57 
58  if( !ret )
59  {
60  perror( "malloc" );
61  exit( 1 );
62  }
63 
64  Buffered_FIFO_chunk_init( ret, chunk_size, elem_size );
65 
66  return ret;
67 }
68 
69 
71 {
72  free( ch->payload );
73  memset( ch, 0, sizeof( struct Buffered_FIFO_chunk ) );
74 }
75 
76 void * Buffered_FIFO_chunk_push( struct Buffered_FIFO_chunk *ch, void *elem )
77 {
78  void *ret = NULL;
79 
80  MALP_Spinlock_lock( &ch->lock );
81 
82  /* Do we have free room ? */
83 
84  if( ch->end_offset < ch->chunk_size )
85  {
86  char *dest = ch->payload + ( ch->end_offset * ch->elem_size );
87  ret = dest;
88  memcpy( dest, elem, ch->elem_size );
89  ch->end_offset++;
90  }
91 
92  MALP_Spinlock_unlock( &ch->lock );
93 
94  return ret;
95 }
96 
97 void * Buffered_FIFO_chunk_pop( struct Buffered_FIFO_chunk *ch, void *dest )
98 {
99  void *ret = NULL;
100 
101  MALP_Spinlock_lock( &ch->lock );
102 
103  /* Is there any elem left ? */
104  if( ch->start_offset < ch->end_offset )
105  {
106  char *src = ch->payload + ( ch->start_offset * ch->elem_size );
107  ret = src;
108  memcpy( dest, src, ch->elem_size );
109  ch->start_offset++;
110  }
111 
112  MALP_Spinlock_unlock( &ch->lock );
113 
114  return ret;
115 }
116 
117 
118 
119 void Buffered_FIFO_init(struct Buffered_FIFO *fifo, uint64_t chunk_size, size_t elem_size)
120 {
121  fifo->head_lock = 0;
122  fifo->head = NULL;
123  fifo->tail_lock = 0;
124  fifo->tail = NULL;
125 
126  fifo->chunk_size = chunk_size;
127  fifo->elem_size = elem_size;
128 
129  fifo->lock = 0;
130  fifo->elem_count = 0;
131 }
132 
133 void Buffered_FIFO_release(struct Buffered_FIFO *fifo, void (*free_func) (void *))
134 {
135  struct Buffered_FIFO_chunk * tmp = fifo->head;
136 
137  /* We have a BUG here */
138 
139  memset( fifo, 0, sizeof(struct Buffered_FIFO) );
140 }
141 
142 
143 void *Buffered_FIFO_push(struct Buffered_FIFO *fifo, void *elem)
144 {
145  void *ret = NULL;
146 
147  MALP_Spinlock_lock( &fifo->head_lock );
148  /* Case of empty FIFO */
149  if( fifo->head == NULL )
150  {
151  MALP_Spinlock_lock( &fifo->tail_lock );
152  fifo->head = Buffered_FIFO_chunk_new( fifo->chunk_size, fifo->elem_size );
153  fifo->tail = fifo->head;
155  }
156 
157  while( !ret )
158  {
159 
160  ret = Buffered_FIFO_chunk_push( fifo->head , elem );
161 
162  /* Chunk is full create a new one*/
163  if( !ret )
164  {
165  struct Buffered_FIFO_chunk *new = Buffered_FIFO_chunk_new( fifo->chunk_size, fifo->elem_size );
166  Buffered_FIFO_chunk_ctx_prev( fifo->head, new);
167  fifo->head = new;
168  }
169 
170  }
171 
172  MALP_Spinlock_lock( &fifo->lock );
173  fifo->elem_count++;
174  MALP_Spinlock_unlock( &fifo->lock );
175 
177 
178  return ret;
179 }
180 
181 
182 void *Buffered_FIFO_pop(struct Buffered_FIFO *fifo, void *dest)
183 {
184  void *ret = NULL;
185  MALP_Spinlock_lock( &fifo->tail_lock );
186 
187  if( fifo->tail != NULL )
188  {
189  struct Buffered_FIFO_chunk *target = fifo->tail;
190 
191  while( !ret )
192  {
193  ret = Buffered_FIFO_chunk_pop( target , dest );
194 
195  if( ret )
196  {
197  MALP_Spinlock_lock( &fifo->lock );
198  fifo->elem_count--;
199  MALP_Spinlock_unlock( &fifo->lock );
200  }
201  else
202  {
203  /* Go to previous chunk */
204  struct Buffered_FIFO_chunk *to_free = target;
205 
206  target = Buffered_FIFO_chunk_prev( target );
207 
208 
209  /* Found previous */
210  if( target )
211  {
212 
213  /* Free old block */
214  Buffered_FIFO_chunk_release( to_free );
215  free( to_free );
216  /* Move tail */
217  fifo->tail = target;
218 
219  }
220  else
221  {
222  /* Head is empty */
223 
224  break;
225  }
226 
227  }
228  }
229  }
230 
232 
233  return ret;
234 }
235 
void * Buffered_FIFO_chunk_pop(struct Buffered_FIFO_chunk *ch, void *dest)
pops en element from a chunk
Definition: Buffered_FIFO.c:97
MALP_Spinlock head_lock
a lock for concurent access to the head
MALP_Spinlock tail_lock
a lock for concurent access to the tail
uint64_t chunk_size
the size of the composing chunks
size_t elem_size
the size of each stored element
void Buffered_FIFO_release(struct Buffered_FIFO *fifo, void(*free_func)(void *))
releases a FIFO
This is a struct defining a FIFO It is composed of several Buffered_FIFO_chunk.
void * Buffered_FIFO_push(struct Buffered_FIFO *fifo, void *elem)
Pushes an element into a FIFO.
char * payload
the actual data
Definition: Buffered_FIFO.h:50
void * Buffered_FIFO_pop(struct Buffered_FIFO *fifo, void *dest)
Pops an element from a FIFO.
void * Buffered_FIFO_chunk_push(struct Buffered_FIFO_chunk *ch, void *elem)
Pushes an element into a chunk.
Definition: Buffered_FIFO.c:76
MALP_Spinlock lock
a lock for concurrent access to element_count
int MALP_Spinlock_unlock(MALP_Spinlock *mutex)
Unlocks the given MALP_Spinlock.
Definition: Spinlock.c:41
struct Buffered_FIFO_chunk * tail
the tail chunk (from where elements are popped
size_t elem_size
the size of stored elements
Definition: Buffered_FIFO.h:52
uint64_t start_offset
the start offset (position of oldest element in payload
Definition: Buffered_FIFO.h:53
struct Buffered_FIFO_chunk * Buffered_FIFO_chunk_new(uint64_t chunk_size, uint64_t elem_size)
Allocates a new Buffered_FIFO_chunk.
Definition: Buffered_FIFO.c:54
void Buffered_FIFO_chunk_init(struct Buffered_FIFO_chunk *ch, uint64_t chunk_size, uint64_t elem_size)
Definition: Buffered_FIFO.c:34
uint64_t Buffered_FIFO_count(struct Buffered_FIFO *fifo)
Thread-safely gets the number of elements stored in the FIFO.
Definition: Buffered_FIFO.c:23
void Buffered_FIFO_chunk_release(struct Buffered_FIFO_chunk *ch)
Deallocates a new Buffered_FIFO_chunk.
Definition: Buffered_FIFO.c:70
static struct Buffered_FIFO_chunk * Buffered_FIFO_chunk_prev(struct Buffered_FIFO_chunk *ch)
Thread-safely gets the previous chunk (ch->prev)
int MALP_Spinlock_lock(MALP_Spinlock *mutex)
Locks the given MALP_Spinlock.
Definition: Spinlock.c:29
MALP_Spinlock lock
a lock for concurrent internal manipulations
Definition: Buffered_FIFO.h:49
struct Buffered_FIFO_chunk * prev
previous chunk of the FIFO (newer elements)
Definition: Buffered_FIFO.h:56
struct Buffered_FIFO_chunk * head
the head chunk (chere elements are pushed
void Buffered_FIFO_init(struct Buffered_FIFO *fifo, uint64_t chunk_size, size_t elem_size)
Initializes a Buffered_FIFO.
static void Buffered_FIFO_chunk_ctx_prev(struct Buffered_FIFO_chunk *ch, struct Buffered_FIFO_chunk *prev)
Thread-safely sets the previous chunk (ch->prev)
uint64_t end_offset
the end offset (position of the end of newest element in payload
Definition: Buffered_FIFO.h:54
uint64_t chunk_size
the size of the current chunk
Definition: Buffered_FIFO.h:51
Structure defining a chunk of FIFO. The Buffered_FIFO is made of several Buffered_FIFO_chunk containi...
Definition: Buffered_FIFO.h:48
uint64_t elem_count
the number of elements currently stored in the FIFO