source: CPL/oasis3-mct/branches/OASIS3-MCT_2.0_branch/lib/mct/mpi-serial/handles.c

Last change on this file was 4775, checked in by aclsce, 5 years ago
  • Imported oasis3-mct from Cerfacs svn server (not suppotred anymore).

The version has been extracted from https://oasis3mct.cerfacs.fr/svn/branches/OASIS3-MCT_2.0_branch/oasis3-mct@1818

File size: 5.1 KB
Line 
1
2/*
3 * 5/20/2005 RML
4 *
5 */
6
7
8#include "mpiP.h"
9
10/*
11 * handles.c
12 *
13 * handle management
14 * based on code from mpich-1.x/ptrcvt.c
15 * --> simplified and store item directly in the struct
16 * rather than as pointer to separately allocated object.
17 *
18 * CAVEAT:
19 * as in mpich-1, storage will grow as needed and will
20 * remain at the high water mark since it is likely that
21 * the user code will repeat the use.
22 *
23 */ 
24
25
26typedef struct _Handleitem
27{
28  int handle;
29  struct _Handleitem *next;
30
31  union
32  {
33    void *anything;           /* At least size of void *  */
34    Comm comm;
35    Req req;
36
37  } data;
38
39
40} Handleitem;
41
42
43/*
44 * These must be consistent with each other
45 *
46 */
47
48#define BLOCK_ITEMS          (256)
49#define HANDLE_TO_BLOCK(x)   ( (x) >> 8)
50#define HANDLE_TO_INDEX(x)   ( (x) & 0xff )
51#define HANDLE(block,index)  ( (block << 8) | (index) )
52
53
54/*
55 * The first block of handle items will be statically allocated.
56 * Subsequent ones will be added if necessary.
57 * blocks[0..nblocks-1] are allocated at any given time.
58 *
59 * Increase MAX_BLOCKS if you *really* need more active request
60 * (Although probably something is wrong if you need more than 256k !!!)
61 *
62 */
63
64
65#define MAX_BLOCKS (1024)
66
67static Handleitem block0[BLOCK_ITEMS];     /* array of handleitems */
68static Handleitem *(blocks[MAX_BLOCKS]);   /* array of pointers to blocks */
69static int nblocks;
70
71
72static int need_to_init=1;
73static Handleitem *nextfree;
74
75
76/************************************************************************/
77
78void *mpi_malloc(int size)
79{
80  void *ret;
81
82  ret=malloc(size);
83
84  if (!ret)
85    {
86      fprintf(stderr,"mpi_malloc: failed to allocate %d bytes\n",size);
87      abort();
88    }
89     
90  return(ret);
91}
92
93
94void mpi_free(void *ptr)
95{
96  free(ptr);
97}
98
99
100/************************************************************************/
101
102
103/*
104 * initialize a block s.t. handles are set and
105 * 0 -> 1 -> 2 ... -> (BLOCK_ITEMS-1) -> NULL
106 *
107 */
108
109static Handleitem *init_block(int block, Handleitem *b)
110{
111  int i;
112
113  for (i=0; i<BLOCK_ITEMS-1; i++)
114    {
115      b[i].handle= HANDLE(block,i);
116      b[i].next = &b[i+1];
117    }
118
119  b[BLOCK_ITEMS-1].handle= HANDLE(block,BLOCK_ITEMS-1);
120  b[BLOCK_ITEMS-1].next=0;
121
122  return( &(b[0]) );
123}
124
125
126
127
128static void init_handles(void)
129{
130  int i;
131  Handleitem *new;
132
133  /*
134   * item 0 will not be used  (handle 0 maps to NULL)
135   *
136   */
137
138  new=init_block(0,block0);
139
140  nextfree=new->next;             /* Skip over using item 0 */
141  new->next=NULL;
142
143  /*
144   * initialize the array of blocks
145   *
146   */
147
148  blocks[0]=block0;
149  nblocks=1;
150
151  for (i=1; i<MAX_BLOCKS; i++)
152    blocks[i]=NULL;
153 
154
155  need_to_init=0;
156}
157
158
159
160void mpi_destroy_handles(void)
161{
162  int i;
163
164  if (need_to_init)
165    return;
166
167  for (i=1; i<nblocks; i++)          /* blocks[0] is statically allocated */
168    mpi_free(blocks[i]);
169
170  need_to_init=1;
171}
172
173
174/************************************************************************/
175
176
177void mpi_alloc_handle(int *handle, void **data)
178{
179  Handleitem *new;
180  int i;
181
182  if (need_to_init)
183    init_handles();
184
185  if (nextfree)
186    {
187      new= nextfree;
188      nextfree= nextfree->next;
189      new->next=NULL;
190
191      *handle= new->handle;
192      *data= &(new->data);
193
194      return;
195    }
196
197  /* there is nothing free, so allocate a new block and add it
198   * to blocks[]
199   */
200
201  if (nblocks==MAX_BLOCKS)
202    {
203      fprintf(stderr,"mpi_allocate_handle: max %d active handles exceeded\n",
204              MAX_BLOCKS*BLOCK_ITEMS);
205      abort();
206    }
207
208  blocks[nblocks]= (Handleitem *)mpi_malloc(sizeof(Handleitem)* BLOCK_ITEMS);
209  new=init_block(nblocks,blocks[nblocks]);
210
211  nextfree= new->next;
212  new->next=NULL;
213
214  *handle= new->handle;
215  *data= &(new->data);
216
217  nblocks++;  /* DON'T FORGET THIS!!!! */
218
219#ifdef HANDLE_INFO
220  fflush(stdout);
221  fprintf(stderr,"mpi_alloc_handle: allocation %d blocks (%d handles)\n",
222          nblocks,nblocks*BLOCK_ITEMS);
223#endif
224
225}
226
227
228
229
230static void verify_handle(int handle, int block, int index)
231{
232  if (block>=nblocks || block<0 ||
233      index>=BLOCK_ITEMS || index<0)
234    {
235      fprintf(stderr,"mpi_verify_handle: bad handle\n");
236      abort();
237    }
238
239  if (blocks[block][index].handle != handle)
240    {
241      fprintf(stderr,"mpi_verify_handle: handle mismatch\n");
242      abort();
243    }
244}
245
246
247
248void *mpi_handle_to_ptr(int handle)
249{
250  int block;
251  int index;
252
253  if (need_to_init)
254    init_handles();
255
256  if (!handle)     /* Handle 0 -> NULL */
257    return(NULL);
258
259  block=HANDLE_TO_BLOCK(handle);
260  index=HANDLE_TO_INDEX(handle);
261
262#ifdef CHECKS
263  verify_handle(handle,block,index);
264#endif
265
266  return( &(blocks[block][index].data) );
267}
268
269
270
271void mpi_free_handle(int handle)
272{
273  int block;
274  int index;
275  Handleitem *item;
276
277  if (!handle)                         /* ignore null handle */
278    return;
279
280  if (need_to_init)
281    {
282      fprintf(stderr,"mpi_free_handle: handles not initialized\n");
283      abort();
284    }
285
286  block=HANDLE_TO_BLOCK(handle);
287  index=HANDLE_TO_INDEX(handle);
288
289#ifdef CHECKS
290  verify_handle(handle,block,index);
291#endif
292 
293  item=&(blocks[block][index]);
294
295#ifdef CHECKS
296  if (item->next)
297    {
298      fprintf(stderr,"mpi_free_handle: handle still in use\n");
299      abort();
300    }
301#endif
302
303
304  /* just return it to the free list.
305   * space is not reclaimed.
306   */
307
308  item->next=nextfree;
309  nextfree=item;
310}
Note: See TracBrowser for help on using the repository browser.