1#define	JEMALLOC_BASE_C_
2#include "jemalloc/internal/jemalloc_internal.h"
3
4/******************************************************************************/
5/* Data. */
6
7static malloc_mutex_t	base_mtx;
8
9/*
10 * Current pages that are being used for internal memory allocations.  These
11 * pages are carved up in cacheline-size quanta, so that there is no chance of
12 * false cache line sharing.
13 */
14static void		*base_pages;
15static void		*base_next_addr;
16static void		*base_past_addr; /* Addr immediately past base_pages. */
17static extent_node_t	*base_nodes;
18
19/******************************************************************************/
20
21static bool
22base_pages_alloc(size_t minsize)
23{
24	size_t csize;
25
26	assert(minsize != 0);
27	csize = CHUNK_CEILING(minsize);
28	base_pages = chunk_alloc_base(csize);
29	if (base_pages == NULL)
30		return (true);
31	base_next_addr = base_pages;
32	base_past_addr = (void *)((uintptr_t)base_pages + csize);
33
34	return (false);
35}
36
37void *
38base_alloc(size_t size)
39{
40	void *ret;
41	size_t csize;
42
43	/* Round size up to nearest multiple of the cacheline size. */
44	csize = CACHELINE_CEILING(size);
45
46	malloc_mutex_lock(&base_mtx);
47	/* Make sure there's enough space for the allocation. */
48	if ((uintptr_t)base_next_addr + csize > (uintptr_t)base_past_addr) {
49		if (base_pages_alloc(csize)) {
50			malloc_mutex_unlock(&base_mtx);
51			return (NULL);
52		}
53	}
54	/* Allocate. */
55	ret = base_next_addr;
56	base_next_addr = (void *)((uintptr_t)base_next_addr + csize);
57	malloc_mutex_unlock(&base_mtx);
58	JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret, csize);
59
60	return (ret);
61}
62
63void *
64base_calloc(size_t number, size_t size)
65{
66	void *ret = base_alloc(number * size);
67
68	if (ret != NULL)
69		memset(ret, 0, number * size);
70
71	return (ret);
72}
73
74extent_node_t *
75base_node_alloc(void)
76{
77	extent_node_t *ret;
78
79	malloc_mutex_lock(&base_mtx);
80	if (base_nodes != NULL) {
81		ret = base_nodes;
82		base_nodes = *(extent_node_t **)ret;
83		malloc_mutex_unlock(&base_mtx);
84		JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(ret,
85		    sizeof(extent_node_t));
86	} else {
87		malloc_mutex_unlock(&base_mtx);
88		ret = (extent_node_t *)base_alloc(sizeof(extent_node_t));
89	}
90
91	return (ret);
92}
93
94void
95base_node_dalloc(extent_node_t *node)
96{
97
98	JEMALLOC_VALGRIND_MAKE_MEM_UNDEFINED(node, sizeof(extent_node_t));
99	malloc_mutex_lock(&base_mtx);
100	*(extent_node_t **)node = base_nodes;
101	base_nodes = node;
102	malloc_mutex_unlock(&base_mtx);
103}
104
105bool
106base_boot(void)
107{
108
109	base_nodes = NULL;
110	if (malloc_mutex_init(&base_mtx))
111		return (true);
112
113	return (false);
114}
115
116void
117base_prefork(void)
118{
119
120	malloc_mutex_prefork(&base_mtx);
121}
122
123void
124base_postfork_parent(void)
125{
126
127	malloc_mutex_postfork_parent(&base_mtx);
128}
129
130void
131base_postfork_child(void)
132{
133
134	malloc_mutex_postfork_child(&base_mtx);
135}
136