ARGOBOTS  1.1
abti_mem_pool.h
Go to the documentation of this file.
1 /* -*- Mode: C; c-basic-offset:4 ; indent-tabs-mode:nil ; -*- */
2 /*
3  * See COPYRIGHT in top-level directory.
4  */
5 
6 #ifndef ABTI_MEM_POOL_H_INCLUDED
7 #define ABTI_MEM_POOL_H_INCLUDED
8 
9 #define ABT_MEM_POOL_MAX_LOCAL_BUCKETS 2
10 #define ABT_MEM_POOL_NUM_RETURN_BUCKETS 1
11 #define ABT_MEM_POOL_NUM_TAKE_BUCKETS 1
12 
14  /* This is used when it is in ABTI_mem_pool_global_pool */
16  /* This is used when it is in ABTI_mem_pool_local_pool */
17  size_t num_headers;
19 
20 typedef struct ABTI_mem_pool_header {
24 
25 typedef struct ABTI_mem_pool_page {
28  void *mem;
29  size_t page_size;
31  void *p_mem_extra;
34 
35 /*
36  * To efficiently take/return multiple headers per bucket, headers are linked as
37  * follows in the global pool (bucket_lifo).
38  *
39  * header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
40  * | (connected via lifo_elem)
41  * V
42  * header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
43  * | (connected via lifo_elem)
44  * V
45  * header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
46  * .
47  * .
48  */
49 typedef struct ABTI_mem_pool_global_pool {
50  size_t header_size; /* Size of header */
51  size_t page_size; /* Size of page (mem of ABTI_mem_pool_page) */
52  size_t alignment_hint; /* Alignment hint for page */
53  size_t header_offset; /* Offset of ABTI_mem_pool_header from the top
54  * of the memory segment; i.e., the pool returns
55  * p_header_memory_top + offset. */
56  size_t num_headers_per_bucket; /* Number of headers per bucket. */
57  uint32_t
58  num_lp_type_requests; /* Number of requests for large page allocation.
59  */
61  lp_type_requests[4]; /* Requests for large page allocation */
63  ABTI_sync_lifo bucket_lifo; /* LIFO of available buckets. */
65  ABTI_sync_lifo mem_page_lifo; /* LIFO of non-empty pages. */
67  ABTD_atomic_ptr p_mem_page_empty; /* List of empty pages. */
69  /* List of the remaining headers that are not enough to create one
70  * complete bucket. This is protected by a spinlock. The number of
71  * headers is stored in partial_bucket.bucket_info.num_headers. */
72  ABTD_spinlock partial_bucket_lock;
75 
76 /*
77  * To efficiently take/return multiple headers per bucket, headers are stored as
78  * follows in the local pool.
79  *
80  * buckets[0]:
81  * = header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
82  * buckets[1]:
83  * = header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
84  * .
85  * .
86  * buckets[bucket_index]:
87  * = header (p_next)> header (p_next)> header ...
88  * (buckets[bucket_index]->bucket_info.num_headers)
89  */
90 typedef struct ABTI_mem_pool_local_pool {
92  size_t num_headers_per_bucket; /* Cached value to reduce dereference. It
93  must be equal to
94  p_global_pool->num_headers_per_bucket. */
95  size_t bucket_index;
98 
100  ABTI_mem_pool_global_pool *p_global_pool, size_t num_headers_per_bucket,
101  size_t header_size, size_t header_offset, size_t page_size,
102  const ABTU_MEM_LARGEPAGE_TYPE *lp_type_requests,
103  uint32_t num_lp_type_requests, size_t alignment_hint);
105  ABTI_mem_pool_global_pool *p_global_pool);
106 ABTU_ret_err int
108  ABTI_mem_pool_global_pool *p_global_pool);
111  ABTI_mem_pool_header **p_bucket);
113  ABTI_mem_pool_header *bucket);
114 
115 ABTU_ret_err static inline int
116 ABTI_mem_pool_alloc(ABTI_mem_pool_local_pool *p_local_pool, void **p_mem)
117 {
118  size_t bucket_index = p_local_pool->bucket_index;
119  ABTI_mem_pool_header *cur_bucket = p_local_pool->buckets[bucket_index];
120  size_t num_headers_in_cur_bucket = cur_bucket->bucket_info.num_headers;
121  /* At least one header is available in the current bucket, so it must be
122  * larger than 0. */
123  ABTI_ASSERT(num_headers_in_cur_bucket >= 1);
124  if (num_headers_in_cur_bucket == 1) {
125  /*cur_bucket will be empty after allocation. */
126  if (bucket_index == 0) {
127  /* cur_bucket is the last header in this pool.
128  * Let's get some buckets from the global pool. */
129  size_t i;
130  for (i = 0; i < ABT_MEM_POOL_NUM_TAKE_BUCKETS; i++) {
131  int abt_errno =
133  &p_local_pool->buckets[i]);
134  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
135  /* Return buckets that have been already taken. */
136 #if ABT_MEM_POOL_NUM_TAKE_BUCKETS > 1
137  size_t j;
138  for (j = 0; j < i; j++) {
140  p_local_pool->buckets[j]);
141  }
142 #endif
143  return abt_errno;
144  }
145  }
146  p_local_pool->bucket_index = ABT_MEM_POOL_NUM_TAKE_BUCKETS - 1;
147  } else {
148  p_local_pool->bucket_index = bucket_index - 1;
149  }
150  /* Now buckets[bucket_index] is full of headers. */
151  } else {
152  /* Let's return the header in the bucket. */
153  ABTI_mem_pool_header *p_next = cur_bucket->p_next;
154  p_next->bucket_info.num_headers = num_headers_in_cur_bucket - 1;
155  p_local_pool->buckets[bucket_index] = p_next;
156  }
157  /* At least one header is available in the current bucket. */
158  *p_mem = (void *)cur_bucket;
159  return ABT_SUCCESS;
160 }
161 
162 static inline void ABTI_mem_pool_free(ABTI_mem_pool_local_pool *p_local_pool,
163  void *mem)
164 {
165  /* At least one header is available in the current bucket. */
166  size_t bucket_index = p_local_pool->bucket_index;
167  ABTI_mem_pool_header *p_freed_header = (ABTI_mem_pool_header *)mem;
168  ABTI_mem_pool_header *cur_bucket = p_local_pool->buckets[bucket_index];
169  if (cur_bucket->bucket_info.num_headers ==
170  p_local_pool->num_headers_per_bucket) {
171  /* cur_bucket is full. */
172  if (++bucket_index == ABT_MEM_POOL_MAX_LOCAL_BUCKETS) {
173  size_t i;
174  /* All buckets are full, so let's return some old buckets. */
175  for (i = 0; i < ABT_MEM_POOL_NUM_RETURN_BUCKETS; i++) {
177  p_local_pool->buckets[i]);
178  }
181  p_local_pool->buckets[i - ABT_MEM_POOL_NUM_RETURN_BUCKETS] =
182  p_local_pool->buckets[i];
183  }
184  bucket_index = ABT_MEM_POOL_MAX_LOCAL_BUCKETS -
186  }
187  p_local_pool->bucket_index = bucket_index;
188  p_freed_header->p_next = NULL;
189  p_freed_header->bucket_info.num_headers = 1;
190  } else {
191  p_freed_header->p_next = cur_bucket;
192  p_freed_header->bucket_info.num_headers =
193  cur_bucket->bucket_info.num_headers + 1;
194  }
195  p_local_pool->buckets[bucket_index] = p_freed_header;
196  /* At least one header is available in the current bucket. */
197 }
198 
199 #endif /* ABTI_MEM_POOL_H_INCLUDED */
ABTI_mem_pool_destroy_local_pool
void ABTI_mem_pool_destroy_local_pool(ABTI_mem_pool_local_pool *p_local_pool)
Definition: mem_pool.c:144
ABT_MEM_POOL_NUM_RETURN_BUCKETS
#define ABT_MEM_POOL_NUM_RETURN_BUCKETS
Definition: abti_mem_pool.h:10
ABTI_mem_pool_header::bucket_info
ABTI_mem_pool_header_bucket_info bucket_info
Definition: abti_mem_pool.h:22
ABTI_mem_pool_header
struct ABTI_mem_pool_header ABTI_mem_pool_header
ABTI_mem_pool_global_pool::num_lp_type_requests
uint32_t num_lp_type_requests
Definition: abti_mem_pool.h:58
ABTI_mem_pool_local_pool
Definition: abti_mem_pool.h:90
ABTI_mem_pool_local_pool::bucket_index
size_t bucket_index
Definition: abti_mem_pool.h:95
ABTI_sync_lifo_element
Definition: abti_sync_lifo.h:16
ABT_MEM_POOL_MAX_LOCAL_BUCKETS
#define ABT_MEM_POOL_MAX_LOCAL_BUCKETS
Definition: abti_mem_pool.h:9
ABTI_mem_pool_page::p_mem_extra
void * p_mem_extra
Definition: abti_mem_pool.h:31
ABTI_mem_pool_return_bucket
void ABTI_mem_pool_return_bucket(ABTI_mem_pool_global_pool *p_global_pool, ABTI_mem_pool_header *bucket)
Definition: mem_pool.c:279
ABTI_IS_ERROR_CHECK_ENABLED
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
ABTI_mem_pool_header_bucket_info
union ABTI_mem_pool_header_bucket_info ABTI_mem_pool_header_bucket_info
ABT_MEM_POOL_NUM_TAKE_BUCKETS
#define ABT_MEM_POOL_NUM_TAKE_BUCKETS
Definition: abti_mem_pool.h:11
ABTI_mem_pool_page::p_next_empty_page
struct ABTI_mem_pool_page * p_next_empty_page
Definition: abti_mem_pool.h:27
ABTD_spinlock
Definition: abtd_spinlock.h:9
ABTI_mem_pool_local_pool::p_global_pool
ABTI_mem_pool_global_pool * p_global_pool
Definition: abti_mem_pool.h:91
ABTI_mem_pool_alloc
static ABTU_ret_err int ABTI_mem_pool_alloc(ABTI_mem_pool_local_pool *p_local_pool, void **p_mem)
Definition: abti_mem_pool.h:116
ABTI_mem_pool_local_pool
struct ABTI_mem_pool_local_pool ABTI_mem_pool_local_pool
ABTI_mem_pool_global_pool::page_size
size_t page_size
Definition: abti_mem_pool.h:51
ABTI_mem_pool_global_pool::num_headers_per_bucket
size_t num_headers_per_bucket
Definition: abti_mem_pool.h:56
ABTI_mem_pool_global_pool::ABTU_align_member_var
ABTU_align_member_var(ABT_CONFIG_STATIC_CACHELINE_SIZE) ABTI_sync_lifo bucket_lifo
ABTD_atomic_ptr
Definition: abtd_atomic.h:39
ABTI_mem_pool_global_pool::alignment_hint
size_t alignment_hint
Definition: abti_mem_pool.h:52
ABTI_mem_pool_header_bucket_info::num_headers
size_t num_headers
Definition: abti_mem_pool.h:17
ABTI_mem_pool_global_pool::header_offset
size_t header_offset
Definition: abti_mem_pool.h:53
ABTI_mem_pool_page::page_size
size_t page_size
Definition: abti_mem_pool.h:29
ABTI_ASSERT
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTI_mem_pool_header
Definition: abti_mem_pool.h:20
ABTU_MEM_LARGEPAGE_TYPE
ABTU_MEM_LARGEPAGE_TYPE
Definition: abtu.h:297
ABTI_mem_pool_init_global_pool
void ABTI_mem_pool_init_global_pool(ABTI_mem_pool_global_pool *p_global_pool, size_t num_headers_per_bucket, size_t header_size, size_t header_offset, size_t page_size, const ABTU_MEM_LARGEPAGE_TYPE *lp_type_requests, uint32_t num_lp_type_requests, size_t alignment_hint)
Definition: mem_pool.c:77
ABT_CONFIG_STATIC_CACHELINE_SIZE
#define ABT_CONFIG_STATIC_CACHELINE_SIZE
Definition: abt_config.h:72
ABTI_mem_pool_init_local_pool
ABTU_ret_err int ABTI_mem_pool_init_local_pool(ABTI_mem_pool_local_pool *p_local_pool, ABTI_mem_pool_global_pool *p_global_pool)
Definition: mem_pool.c:129
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:146
ABTI_mem_pool_global_pool
struct ABTI_mem_pool_global_pool ABTI_mem_pool_global_pool
ABTI_mem_pool_global_pool::lp_type_requests
ABTU_MEM_LARGEPAGE_TYPE lp_type_requests[4]
Definition: abti_mem_pool.h:61
ABTI_mem_pool_take_bucket
int ABTI_mem_pool_take_bucket(ABTI_mem_pool_global_pool *p_global_pool, ABTI_mem_pool_header **p_bucket)
Definition: mem_pool.c:165
ABTI_mem_pool_global_pool
Definition: abti_mem_pool.h:49
ABTI_mem_pool_page::mem
void * mem
Definition: abti_mem_pool.h:28
ABTI_mem_pool_header_bucket_info::lifo_elem
ABTI_sync_lifo_element lifo_elem
Definition: abti_mem_pool.h:15
ABTI_sync_lifo
ABTI_sync_lifo
Definition: abti_sync_lifo.h:27
ABTI_mem_pool_page::lp_type
ABTU_MEM_LARGEPAGE_TYPE lp_type
Definition: abti_mem_pool.h:30
ABTI_mem_pool_global_pool::header_size
size_t header_size
Definition: abti_mem_pool.h:50
ABTI_mem_pool_page
Definition: abti_mem_pool.h:25
ABTI_mem_pool_global_pool::partial_bucket
ABTI_mem_pool_header * partial_bucket
Definition: abti_mem_pool.h:73
ABTI_mem_pool_header::p_next
struct ABTI_mem_pool_header * p_next
Definition: abti_mem_pool.h:21
ABTI_mem_pool_header_bucket_info
Definition: abti_mem_pool.h:13
ABTI_mem_pool_destroy_global_pool
void ABTI_mem_pool_destroy_global_pool(ABTI_mem_pool_global_pool *p_global_pool)
Definition: mem_pool.c:105
ABTI_mem_pool_free
static void ABTI_mem_pool_free(ABTI_mem_pool_local_pool *p_local_pool, void *mem)
Definition: abti_mem_pool.h:162
ABTI_mem_pool_page::lifo_elem
ABTI_sync_lifo_element lifo_elem
Definition: abti_mem_pool.h:26
ABTI_mem_pool_page::mem_extra_size
size_t mem_extra_size
Definition: abti_mem_pool.h:32
ABTI_mem_pool_page
struct ABTI_mem_pool_page ABTI_mem_pool_page
ABTI_mem_pool_local_pool::num_headers_per_bucket
size_t num_headers_per_bucket
Definition: abti_mem_pool.h:92
ABTI_mem_pool_local_pool::buckets
ABTI_mem_pool_header * buckets[ABT_MEM_POOL_MAX_LOCAL_BUCKETS]
Definition: abti_mem_pool.h:96