build: fix travis MPI/SMP build
[charm.git] / src / arch / util / mempool.h
1
2 #ifndef MEMPOOL_H
3 #define MEMPOOL_H
4
5 #include "conv-config.h"
6 #include "converse.h"
7
8 #if CMK_CONVERSE_UGNI
9 #include "gni_pub.h"
10 #include "pmi.h"
11 typedef gni_mem_handle_t mem_handle_t;
12 #else
13 // in uGNI, it is memory handler, other versions, this is an integer
14 // a unique integer to represent the memory block
15 typedef CmiInt8 mem_handle_t;
16 #endif
17
18 typedef void* (*mempool_newblockfn)(size_t* size, mem_handle_t* mem_hndl, int expand_flag);
19 typedef void (*mempool_freeblock)(void* ptr, mem_handle_t mem_hndl);
20
21 #define cutOffNum CMK_MEMPOOL_CUTOFFNUM
22
23 //given x as mptr get
24 #define MEMPOOL_GetBlockHead(x) (&((x)->block_head))
25 //given x as block header, get ...
26 #define MEMPOOL_GetBlockSize(x) ((x)->size)
27 #define MEMPOOL_GetBlockMemHndl(x) ((x)->mem_hndl)
28 #define MEMPOOL_GetBlockNext(x) ((x)->block_next)
29 //given x as user pointer, get mempool_header/slot_header
30 #define MEMPOOL_GetMempoolHeader(x, align) \
31   ((mempool_header*)((char*)(x) - (align)))
32 //given x as mempool_header/slot_header, get ...
33 #define MEMPOOL_GetBlockPtr(x) ((x)->block_ptr)
34 #define MEMPOOL_GetMempoolPtr(x) (MEMPOOL_GetBlockPtr(x)->mptr)
35 #define MEMPOOL_GetSize(x) (MEMPOOL_GetBlockPtr(x)->size)
36 #define MEMPOOL_GetMemHndl(x) (MEMPOOL_GetBlockPtr(x)->mem_hndl)
37 #define MEMPOOL_GetMsgInRecv(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_recv)
38 #define MEMPOOL_GetMsgInSend(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_send)
39 #define MEMPOOL_IncMsgInRecv(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_recv)++
40 #define MEMPOOL_DecMsgInRecv(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_recv)--
41 #define MEMPOOL_IncMsgInSend(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_send)++
42 #define MEMPOOL_DecMsgInSend(x) (MEMPOOL_GetBlockPtr(x)->msgs_in_send)--
43 #define MEMPOOL_GetSlotGNext(x) ((x)->gnext)
44 #define MEMPOOL_GetSlotStatus(x) ((x)->status)
45 #define MEMPOOL_GetSlotSize(x) ((x)->size)
46 struct block_header;
47 struct mempool_type;
48
49 //header of an free slot
50 typedef struct slot_header_
51 {
52   struct block_header* block_ptr;
53   size_t size;
54   int power, status;    // status is 1 for free, 0 for used
55   size_t gprev, gnext;  // global slot list within a block
56   size_t prev, next;    // linked list for freelists slots
57 #if CMK_64BIT
58   int padding[2];
59 #endif
60 } slot_header;
61
62 typedef struct used_header_
63 {
64   struct block_header* block_ptr;
65   size_t size;
66   int power, status;    // status is 1 for free, 0 for used
67   size_t gprev, gnext;  // global slot list within a block
68   int padding[2];
69 } used_header;
70
71 typedef used_header mempool_header;
72
73 // multiple mempool for different size allocation
74 // make sure this is 16 byte aligned
75 typedef struct block_header
76 {
77   mem_handle_t mem_hndl;
78   size_t size, used;
79   size_t block_prev, block_next;  // offset to next memblock
80   struct mempool_type* mptr;      // mempool_type
81 #if CMK_CONVERSE_UGNI
82   int msgs_in_send;
83   int msgs_in_recv;
84 #define freelists_extra (sizeof(mem_handle_t) + sizeof(struct mempool_type*) + 2 * sizeof(int))
85 #else
86 #define freelists_extra (sizeof(mem_handle_t) + sizeof(struct mempool_type*))
87 #endif
88   // use freelists as padding to the nearest 16-byte interval to avoid size-zero array warnings
89   size_t freelists[cutOffNum + CMIPADDING(cutOffNum * sizeof(size_t) + freelists_extra, 16) / sizeof(size_t)];
90 #undef freelists_extra
91 } block_header;
92
93 typedef struct large_block_header
94 {
95   mem_handle_t mem_hndl;
96   size_t size;
97   size_t block_prev, block_next;  // offset to next memblock
98   struct mempool_type* mptr;      // mempool_type
99 #if CMK_CONVERSE_UGNI
100   int msgs_in_send;
101   int msgs_in_recv;
102 #endif
103   int padding[2];
104 } large_block_header;
105
106 // only at beginning of first block of mempool, representing the mempool
107 typedef struct mempool_type
108 {
109   block_header block_head;
110   mempool_newblockfn newblockfn;
111   mempool_freeblock freeblockfn;
112   size_t large_blocks;
113   size_t block_tail;
114   size_t limit;
115   size_t size;
116 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_UGNI)
117   CmiNodeLock mempoolLock;
118   char padding[CMIPADDING((6 * sizeof(size_t) + sizeof(CmiNodeLock)), 16)];
119 #elif !CMK_64BIT
120   size_t padding[2];
121 #endif
122 } mempool_type;
123
124 #ifdef __cplusplus
125 static_assert(sizeof(slot_header) % 16 == 0, "slot_header is not a multiple of 16 bytes");
126 static_assert(sizeof(used_header) % 16 == 0, "used_header is not a multiple of 16 bytes");
127 static_assert(sizeof(block_header) % 16 == 0, "block_header is not a multiple of 16 bytes");
128 static_assert(sizeof(large_block_header) % 16 == 0, "large_block_header is not a multiple of 16 bytes");
129 static_assert(sizeof(mempool_type) % 16 == 0, "mempool_type is not a multiple of 16 bytes");
130
131 extern "C" {
132 #endif
133
134 mempool_type* mempool_init(size_t pool_size, mempool_newblockfn newfn, mempool_freeblock freefn, size_t limit);
135 void mempool_destroy(mempool_type* mptr);
136 void* mempool_malloc(mempool_type* mptr, size_t size, int expand);
137 void* mempool_large_malloc(mempool_type* mptr, size_t size, int expand);
138 void mempool_free(mempool_type* mptr, void* ptr_free);
139 #if CMK_USE_MEMPOOL_ISOMALLOC || (CMK_SMP && CMK_CONVERSE_UGNI)
140 void mempool_free_thread(void* ptr_free);
141 #endif
142
143 #if defined(__cplusplus)
144 }
145 #endif
146
147 #if CMK_CONVERSE_UGNI
148 void* getNextRegisteredPool();
149 #endif
150
151 #endif /* MEMPOOL.H */