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_MT_H_ 22 #define _BUCKETS_MT_H_ 23 24 #ifdef BUCKETS_MT_MMAP_ALLOC 25 #include <sys/mman.h> 26 #define BUCKETS_MT_ALLOC(size) mmap(NULL,size,PROT_READ | PROT_WRITE, MAP_ANON | MAP_PRIVATE,-1,0) 27 #define BUCKETS_MT_FREE(p,size) munmap(p,size) 28 #else 29 #define BUCKETS_MT_ALLOC(size) malloc(size) 30 #define BUCKETS_MT_FREE(p,size) free(p) 31 #endif 32 33 #include <pthread.h> 34 #include <inttypes.h> 35 36 #define CREATE_BUCKET_MT_ALLOCATOR(allocator_name,element_type,bucket_size) \ 37 typedef struct _##allocator_name##_bucket { \ 38 element_type bucket[bucket_size]; \ 39 uint32_t firstfree; \ 40 struct _##allocator_name##_bucket *next; \ 41 } allocator_name##_bucket; \ 42 static allocator_name##_bucket *allocator_name##_buckets_head = NULL; \ 43 static void *allocator_name##_free_head = NULL; \ 44 static uint64_t allocator_name##_allocated = 0; \ 45 static uint64_t allocator_name##_used = 0; \ 46 static pthread_mutex_t allocator_name##_lock = PTHREAD_MUTEX_INITIALIZER; \ 47 static inline void allocator_name##_free_all(void) { \ 48 allocator_name##_bucket *srb,*nsrb; \ 49 pthread_mutex_lock(&allocator_name##_lock); \ 50 for (srb = allocator_name##_buckets_head ; srb ; srb = nsrb) { \ 51 nsrb = srb->next; \ 52 BUCKETS_MT_FREE(srb,sizeof(allocator_name##_bucket)); \ 53 } \ 54 allocator_name##_buckets_head = NULL; \ 55 allocator_name##_free_head = NULL; \ 56 allocator_name##_allocated = 0; \ 57 allocator_name##_used = 0; \ 58 pthread_mutex_unlock(&allocator_name##_lock); \ 59 } \ 60 static inline element_type* allocator_name##_malloc() { \ 61 allocator_name##_bucket *srb; \ 62 element_type *ret; \ 63 pthread_mutex_lock(&allocator_name##_lock); \ 64 if (allocator_name##_free_head) { \ 65 ret = (element_type*)allocator_name##_free_head; \ 66 allocator_name##_free_head = *((void**)(ret)); \ 67 allocator_name##_used += sizeof(element_type); \ 68 pthread_mutex_unlock(&allocator_name##_lock); \ 69 return ret; \ 70 } \ 71 if (allocator_name##_buckets_head==NULL || allocator_name##_buckets_head->firstfree==(bucket_size)) { \ 72 srb = (allocator_name##_bucket*)BUCKETS_MT_ALLOC(sizeof(allocator_name##_bucket)); \ 73 passert(srb); \ 74 srb->next = allocator_name##_buckets_head; \ 75 srb->firstfree = 0; \ 76 allocator_name##_buckets_head = srb; \ 77 allocator_name##_allocated += sizeof(allocator_name##_bucket); \ 78 } \ 79 ret = (allocator_name##_buckets_head->bucket)+(allocator_name##_buckets_head->firstfree); \ 80 allocator_name##_buckets_head->firstfree++; \ 81 allocator_name##_used += sizeof(element_type); \ 82 pthread_mutex_unlock(&allocator_name##_lock); \ 83 return ret; \ 84 } \ 85 static inline void allocator_name##_free(element_type *p) { \ 86 pthread_mutex_lock(&allocator_name##_lock); \ 87 *((void**)p) = allocator_name##_free_head; \ 88 allocator_name##_free_head = (void*)p; \ 89 allocator_name##_used -= sizeof(element_type); \ 90 pthread_mutex_unlock(&allocator_name##_lock); \ 91 } \ 92 static inline void allocator_name##_getusage(uint64_t *allocated,uint64_t *used) { \ 93 pthread_mutex_lock(&allocator_name##_lock); \ 94 *allocated = allocator_name##_allocated ; \ 95 *used = allocator_name##_used ; \ 96 pthread_mutex_unlock(&allocator_name##_lock); \ 97 } 98 99 #endif 100