SIONlib  1.7.7
Scalable I/O library for parallel access to task-local files
sion_fd.c
Go to the documentation of this file.
1 /****************************************************************************
2 ** SIONLIB http://www.fz-juelich.de/jsc/sionlib **
3 *****************************************************************************
4 ** Copyright (c) 2008-2019 **
5 ** Forschungszentrum Juelich, Juelich Supercomputing Centre **
6 ** **
7 ** See the file COPYRIGHT in the package base directory for details **
8 ****************************************************************************/
9 
17 #define _XOPEN_SOURCE 700
18 
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdarg.h>
23 #include <assert.h>
24 #include "sion_lock.h"
25 #include "sion_fd.h"
26 
27 #define sion_assert(expr, args) (assert(expr))
28 
29 #define SION_FDDATA_INITIALIZER {0,0,-1,NULL}
30 
31 /************************/
32 static struct _sion_fddata {
33  int size;
34  int nfree;
35  int last_freed;
36  struct _sion_fd *list;
37 } sion_fd_data = SION_FDDATA_INITIALIZER;
38 
39 static char *text; /* just a temp hack */
40 
41 /* some abbreviations for fd functions */
43 int _sion_newvcd(void *data, int type)
44 {
45  return _sion_new_fd(&sion_fd_data, data, type);
46 }
48 int _sion_freevcd(int sid)
49 {
50  return _sion_free_fd(&sion_fd_data, sid, text);
51 }
53 void *_sion_vcdtovcon(int sid)
54 {
55  return _sion_fd2ptr(&sion_fd_data, sid);
56 }
58 int _sion_vcdtype(int sid)
59 {
60  return _sion_fd2type(&sion_fd_data, sid, text);
61 }
63 int _sion_reassignvcd(int sid, void *data, int type)
64 {
65  return _sion_reassign_fd(&sion_fd_data, sid, data, type, text);
66 }
67 /************************/
68 
69 
70 
76 int _sion_new_fd(sion_fddata *fdd, void *data, int type)
77 {
78  int i;
79 
80  _sion_lock();
81 
82  /* if we are sure that we have at least 2 free descriptors,
83  * we can guarantee, that we don't need to reuse a freed
84  * one immediately
85  * so enlarge array of descriptors if we have less than 2 free ones
86  */
87  if (fdd->nfree < 2) {
88  int new_size;
89 
90  new_size = fdd->size + SION_FD_CHUNK;
91 
92  if (fdd->list) {
93  fdd->list = realloc(fdd->list, new_size * sizeof(struct _sion_fd));
94  }
95  else {
96  fdd->list = malloc(new_size * sizeof(struct _sion_fd));
97  }
98  sion_assert(fdd->list, ("out of memory"));
99 
100  for (i = fdd->size; i < new_size; i++) {
101  fdd->list[i].state = 0; /* free */
102  fdd->list[i].type = 0;
103  fdd->list[i].data = NULL;
104  }
105 
106  fdd->size = new_size;
107  fdd->nfree += SION_FD_CHUNK;
108  }
109 
110  /* use first 'fresh' index */
111  for (i = 0; i < fdd->size; i++) {
112  if (fdd->list[i].state == 0) {
113  fdd->list[i].data = data;
114  fdd->list[i].type = type;
115  fdd->list[i].state = 1;
116  fdd->nfree--;
117  _sion_unlock();
118  return i;
119  }
120  }
121 
122  /* if all have been used before, use a 'closed' one,
123  * start seraching a new one AFTER the last freed
124  * so this one will not be reused immediately
125  */
126  for (i = fdd->last_freed + 1; i < fdd->last_freed + 1 + fdd->size; i++) {
127  int imod = i % fdd->size;
128  if (fdd->list[imod].state == -1) {
129  fdd->list[imod].data = data;
130  fdd->list[imod].type = type;
131  fdd->list[imod].state = 1;
132  fdd->nfree--;
133  _sion_unlock();
134  return imod;
135  }
136  }
137  sion_assert(0, ("oops - we should never get here"));
138  return -1;
139 }
140 
141 
148 int _sion_set_fd(sion_fddata *fdd, int fd, void *data, int type, char *text)
149 {
150 
151  if (text && (!*text))
152  text = "_sion_set_fd";
153 
154  if (fd < 0) {
155  if (text) {
156  fprintf(stderr, "%s: trying to set an invalid descriptor fd=%d.\n", text, fd);
157  }
158  return 0;
159  }
160 
161  _sion_lock();
162 
163  if (fd >= fdd->size) {
164  /*
165  * enlarge descriptor array if neccessary
166  *
167  */
168  int i, new_size;
169 
170  new_size = fdd->size + SION_FD_CHUNK;
171  while (fd >= new_size) {
172  new_size += SION_FD_CHUNK;
173  }
174 
175  if (fdd->list) {
176  fdd->list = realloc(fdd->list, new_size * sizeof(struct _sion_fd));
177  }
178  else {
179  fdd->list = malloc(new_size * sizeof(struct _sion_fd));
180  }
181  sion_assert(fdd->list, ("out of memory"));
182 
183  for (i = fdd->size; i < new_size; i++) {
184  fdd->list[i].state = 0; /* free */
185  fdd->list[i].type = 0;
186  fdd->list[i].data = NULL;
187  }
188 
189  fdd->nfree += new_size - fdd->size;
190  fdd->size = new_size;
191  }
192  else if (fdd->list[fd].state == 1) {
193  if (text) {
194  fprintf(stderr, "%s: trying to set a descriptor that is in use fd=%d.\n", text, fd);
195  }
196  _sion_unlock();
197  return 0;
198  }
199 
200  fdd->list[fd].data = data;
201  fdd->list[fd].type = type;
202  fdd->list[fd].state = 1;
203  fdd->nfree--;
204 
205  _sion_unlock();
206  return 1;
207 }
208 
209 
213 int _sion_free_fd(sion_fddata *fdd, int fd, char *text)
214 {
215 
216  _sion_lock();
217  if ((fd < fdd->size) && (fd >= 0) && (fdd->list) && (fdd->list[fd].state == 1)) {
218  fdd->list[fd].state = -1;
219  fdd->nfree++;
220  fdd->last_freed = fd; /* remember this one to avoid immediate reuse */
221 
222  if (fdd->nfree == fdd->size) {
223  free(fdd->list);
224  fdd->list = NULL;
225  fdd->nfree = 0;
226  fdd->size = 0;
227  }
228 
229  _sion_unlock();
230  return 1;
231  }
232  else {
233  if (text) {
234  if (!*text)
235  text = "_sion_free_fd";
236  fprintf(stderr, "%s: trying to free an invalid descriptor fd=%d.\n", text, fd);
237  }
238  _sion_unlock();
239  return 0;
240  }
241 }
242 
243 
247 void *_sion_fd2ptr(sion_fddata *fdd, int fd)
248 {
249  _sion_lock();
250  if ((fd < fdd->size) && (fd >= 0) && (fdd->list[fd].state == 1)) {
251  void *ptr = fdd->list[fd].data;
252  _sion_unlock();
253  return ptr;
254  }
255  else {
256  _sion_unlock();
257  return NULL;
258  }
259 }
260 
261 
265 int _sion_fd2type(sion_fddata *fdd, int fd, char *text)
266 {
267  _sion_lock();
268  if ((fd < fdd->size) && (fd >= 0) && (fdd->list[fd].state == 1)) {
269  int type = fdd->list[fd].type;
270  _sion_unlock();
271  return type;
272  }
273  else {
274  if (text) {
275  if (!*text)
276  text = "_sion_fd2type";
277  fprintf(stderr, "%s: invalid descriptor fd=%d.\n", text, fd);
278  }
279  _sion_unlock();
280  return -1;
281  }
282 }
283 
284 
289 int _sion_ptr2fd(sion_fddata *fdd, void *ptr, char *text)
290 {
291  int i;
292 
293  _sion_lock();
294  for (i = 0; i < fdd->size; i++) {
295  if ((fdd->list[i].state == 1) && (fdd->list[i].data == ptr)) {
296  _sion_unlock();
297  return i;
298  }
299  }
300  if (text) {
301  if (!*text)
302  text = "_sion_ptr2fd";
303  fprintf(stderr, "%s: invalid pointer ptr=%x.\n", text, (unsigned) (size_t) ptr);
304  }
305  _sion_unlock();
306  return -1;
307 }
308 
309 
315 int _sion_reassign_fd(sion_fddata *fdd, int fd, void *data, int type, char *text)
316 {
317  _sion_lock();
318  if ((fd < fdd->size) && (fd >= 0) && (fdd->list[fd].state == 1)) {
319  fdd->list[fd].data = data;
320  fdd->list[fd].type = type;
321  _sion_unlock();
322  return 1;
323  }
324  else {
325  if (text) {
326  if (!*text)
327  text = "_sion_reassign_fd";
328  fprintf(stderr, "%s: invalid descriptor fd=%d.\n", text, fd);
329  }
330  _sion_unlock();
331  return 0;
332  }
333 }
334 
335 
339 int _sion_fd_size(sion_fddata *fdd)
340 {
341  /* should be atomic */
342  return fdd->size;
343 }
callback wrappers for OMP thread safe fd manipulation
int _sion_reassignvcd(int sid, void *data, int type)
Definition: sion_fd.c:63
int _sion_free_fd(sion_fddata *fdd, int fd, char *text)
Definition: sion_fd.c:213
int _sion_ptr2fd(sion_fddata *fdd, void *ptr, char *text)
Definition: sion_fd.c:289
void * _sion_vcdtovcon(int sid)
Definition: sion_fd.c:53
int _sion_vcdtype(int sid)
Definition: sion_fd.c:58
int _sion_newvcd(void *data, int type)
Definition: sion_fd.c:43
int _sion_reassign_fd(sion_fddata *fdd, int fd, void *data, int type, char *text)
Definition: sion_fd.c:315
void * _sion_fd2ptr(sion_fddata *fdd, int fd)
Definition: sion_fd.c:247
int _sion_new_fd(sion_fddata *fdd, void *data, int type)
Definition: sion_fd.c:76
int _sion_fd_size(sion_fddata *fdd)
Definition: sion_fd.c:339
int _sion_freevcd(int sid)
Definition: sion_fd.c:48
int _sion_set_fd(sion_fddata *fdd, int fd, void *data, int type, char *text)
Definition: sion_fd.c:148
int _sion_fd2type(sion_fddata *fdd, int fd, char *text)
Definition: sion_fd.c:265