handles.c 5.1 KB

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