area_linux.c 7.38 KB
Newer Older
Swann Perarnau's avatar
Swann Perarnau committed
1 2 3 4 5 6 7 8 9 10
/*******************************************************************************
 * Copyright 2019 UChicago Argonne, LLC.
 * (c.f. AUTHORS, LICENSE)
 *
 * This file is part of the AML project.
 * For more info, see https://xgitlab.cels.anl.gov/argo/aml
 *
 * SPDX-License-Identifier: BSD-3-Clause
*******************************************************************************/

11
#include "aml.h"
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
#include <assert.h>
#include <sys/mman.h>

/*******************************************************************************
 * Linux backed area:
 * The area itself is organized into various two sets of data:
 * - parameters that defines what policies are applied
 * - methods that implement those policies
 * This is designed similarly to component-entity-systems.
 ******************************************************************************/

/* two functions used by arenas to handle real allocations */

void *aml_area_linux_mmap(struct aml_area_data *a, void *ptr, size_t sz)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
29
	return area->ops.mmap.mmap(&area->data.mmap, ptr, sz);
30 31
}

Kamil Iskra's avatar
Kamil Iskra committed
32
int aml_area_linux_available(const struct aml_area_data *a)
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
{
	return 1;
}

/*******************************************************************************
 * Public API:
 * The actual functions that will be called on the area from users
 * Respect the POSIX spec for those functions.
 ******************************************************************************/

void *aml_area_linux_malloc(struct aml_area_data *a, size_t size)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
49
	void *ret;
50 51 52
	assert(arena != NULL);
	if(size == 0)
		return NULL;
53 54 55 56 57

	area->ops.mbind.pre_bind(&area->data.mbind);
	ret = aml_arena_mallocx(arena, size, AML_ARENA_FLAG_ZERO);
	area->ops.mbind.post_bind(&area->data.mbind, ret, size);
	return ret;
58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
}

void aml_area_linux_free(struct aml_area_data *a, void *ptr)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
	assert(arena != NULL);
	if(ptr == NULL)
		return;
	aml_arena_dallocx(arena, ptr, 0);
}

void *aml_area_linux_calloc(struct aml_area_data *a, size_t num, size_t size)
{
	assert(a != NULL);
	return aml_area_linux_malloc(a, num*size);
}

78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96
void *aml_area_linux_memalign(struct aml_area_data *a, size_t align,
			      size_t size)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
	void *ret;
	assert(arena != NULL);
	if(size == 0)
		return NULL;

	area->ops.mbind.pre_bind(&area->data.mbind);
	ret = aml_arena_mallocx(arena, size, AML_ARENA_FLAG_ZERO |
				AML_ARENA_FLAG_ALIGN(align));
	area->ops.mbind.post_bind(&area->data.mbind, ret, size);
	return ret;
}

97 98 99 100 101 102 103 104 105 106 107 108 109 110
void *aml_area_linux_realloc(struct aml_area_data *a, void *ptr, size_t size)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	if(ptr == NULL)
		return aml_area_linux_malloc(a, size);
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
	assert(arena != NULL);
	if(size == 0)
	{
		aml_arena_dallocx(arena, ptr, 0);
		return NULL;
	}
111 112 113 114 115

	area->ops.mbind.pre_bind(&area->data.mbind);
	ptr = aml_arena_reallocx(arena, ptr, size, 0);
	area->ops.mbind.post_bind(&area->data.mbind, ptr, size);
	return ptr;
116 117 118 119 120 121 122 123
}

void *aml_area_linux_acquire(struct aml_area_data *a, size_t size)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
124
	void *ret;
125
	assert(arena != NULL);
126 127 128 129
	area->ops.mbind.pre_bind(&area->data.mbind);
	ret = aml_arena_mallocx(arena, size, 0);
	area->ops.mbind.post_bind(&area->data.mbind, ret, size);
	return ret;
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
}

void aml_area_linux_release(struct aml_area_data *a, void *ptr)
{
	assert(a != NULL);
	struct aml_area_linux *area = (struct aml_area_linux *)a;
	struct aml_arena *arena = (struct aml_arena *)
		area->ops.manager.get_arena(&area->data.manager);
	assert(arena != NULL);
	aml_arena_dallocx(arena, ptr, 0);
}

struct aml_area_ops aml_area_linux_ops = {
	aml_area_linux_malloc,
	aml_area_linux_free,
	aml_area_linux_calloc,
146
	aml_area_linux_memalign,
147 148 149 150 151 152 153 154 155 156 157 158
	aml_area_linux_realloc,
	aml_area_linux_acquire,
	aml_area_linux_release,
	aml_area_linux_mmap,
	aml_area_linux_available,
};

/*******************************************************************************
 * Initialization/Destroy function:
 * Collections of init/destroy functions for popular types of linux-based areas
 ******************************************************************************/

159 160
int aml_area_linux_create(struct aml_area **a, int manager_type,
			  int mbind_type, int mmap_type, ...)
161
{
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
	va_list ap;
	struct aml_area *ret = NULL;
	intptr_t baseptr, dataptr;
	va_start(ap, mmap_type);

	/* alloc */
	baseptr = (intptr_t) calloc(1, AML_AREA_LINUX_ALLOCSIZE);
	dataptr = baseptr + sizeof(struct aml_area);

	ret = (struct aml_area *)baseptr;
	ret->data = (struct aml_area_data *)dataptr;

	aml_area_linux_vinit(ret, manager_type, mbind_type, mmap_type, ap);

	va_end(ap);
	*a = ret;
	return 0;

}

int aml_area_linux_vinit(struct aml_area *a, int manager_type,
			 int mbind_type, int mmap_type, va_list ap)
{
	a->ops = &aml_area_linux_ops;
	struct aml_area_linux *area = (struct aml_area_linux *)a->data;

	/* manager init */
	assert(manager_type == AML_AREA_LINUX_MANAGER_TYPE_SINGLE);
	struct aml_arena *arena = va_arg(ap, struct aml_arena *);
	aml_area_linux_manager_single_init(&area->data.manager, arena);
	area->ops.manager = aml_area_linux_manager_single_ops;

	/* mbind init */
	int policy = va_arg(ap, int);
	unsigned long *nodemask = va_arg(ap, unsigned long *);
	aml_area_linux_mbind_init(&area->data.mbind, policy, nodemask);
	if(mbind_type == AML_AREA_LINUX_MBIND_TYPE_REGULAR)
		area->ops.mbind = aml_area_linux_mbind_regular_ops;
	else if(mbind_type == AML_AREA_LINUX_MBIND_TYPE_MEMPOLICY)
		area->ops.mbind = aml_area_linux_mbind_mempolicy_ops;

	/* mmap init */
	area->ops.mmap = aml_area_linux_mmap_generic_ops;
	if(mmap_type == AML_AREA_LINUX_MMAP_TYPE_ANONYMOUS)
		aml_area_linux_mmap_anonymous_init(&area->data.mmap);
	else if(mmap_type == AML_AREA_LINUX_MMAP_TYPE_FD)
	{
		int fd = va_arg(ap, int);
210 211
		off_t offset = va_arg(ap, off_t);
		aml_area_linux_mmap_fd_init(&area->data.mmap, fd, offset);
212 213 214 215 216 217 218 219 220
	}
	else if(mmap_type == AML_AREA_LINUX_MMAP_TYPE_TMPFILE)
	{
		char *template = va_arg(ap, char*);
		size_t max = va_arg(ap, size_t);
		aml_area_linux_mmap_tmpfile_init(&area->data.mmap, template,
						 max);
	}
	aml_arena_register(arena, a);
221 222 223
	return 0;
}

224 225 226 227 228 229 230 231 232 233 234 235 236
int aml_area_linux_init(struct aml_area *a, int manager_type,
			int mbind_type, int mmap_type, ...)
{
	int err;
	va_list ap;
	va_start(ap, mmap_type);
	err = aml_area_linux_vinit(a, manager_type, mbind_type, mmap_type, ap);
	va_end(ap);
	return err;

}

int aml_area_linux_destroy(struct aml_area *a)
237
{
238 239 240 241 242 243 244
	struct aml_area_linux *area = (struct aml_area_linux *)a->data;
	struct aml_arena *arena = area->data.manager.pool;
	aml_arena_deregister(arena);
	aml_area_linux_mmap_anonymous_destroy(&area->data.mmap);
	aml_area_linux_mbind_destroy(&area->data.mbind);
	aml_area_linux_manager_single_destroy(&area->data.manager);
	aml_arena_jemalloc_destroy(arena);
245 246
	return 0;
}