1 /*
2  * Copyright (C) 2021 Jakub Kruszona-Zawadzki, Core Technology Sp. z o.o.
3  *
4  * This file is part of MooseFS.
5  *
6  * MooseFS is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, version 2 (only).
9  *
10  * MooseFS is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with MooseFS; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA
18  * or visit http://www.gnu.org/licenses/gpl-2.0.html
19  */
20 
21 #ifndef _BUCKETS_H_
22 #define _BUCKETS_H_
23 
24 
25 #ifdef BUCKETS_MMAP_ALLOC
26 #include <sys/mman.h>
27 #define BUCKETS_ALLOC(size) mmap(NULL,size,PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1,0)
28 #define BUCKETS_FREE(p,size) munmap(p,size)
29 #else
30 #define BUCKETS_ALLOC(size) malloc(size)
31 #define BUCKETS_FREE(p,size) free(p)
32 #endif
33 
34 #define CREATE_BUCKET_ALLOCATOR(allocator_name,element_type,bucket_size) \
35 typedef struct _##allocator_name##_bucket { \
36 	element_type bucket[bucket_size]; \
37 	uint32_t firstfree; \
38 	struct _##allocator_name##_bucket *next; \
39 } allocator_name##_bucket; \
40 static allocator_name##_bucket *allocator_name##_buckets_head = NULL; \
41 static void *allocator_name##_free_head = NULL; \
42 static uint64_t allocator_name##_allocated = 0; \
43 static uint64_t allocator_name##_used = 0; \
44 static inline void allocator_name##_free_all(void) { \
45 	allocator_name##_bucket *srb,*nsrb; \
46 	for (srb = allocator_name##_buckets_head ; srb ; srb = nsrb) { \
47 		nsrb = srb->next; \
48 		BUCKETS_FREE(srb,sizeof(allocator_name##_bucket)); \
49 	} \
50 	allocator_name##_buckets_head = NULL; \
51 	allocator_name##_free_head = NULL; \
52 	allocator_name##_allocated = 0; \
53 	allocator_name##_used = 0; \
54 } \
55 static inline element_type* allocator_name##_malloc() { \
56 	allocator_name##_bucket *srb; \
57 	element_type *ret; \
58 	if (allocator_name##_free_head) { \
59 		ret = (element_type*)allocator_name##_free_head; \
60 		allocator_name##_free_head = *((void**)(ret)); \
61 		allocator_name##_used += sizeof(element_type); \
62 		return ret; \
63 	} \
64 	if (allocator_name##_buckets_head==NULL || allocator_name##_buckets_head->firstfree==(bucket_size)) { \
65 		srb = (allocator_name##_bucket*)BUCKETS_ALLOC(sizeof(allocator_name##_bucket)); \
66 		passert(srb); \
67 		srb->next = allocator_name##_buckets_head; \
68 		srb->firstfree = 0; \
69 		allocator_name##_buckets_head = srb; \
70 		allocator_name##_allocated += sizeof(allocator_name##_bucket); \
71 	} \
72 	ret = (allocator_name##_buckets_head->bucket)+(allocator_name##_buckets_head->firstfree); \
73 	allocator_name##_buckets_head->firstfree++; \
74 	allocator_name##_used += sizeof(element_type); \
75 	return ret; \
76 } \
77 static inline void allocator_name##_free(element_type *p) { \
78 	*((void**)p) = allocator_name##_free_head; \
79 	allocator_name##_free_head = (void*)p; \
80 	allocator_name##_used -= sizeof(element_type); \
81 } \
82 static inline void allocator_name##_getusage(uint64_t *allocated,uint64_t *used) { \
83 	*allocated = allocator_name##_allocated ; \
84 	*used = allocator_name##_used ; \
85 }
86 
87 #endif
88