ARGOBOTS  66b1c39742507d8df30e8d28c54839b961a14814
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups
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 */
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  int num_headers_per_bucket; /* Number of headers per bucket. */
57  int num_lp_type_requests; /* Number of requests for large page allocation.
58  */
60  lp_type_requests[4]; /* Requests for large page allocation */
62  ABTI_sync_lifo bucket_lifo; /* LIFO of available buckets. */
64  ABTI_sync_lifo mem_page_lifo; /* LIFO of non-empty pages. */
66  ABTD_atomic_ptr p_mem_page_empty; /* List of empty pages. */
68  /* List of the remaining headers that are not enough to create one
69  * complete bucket. This is protected by a spinlock. The number of
70  * headers is stored in partial_bucket.bucket_info.num_headers. */
74 
75 /*
76  * To efficiently take/return multiple headers per bucket, headers are stored as
77  * follows in the local pool.
78  *
79  * buckets[0]:
80  * = header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
81  * buckets[1]:
82  * = header (p_next)> header (p_next)> header ... (num_headers_per_bucket)
83  * .
84  * .
85  * buckets[bucket_index]:
86  * = header (p_next)> header (p_next)> header ...
87  * (buckets[bucket_index]->bucket_info.num_headers)
88  */
89 typedef struct ABTI_mem_pool_local_pool {
91  size_t num_headers_per_bucket; /* Cached value to reduce dereference. It
92  must be equal to
93  p_global_pool->num_headers_per_bucket. */
94  size_t bucket_index;
97 
100  size_t header_size, size_t header_offset, size_t page_size,
102  size_t alignment_hint);
104  ABTI_mem_pool_global_pool *p_global_pool);
106  ABTI_mem_pool_global_pool *p_global_pool);
109  ABTI_mem_pool_header **p_bucket);
111  ABTI_mem_pool_header *bucket);
112 
113 ABTU_ret_err static inline int
114 ABTI_mem_pool_alloc(ABTI_mem_pool_local_pool *p_local_pool, void **p_mem)
115 {
116  size_t bucket_index = p_local_pool->bucket_index;
117  ABTI_mem_pool_header *cur_bucket = p_local_pool->buckets[bucket_index];
118  int num_headers_in_cur_bucket = cur_bucket->bucket_info.num_headers;
119  /* At least one header is available in the current bucket, so it must be
120  * larger than 0. */
121  ABTI_ASSERT(num_headers_in_cur_bucket >= 1);
122  if (num_headers_in_cur_bucket == 1) {
123  /*cur_bucket will be empty after allocation. */
124  if (bucket_index == 0) {
125  /* cur_bucket is the last header in this pool.
126  * Let's get some buckets from the global pool. */
127  int i;
128  for (i = 0; i < ABT_MEM_POOL_NUM_TAKE_BUCKETS; i++) {
129  int abt_errno =
131  &p_local_pool->buckets[i]);
132  if (ABTI_IS_ERROR_CHECK_ENABLED && abt_errno != ABT_SUCCESS) {
133  /* Return buckets that have been already taken. */
134  int j;
135  for (j = 0; j < i; j++) {
137  p_local_pool->buckets[j]);
138  }
139  return abt_errno;
140  }
141  }
142  p_local_pool->bucket_index = ABT_MEM_POOL_NUM_TAKE_BUCKETS - 1;
143  } else {
144  p_local_pool->bucket_index = bucket_index - 1;
145  }
146  /* Now buckets[bucket_index] is full of headers. */
147  } else {
148  /* Let's return the header in the bucket. */
149  ABTI_mem_pool_header *p_next = cur_bucket->p_next;
150  p_next->bucket_info.num_headers = num_headers_in_cur_bucket - 1;
151  p_local_pool->buckets[bucket_index] = p_next;
152  }
153  /* At least one header is available in the current bucket. */
154  *p_mem = (void *)cur_bucket;
155  return ABT_SUCCESS;
156 }
157 
158 static inline void ABTI_mem_pool_free(ABTI_mem_pool_local_pool *p_local_pool,
159  void *mem)
160 {
161  /* At least one header is available in the current bucket. */
162  size_t bucket_index = p_local_pool->bucket_index;
163  ABTI_mem_pool_header *p_freed_header = (ABTI_mem_pool_header *)mem;
164  ABTI_mem_pool_header *cur_bucket = p_local_pool->buckets[bucket_index];
165  if (cur_bucket->bucket_info.num_headers ==
166  p_local_pool->num_headers_per_bucket) {
167  /* cur_bucket is full. */
168  if (++bucket_index == ABT_MEM_POOL_MAX_LOCAL_BUCKETS) {
169  int i;
170  /* All buckets are full, so let's return some old buckets. */
171  for (i = 0; i < ABT_MEM_POOL_NUM_RETURN_BUCKETS; i++) {
173  p_local_pool->buckets[i]);
174  }
175  for (i = ABT_MEM_POOL_NUM_RETURN_BUCKETS;
177  p_local_pool->buckets[i - ABT_MEM_POOL_NUM_RETURN_BUCKETS] =
178  p_local_pool->buckets[i];
179  }
180  bucket_index = ABT_MEM_POOL_MAX_LOCAL_BUCKETS -
182  }
183  p_local_pool->bucket_index = bucket_index;
184  p_freed_header->p_next = NULL;
185  p_freed_header->bucket_info.num_headers = 1;
186  } else {
187  p_freed_header->p_next = cur_bucket;
188  p_freed_header->bucket_info.num_headers =
189  cur_bucket->bucket_info.num_headers + 1;
190  }
191  p_local_pool->buckets[bucket_index] = p_freed_header;
192  /* At least one header is available in the current bucket. */
193 }
194 
195 #endif /* ABTI_MEM_POOL_H_INCLUDED */
static ABTU_ret_err int ABTI_mem_pool_alloc(ABTI_mem_pool_local_pool *p_local_pool, void **p_mem)
#define ABT_MEM_POOL_MAX_LOCAL_BUCKETS
Definition: abti_mem_pool.h:9
struct ABTI_mem_pool_page * p_next_empty_page
Definition: abti_mem_pool.h:27
void 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:128
ABTI_spinlock partial_bucket_lock
Definition: abti_mem_pool.h:71
ABTI_mem_pool_header * buckets[ABT_MEM_POOL_MAX_LOCAL_BUCKETS]
Definition: abti_mem_pool.h:95
ABTU_MEM_LARGEPAGE_TYPE lp_type_requests[4]
Definition: abti_mem_pool.h:60
#define ABT_CONFIG_STATIC_CACHELINE_SIZE
Definition: abt_config.h:57
#define ABT_MEM_POOL_NUM_TAKE_BUCKETS
Definition: abti_mem_pool.h:11
ABTI_sync_lifo
ABTI_mem_pool_header_bucket_info bucket_info
Definition: abti_mem_pool.h:22
ABTI_sync_lifo mem_page_lifo
Definition: abti_mem_pool.h:64
ABTI_mem_pool_global_pool * p_global_pool
Definition: abti_mem_pool.h:90
void ABTI_mem_pool_destroy_local_pool(ABTI_mem_pool_local_pool *p_local_pool)
Definition: mem_pool.c:142
#define ABT_SUCCESS
Definition: abt.h:64
static void ABTI_mem_pool_free(ABTI_mem_pool_local_pool *p_local_pool, void *mem)
void ABTI_mem_pool_destroy_global_pool(ABTI_mem_pool_global_pool *p_global_pool)
Definition: mem_pool.c:105
#define ABT_MEM_POOL_NUM_RETURN_BUCKETS
Definition: abti_mem_pool.h:10
ABTI_mem_pool_header * partial_bucket
Definition: abti_mem_pool.h:72
#define ABTU_align_member_var(size)
Definition: abtu.h:64
struct ABTI_mem_pool_local_pool ABTI_mem_pool_local_pool
struct ABTI_mem_pool_header ABTI_mem_pool_header
ABTI_sync_lifo_element lifo_elem
Definition: abti_mem_pool.h:26
void ABTI_mem_pool_init_global_pool(ABTI_mem_pool_global_pool *p_global_pool, int num_headers_per_bucket, size_t header_size, size_t header_offset, size_t page_size, const ABTU_MEM_LARGEPAGE_TYPE *lp_type_requests, int num_lp_type_requests, size_t alignment_hint)
Definition: mem_pool.c:77
ABTU_MEM_LARGEPAGE_TYPE
Definition: abtu.h:218
ABTI_sync_lifo_element lifo_elem
Definition: abti_mem_pool.h:15
ABTI_sync_lifo bucket_lifo
Definition: abti_mem_pool.h:62
ABTU_MEM_LARGEPAGE_TYPE lp_type
Definition: abti_mem_pool.h:30
int ABTI_mem_pool_take_bucket(ABTI_mem_pool_global_pool *p_global_pool, ABTI_mem_pool_header **p_bucket)
Definition: mem_pool.c:163
union ABTI_mem_pool_header_bucket_info ABTI_mem_pool_header_bucket_info
#define ABTI_ASSERT(cond)
Definition: abti_error.h:12
ABTD_atomic_ptr p_mem_page_empty
Definition: abti_mem_pool.h:66
struct ABTI_mem_pool_page ABTI_mem_pool_page
#define ABTI_IS_ERROR_CHECK_ENABLED
Definition: abti.h:20
void ABTI_mem_pool_return_bucket(ABTI_mem_pool_global_pool *p_global_pool, ABTI_mem_pool_header *bucket)
Definition: mem_pool.c:277
struct ABTI_mem_pool_header * p_next
Definition: abti_mem_pool.h:21
#define ABTU_ret_err
Definition: abtu.h:49