Multi-ApplicationOnlineProfiling  2.1
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
Buffered_LIFO.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_LIFO.h"
20 
21 #include <string.h>
22 
23 struct Buffered_LIFO_chunk * Buffered_LIFO_chunk_new( size_t sizeof_payload, uint64_t chunk_size, struct Buffered_LIFO_chunk * prev )
24 {
25  struct Buffered_LIFO_chunk * ret = malloc( sizeof( struct Buffered_LIFO_chunk ) + sizeof_payload * chunk_size );
26 
27  if( !ret )
28  {
29  perror( "malloc" );
30  abort();
31  }
32 
33  ret->offset = 0;
34  ret->next = prev;
35 
36  return ret;
37 }
38 
39 void Buffered_LIFO_chunk_release( struct Buffered_LIFO_chunk * chunk, size_t sizeof_payload, void (*free_func)( void *) )
40 {
41  if( !chunk )
42  {
43  return;
44  }
45 
46  int i;
47 
48  if( free_func )
49  {
50  for( i = 0 ; i < chunk->offset ; i++ )
51  {
52  free_func(chunk->elems + i * sizeof_payload);
53  }
54  }
55 
56  chunk->offset = 0;
57  chunk->next = NULL;
58 
59  free( chunk );
60 }
61 
63  void * elem, size_t sizeof_payload, uint64_t chunk_size )
64 {
65  struct Buffered_LIFO_chunk * ret = chunk;
66 
67  if( !ret )
68  {
69  /* There is no previous chunk so create it */
70  ret = Buffered_LIFO_chunk_new( sizeof_payload, chunk_size, ret );
71  }
72  else
73  {
74  if( ret->offset == chunk_size )
75  {
76  /* Current chunk is full so we need a new one */
77  ret = Buffered_LIFO_chunk_new( sizeof_payload, chunk_size, ret );
78  }
79  }
80 
81  /* We can now push a new entry */
82  memcpy( ret->elems + ret->offset * sizeof_payload , elem, sizeof_payload );
83  ret->offset++;
84 
85  return ret;
86 }
87 
89  size_t sizeof_payload, uint64_t chunk_size,
90  void * elem, int *did_ret )
91 {
92  if( !chunk )
93  {
94  *did_ret = 0;
95  return chunk;
96  }
97 
98  if( chunk->offset == 0 )
99  {
100  /* Move to previous chunk */
101  struct Buffered_LIFO_chunk * next = chunk->next;
102 
103  /* Here no free func as the chunk is empty */
104  Buffered_LIFO_chunk_release( chunk, 0, NULL );
105 
106  return Buffered_LIFO_chunk_pop( next, sizeof_payload, chunk_size, elem, did_ret );;
107  }
108 
109  /* Pop from chunk in the chunk */
110  memcpy( elem, chunk->elems + (chunk->offset - 1) * sizeof_payload , sizeof_payload );
111  *did_ret = 1;
112  chunk->offset--;
113 
114  return chunk;
115 }
116 
117 void * Buffered_LIFO_chunk_head( struct Buffered_LIFO_chunk * chunk, size_t sizeof_payload )
118 {
119  if( !chunk )
120  {
121  return NULL;
122  }
123 
124  if( chunk->offset == 0 )
125  {
126  return Buffered_LIFO_chunk_head( chunk->next, sizeof_payload );
127  }
128 
129  return chunk->elems + sizeof_payload * (chunk->offset - 1 );
130 }
131 
132 void Buffered_LIFO_init( struct Buffered_LIFO *lifo, size_t sizeof_payload, uint64_t chunk_size )
133 {
134  lifo->sizeof_payload = sizeof_payload;
135  lifo->chunk_size = chunk_size;
136 
137  lifo->lock = 0;
138  lifo->head = NULL;
139 }
140 
141 void Buffered_LIFO_release( struct Buffered_LIFO *lifo, void (*free_func)( void *) )
142 {
143  lifo->sizeof_payload = 0;
144  lifo->chunk_size = 0;
145 
146  struct Buffered_LIFO_chunk * tmp;
147  struct Buffered_LIFO_chunk * to_free;
148 
149  tmp = lifo->head;
150 
151  while( tmp )
152  {
153  to_free = tmp;
154  tmp = tmp->next;
155 
156 
157  Buffered_LIFO_chunk_release( to_free, lifo->sizeof_payload, free_func);
158  }
159 
160  lifo->lock = 0;
161  lifo->head = NULL;
162 }
163 
164 void Buffered_LIFO_push( struct Buffered_LIFO *lifo, void * elem )
165 {
166  MALP_Spinlock_lock( &lifo->lock );
167  lifo->head = Buffered_LIFO_chunk_push( lifo->head, elem, lifo->sizeof_payload, lifo->chunk_size );
168  MALP_Spinlock_unlock( &lifo->lock );
169 }
170 
171 void * Buffered_LIFO_pop( struct Buffered_LIFO *lifo, void * elem )
172 {
173  int did_ret = 0;
174  MALP_Spinlock_lock( &lifo->lock );
175  lifo->head = Buffered_LIFO_chunk_pop( lifo->head, lifo->sizeof_payload, lifo->chunk_size, elem, &did_ret );
176  MALP_Spinlock_unlock( &lifo->lock );
177 
178  if( !did_ret )
179  {
180  return NULL;
181  }
182  else
183  {
184  return elem;
185  }
186 }
187 
188 void * Buffered_LIFO_head( struct Buffered_LIFO *lifo )
189 {
190 
191  MALP_Spinlock_lock( &lifo->lock );
192  void * ret = Buffered_LIFO_chunk_head( lifo->head, lifo->sizeof_payload );
193  MALP_Spinlock_unlock( &lifo->lock );
194 
195  return ret;
196 }
197 
199 {
200  MALP_Spinlock_lock( &lifo->lock );
201  return Buffered_LIFO_chunk_head( lifo->head, lifo->sizeof_payload );
202 }
203 
205 {
206  MALP_Spinlock_unlock( &lifo->lock );
207 }
uint64_t offset
offset in current chunk
Definition: Buffered_LIFO.h:52
struct Buffered_LIFO_chunk * Buffered_LIFO_chunk_pop(struct Buffered_LIFO_chunk *chunk, size_t sizeof_payload, uint64_t chunk_size, void *elem, int *did_ret)
Get an element from the Buffered_LIFO_chunk.
Definition: Buffered_LIFO.c:88
size_t sizeof_payload
Sizeof a payload element.
Structure defining a chunk of LIFO. A buffered lifo consists in several chunks which are stacked in a...
Definition: Buffered_LIFO.h:50
struct Buffered_LIFO_chunk * next
A pointer to the next chunk (NULL if none)
Definition: Buffered_LIFO.h:53
void Buffered_LIFO_head_unlock(struct Buffered_LIFO *lifo)
Unlocks the Buffered_LIFO after a call to Buffered_LIFO_head.
int MALP_Spinlock_unlock(MALP_Spinlock *mutex)
Unlocks the given MALP_Spinlock.
Definition: Spinlock.c:41
void * Buffered_LIFO_head(struct Buffered_LIFO *lifo)
Get a reference to the head element of the Buffered_LIFO note that as no lock is held this reference ...
void Buffered_LIFO_push(struct Buffered_LIFO *lifo, void *elem)
Push an element of size sizeof_payload in the Buffered_LIFO.
struct Buffered_LIFO_chunk * Buffered_LIFO_chunk_new(size_t sizeof_payload, uint64_t chunk_size, struct Buffered_LIFO_chunk *prev)
Allocates an empty Buffered_LIFO_chunk pointing to prev.
Definition: Buffered_LIFO.c:23
char elems[0]
A dummy pointer to the data which is piggybacked.
Definition: Buffered_LIFO.h:54
void Buffered_LIFO_chunk_release(struct Buffered_LIFO_chunk *chunk, size_t sizeof_payload, void(*free_func)(void *))
Releases a Buffered_LIFO_chunk note that it does not recurses over previous chunks.
Definition: Buffered_LIFO.c:39
int MALP_Spinlock_lock(MALP_Spinlock *mutex)
Locks the given MALP_Spinlock.
Definition: Spinlock.c:29
void * Buffered_LIFO_pop(struct Buffered_LIFO *lifo, void *elem)
Push an element of size sizeof_payload in the Buffered_LIFO.
void Buffered_LIFO_release(struct Buffered_LIFO *lifo, void(*free_func)(void *))
Releases a Buffered_LIFO and all its chunks.
uint64_t chunk_size
Maximum number of elems in a chunk.
void Buffered_LIFO_init(struct Buffered_LIFO *lifo, size_t sizeof_payload, uint64_t chunk_size)
Initializes a Buffered_LIFO ready to contains elems of size sizeof_payload with chunk_size chunks...
void * Buffered_LIFO_chunk_head(struct Buffered_LIFO_chunk *chunk, size_t sizeof_payload)
Get a pointer to the Buffered_LIFO_chunk head eleme (NULL if none)
MALP_Spinlock lock
A spinlock to protect the LIFO.
struct Buffered_LIFO_chunk * Buffered_LIFO_chunk_push(struct Buffered_LIFO_chunk *chunk, void *elem, size_t sizeof_payload, uint64_t chunk_size)
Push a new elem in the Buffered_LIFO_chunk.
Definition: Buffered_LIFO.c:62
void * Buffered_LIFO_head_locked(struct Buffered_LIFO *lifo)
Get a reference to the head element of the Buffered_LIFO but keeps the LIFO locked in order to allow ...
Structure defining buffered LIFO.
struct Buffered_LIFO_chunk * head
A pointer to the first chunk.