ARGOBOTS  dce6e727ffc4ca5b3ffc04cb9517c6689be51ec5
largepage.c
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 #include <sys/types.h>
7 #include <sys/mman.h>
8 
9 #include "abti.h"
10 
11 #define ABTU_LP_PROTS (PROT_READ | PROT_WRITE)
12 
13 #if defined(HAVE_MAP_ANONYMOUS)
14 #define ABTU_LP_FLAGS_RP (MAP_PRIVATE | MAP_ANONYMOUS)
15 #define ABTU_LP_USE_MMAP 1
16 #elif defined(HAVE_MAP_ANON)
17 #define ABTU_LP_FLAGS_RP (MAP_PRIVATE | MAP_ANON)
18 #define ABTU_LP_USE_MMAP 1
19 #else
20 #define ABTU_LP_USE_MMAP 0
21 #endif
22 
23 #if ABTU_LP_USE_MMAP && defined(HAVE_MAP_HUGETLB)
24 #define ABTU_LP_FLAGS_HP (ABTU_LP_FLAGS_RP | MAP_HUGETLB)
25 #define ABTU_LP_USE_MMAP_HUGEPAGE 1
26 #else
27 /* NOTE: On Mac OS, we tried VM_FLAGS_SUPERPAGE_SIZE_ANY that is defined in
28  * <mach/vm_statistics.h>, but mmap() failed with it and its execution was too
29  * slow. By that reason, we do not support it for now. */
30 #define ABTU_LP_USE_HUGEPAGE 0
31 #endif
32 
33 static void *mmap_regular(size_t size)
34 {
35 #if ABTU_LP_USE_MMAP
36  void *p_page = mmap(NULL, size, ABTU_LP_PROTS, ABTU_LP_FLAGS_RP, -1, 0);
37  return p_page != MAP_FAILED ? p_page : NULL;
38 #else
39  return NULL;
40 #endif
41 }
42 
43 static void *mmap_hugepage(size_t size)
44 {
45 #if ABTU_LP_USE_MMAP && ABTU_LP_USE_MMAP_HUGEPAGE
46  void *p_page = mmap(NULL, size, ABTU_LP_PROTS, ABTU_LP_FLAGS_HP, -1, 0);
47  return p_page != MAP_FAILED ? p_page : NULL;
48 #else
49  return NULL;
50 #endif
51 }
52 
53 static void mmap_free(void *p_page, size_t size)
54 {
55  munmap(p_page, size);
56 }
57 
58 /* Returns if a given large page type is supported. */
59 int ABTU_is_supported_largepage_type(size_t size, size_t alignment_hint,
60  ABTU_MEM_LARGEPAGE_TYPE requested)
61 {
62  if (requested == ABTU_MEM_LARGEPAGE_MALLOC) {
63  /* It always succeeds. */
64  return 1;
65  } else if (requested == ABTU_MEM_LARGEPAGE_MEMALIGN) {
66  void *p_page;
67  int ret = ABTU_memalign(alignment_hint, size, &p_page);
68  if (ret == ABT_SUCCESS && p_page != NULL) {
69  ABTU_free(p_page);
70  return 1;
71  }
72  } else if (requested == ABTU_MEM_LARGEPAGE_MMAP) {
73  void *p_page = mmap_regular(size);
74  if (p_page) {
75  mmap_free(p_page, size);
76  return 1;
77  }
78  } else if (requested == ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE) {
79  void *p_page = mmap_hugepage(size);
80  if (p_page) {
81  mmap_free(p_page, size);
82  return 1;
83  }
84  }
85  /* Not supported. */
86  return 0;
87 }
88 
89 ABTU_ret_err int
90 ABTU_alloc_largepage(size_t size, size_t alignment_hint,
91  const ABTU_MEM_LARGEPAGE_TYPE *requested_types,
92  int num_requested_types, ABTU_MEM_LARGEPAGE_TYPE *p_actual,
93  void **p_ptr)
94 {
95  int i;
96  void *ptr = NULL;
97  for (i = 0; i < num_requested_types; i++) {
98  ABTU_MEM_LARGEPAGE_TYPE requested = requested_types[i];
99  if (requested == ABTU_MEM_LARGEPAGE_MALLOC) {
100  int abt_error = ABTU_malloc(size, &ptr);
101  if (abt_error == ABT_SUCCESS && ptr) {
102  *p_actual = ABTU_MEM_LARGEPAGE_MALLOC;
103  *p_ptr = ptr;
104  return ABT_SUCCESS;
105  }
106  } else if (requested == ABTU_MEM_LARGEPAGE_MEMALIGN) {
107  int abt_error = ABTU_memalign(alignment_hint, size, &ptr);
108  if (abt_error == ABT_SUCCESS && ptr) {
109  *p_actual = ABTU_MEM_LARGEPAGE_MEMALIGN;
110  *p_ptr = ptr;
111  return ABT_SUCCESS;
112  }
113  } else if (requested == ABTU_MEM_LARGEPAGE_MMAP) {
114  ptr = mmap_regular(size);
115  if (ptr) {
116  *p_actual = ABTU_MEM_LARGEPAGE_MMAP;
117  *p_ptr = ptr;
118  return ABT_SUCCESS;
119  }
120  } else if (requested == ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE) {
121  ptr = mmap_hugepage(size);
122  if (ptr) {
124  *p_ptr = ptr;
125  return ABT_SUCCESS;
126  }
127  }
128  }
129  return ABT_ERR_MEM;
130 }
131 
132 void ABTU_free_largepage(void *ptr, size_t size, ABTU_MEM_LARGEPAGE_TYPE type)
133 {
134  if (!ptr)
135  return;
136  if (type == ABTU_MEM_LARGEPAGE_MALLOC) {
137  ABTU_free(ptr);
138  } else if (type == ABTU_MEM_LARGEPAGE_MEMALIGN) {
139  ABTU_free(ptr);
140  } else if (type == ABTU_MEM_LARGEPAGE_MMAP) {
141  mmap_free(ptr, size);
142  } else if (type == ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE) {
143  mmap_free(ptr, size);
144  }
145 }
mmap_hugepage
static void * mmap_hugepage(size_t size)
Definition: largepage.c:43
ABTU_memalign
static ABTU_ret_err int ABTU_memalign(size_t alignment, size_t size, void **p_ptr)
Definition: abtu.h:216
ABTU_MEM_LARGEPAGE_MMAP
@ ABTU_MEM_LARGEPAGE_MMAP
Definition: abtu.h:311
ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE
@ ABTU_MEM_LARGEPAGE_MMAP_HUGEPAGE
Definition: abtu.h:312
abti.h
mmap_free
static void mmap_free(void *p_page, size_t size)
Definition: largepage.c:53
ABTU_malloc
static ABTU_ret_err int ABTU_malloc(size_t size, void **p_ptr)
Definition: abtu.h:235
ABT_ERR_MEM
#define ABT_ERR_MEM
Error code: Memory allocation failure.
Definition: abt.h:104
ABTU_MEM_LARGEPAGE_TYPE
ABTU_MEM_LARGEPAGE_TYPE
Definition: abtu.h:308
ABT_SUCCESS
#define ABT_SUCCESS
Error code: the routine returns successfully.
Definition: abt.h:92
ABTU_MEM_LARGEPAGE_MALLOC
@ ABTU_MEM_LARGEPAGE_MALLOC
Definition: abtu.h:309
ABTU_ret_err
#define ABTU_ret_err
Definition: abtu.h:155
ABTU_is_supported_largepage_type
int ABTU_is_supported_largepage_type(size_t size, size_t alignment_hint, ABTU_MEM_LARGEPAGE_TYPE requested)
Definition: largepage.c:59
ABTU_LP_PROTS
#define ABTU_LP_PROTS
Definition: largepage.c:11
ABTU_free
static void ABTU_free(void *ptr)
Definition: abtu.h:228
ABTU_alloc_largepage
ABTU_ret_err int ABTU_alloc_largepage(size_t size, size_t alignment_hint, const ABTU_MEM_LARGEPAGE_TYPE *requested_types, int num_requested_types, ABTU_MEM_LARGEPAGE_TYPE *p_actual, void **p_ptr)
Definition: largepage.c:90
ABTU_free_largepage
void ABTU_free_largepage(void *ptr, size_t size, ABTU_MEM_LARGEPAGE_TYPE type)
Definition: largepage.c:132
ABTU_MEM_LARGEPAGE_MEMALIGN
@ ABTU_MEM_LARGEPAGE_MEMALIGN
Definition: abtu.h:310
mmap_regular
static void * mmap_regular(size_t size)
Definition: largepage.c:33