├── .gitignore ├── LICENSE ├── Makefile ├── README ├── buffer ├── ccan │ ├── alignof │ │ ├── _info │ │ └── alignof.h │ ├── antithread │ │ └── alloc │ │ │ ├── _info │ │ │ ├── alloc.c │ │ │ ├── alloc.h │ │ │ ├── bitops.c │ │ │ ├── bitops.h │ │ │ ├── tiny.c │ │ │ └── tiny.h │ ├── build_assert │ │ ├── _info │ │ └── build_assert.h │ ├── compiler │ │ ├── _info │ │ └── compiler.h │ ├── ilog │ │ ├── _info │ │ ├── ilog.c │ │ └── ilog.h │ ├── short_types │ │ ├── _info │ │ └── short_types.h │ └── str │ │ ├── _info │ │ ├── debug.c │ │ ├── str.c │ │ ├── str.h │ │ └── str_debug.h ├── config.h └── licenses │ ├── CC0 │ └── LGPL-2.1 ├── buffer_nofree └── nofree.c ├── buffer_simple └── memmgr.c ├── buffer_slab └── slab.c ├── include ├── buffer │ └── alloc.h ├── buffer_nofree │ └── nofree.h ├── buffer_simple │ └── memmgr.h ├── buffer_slab │ └── slab.h ├── mplite │ ├── mplite.h │ └── pstdint.h └── shalloc │ └── shalloc.h ├── mplite └── mplite.c └── shalloc ├── buffer.c ├── heap.c ├── include ├── interface.h └── util.h ├── interface ├── buffer.c ├── buffer_nofree.c ├── buffer_simple.c ├── buffer_slab.c └── mplite.c ├── region.c └── shalloc.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.so 3 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2016 Vrije Universiteit Amsterdam 2 | 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 9 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | SRCS = $(wildcard buffer/ccan/*/*.c) $(wildcard buffer/ccan/*/*/*.c) $(wildcard buffer_nofree/*.c) $(wildcard buffer_simple/*.c) $(wildcard mplite/*.c) $(wildcard shalloc/*.c) $(wildcard buffer_slab/*.c) $(wildcard shalloc/interface/*.c) 2 | HEADERS = $(wildcard include/*.h) $(wildcard include/common/alloc/*/*.h) $(wildcard include/common/alloc/*/*/*.h) $(wildcard buffer/ccan/*/*.h) $(wildcard buffer/ccan/*/*/*.h) 3 | 4 | CFLAGS = -Wall -Wextra -O2 -I./buffer -I./include -fpic 5 | LDFLAGS = -shared -O2 6 | OBJS := $(SRCS:%.c=%.o) 7 | 8 | all: shalloc.so 9 | 10 | shalloc.so: $(OBJS) $(HEADERS) 11 | @echo "[LINK] $@" 12 | @$(CC) -o $@ $(OBJS) $(LDFLAGS) 13 | 14 | %.o: %.c $(HEADERS) 15 | @echo "[CC] $<" 16 | @$(CC) -c -o $@ $< $(CFLAGS) 17 | 18 | clean: 19 | @echo "[RM] shalloc.so" 20 | @rm shalloc.so 21 | @echo "[RM] $(OBJS)" 22 | @rm $(OBJS) 23 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Library containing a number of modular memory allocators. Contains support for a 2 | number of different types of allocators which can be combined. Furthermore, 3 | shalloc supports allocators in shared memory, meaning any process attached to 4 | this memory can malloc/free, visible to all other processes. 5 | 6 | Licenses: note that most allocators in this projects are pre-existing/external 7 | projects. As such, these projects have different licenses than shalloc itself. 8 | -------------------------------------------------------------------------------- /buffer/ccan/alignof/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * alignof - ALIGNOF() macro to determine alignment of a type. 7 | * 8 | * Many platforms have requirements that certain types must be aligned 9 | * to certain address boundaries, such as ints needing to be on 4-byte 10 | * boundaries. Attempting to access variables with incorrect 11 | * alignment may cause performance loss or even program failure (eg. a 12 | * bus signal). 13 | * 14 | * There are times which it's useful to be able to programatically 15 | * access these requirements, such as for dynamic allocators. 16 | * 17 | * Example: 18 | * #include 19 | * #include 20 | * #include 21 | * 22 | * // Output contains "ALIGNOF(char) == 1" 23 | * // Will also print out whether an onstack char array can hold a long. 24 | * int main(int argc, char *argv[]) 25 | * { 26 | * char arr[sizeof(int)]; 27 | * 28 | * printf("ALIGNOF(char) == %zu\n", ALIGNOF(char)); 29 | * if ((unsigned long)arr % ALIGNOF(int)) { 30 | * printf("arr %p CANNOT hold an int\n", arr); 31 | * exit(1); 32 | * } else { 33 | * printf("arr %p CAN hold an int\n", arr); 34 | * exit(0); 35 | * } 36 | * } 37 | * 38 | * License: CC0 (Public domain) 39 | * Author: Rusty Russell 40 | */ 41 | int main(int argc, char *argv[]) 42 | { 43 | if (argc != 2) 44 | return 1; 45 | 46 | if (strcmp(argv[1], "depends") == 0) { 47 | return 0; 48 | } 49 | 50 | return 1; 51 | } 52 | -------------------------------------------------------------------------------- /buffer/ccan/alignof/alignof.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_ALIGNOF_H 3 | #define CCAN_ALIGNOF_H 4 | #include "config.h" 5 | 6 | /** 7 | * ALIGNOF - get the alignment of a type 8 | * @t: the type to test 9 | * 10 | * This returns a safe alignment for the given type. 11 | */ 12 | #if HAVE_ALIGNOF 13 | /* A GCC extension. */ 14 | #define ALIGNOF(t) __alignof__(t) 15 | #else 16 | /* Alignment by measuring structure padding. */ 17 | #define ALIGNOF(t) ((char *)(&((struct { char c; t _h; } *)0)->_h) - (char *)0) 18 | #endif 19 | 20 | #endif /* CCAN_ALIGNOF_H */ 21 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * antithread/alloc - memory allocator routines 7 | * 8 | * The alloc module implements a simple allocator which you can use to 9 | * dynamically allocate space within a region of memory. This can be useful 10 | * for suballocations within a given region, or a memory-mapped file. 11 | * 12 | * All metadata is kept within the memory handed to the allocator: you only 13 | * need hand the pointer and the size of the memory to each call. 14 | * 15 | * The region contents is always in offsets, so it can be mapped in different 16 | * places, but is not endian-safe. 17 | * 18 | * Example: 19 | * #include 20 | * #include 21 | * #include 22 | * #include 23 | * #include 24 | * #include 25 | * #include 26 | * #include 27 | * #include 28 | * 29 | * static void usage(const char *name) 30 | * { 31 | * errx(1, "Usage: %s --create \n" 32 | * " %s --check \n" 33 | * " %s --alloc \n" 34 | * " %s --free= \n", name, name, name, name); 35 | * } 36 | * 37 | * // Create a memory mapped file, and allocate from within it 38 | * int main(int argc, char *argv[]) 39 | * { 40 | * void *a, *p; 41 | * int fd; 42 | * enum { CREATE, CHECK, ALLOC, FREE } cmd; 43 | * 44 | * if (argc != 3) 45 | * usage(argv[0]); 46 | * 47 | * if (strcmp(argv[1], "--create") == 0) 48 | * cmd = CREATE; 49 | * else if (strcmp(argv[1], "--check") == 0) 50 | * cmd = CHECK; 51 | * else if (strcmp(argv[1], "--alloc") == 0) 52 | * cmd = ALLOC; 53 | * else if (strncmp(argv[1], "--free=", strlen("--free=")) == 0) 54 | * cmd = FREE; 55 | * else 56 | * usage(argv[0]); 57 | * 58 | * if (cmd == CREATE) { 59 | * fd = open(argv[2], O_RDWR|O_CREAT|O_EXCL, 0600); 60 | * if (fd < 0) 61 | * err(1, "Could not create %s", argv[2]); 62 | * if (ftruncate(fd, 1048576) != 0) 63 | * err(1, "Could not set length on %s", argv[2]); 64 | * } else { 65 | * fd = open(argv[2], O_RDWR); 66 | * if (fd < 0) 67 | * err(1, "Could not open %s", argv[2]); 68 | * } 69 | * 70 | * a = mmap(NULL, 1048576, PROT_READ|PROT_WRITE, MAP_SHARED, fd,0); 71 | * if (a == MAP_FAILED) 72 | * err(1, "Could not map %s", argv[2]); 73 | * 74 | * switch (cmd) { 75 | * case CREATE: 76 | * alloc_init(a, 1048576); 77 | * break; 78 | * case CHECK: 79 | * if (!alloc_check(a, 1048576)) 80 | * err(1, "Region is corrupt"); 81 | * break; 82 | * case ALLOC: 83 | * p = alloc_get(a, 1048576, 1024, 16); 84 | * if (!p) 85 | * errx(1, "Could not allocate"); 86 | * printf("%zu\n", (char *)p - (char *)a); 87 | * break; 88 | * case FREE: 89 | * p = (char *)a + atol(argv[1] + strlen("--free=")); 90 | * alloc_free(a, 1048576, p); 91 | * break; 92 | * } 93 | * return 0; 94 | * } 95 | * 96 | * License: LGPL (v2.1 or any later version) 97 | * Author: Rusty Russell 98 | */ 99 | int main(int argc, char *argv[]) 100 | { 101 | if (argc != 2) 102 | return 1; 103 | 104 | if (strcmp(argv[1], "depends") == 0) { 105 | printf("ccan/alignof\n"); 106 | printf("ccan/build_assert\n"); 107 | printf("ccan/compiler\n"); 108 | printf("ccan/ilog\n"); 109 | printf("ccan/likely\n"); 110 | printf("ccan/short_types\n"); 111 | return 0; 112 | } 113 | 114 | return 1; 115 | } 116 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/alloc.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #ifndef ALLOC_H 3 | #define ALLOC_H 4 | #include 5 | #include 6 | 7 | /** 8 | * alloc_init - initialize a pool of memory for the allocator. 9 | * @pool: the contiguous bytes for the allocator to use 10 | * @poolsize: the size of the pool 11 | * 12 | * This stores all the setup state required to perform allocation within the 13 | * pool (there is no external state). Any previous contents of @pool is 14 | * discarded. 15 | * 16 | * The same @pool and @poolsize arguments must be handed to the other alloc 17 | * functions after this. 18 | * 19 | * If the pool is too small for meaningful allocations, alloc_get will fail. 20 | * 21 | * Example: 22 | * void *pool = malloc(32*1024*1024); 23 | * if (!pool) 24 | * err(1, "Failed to allocate 32MB"); 25 | * alloc_init(pool, 32*1024*1024); 26 | */ 27 | void alloc_init(void *pool, unsigned long poolsize); 28 | 29 | /** 30 | * alloc_get - allocate some memory from the pool 31 | * @pool: the contiguous bytes for the allocator to use 32 | * @poolsize: the size of the pool 33 | * @size: the size of the desired allocation 34 | * @align: the alignment of the desired allocation (0 or power of 2) 35 | * 36 | * This is "malloc" within an initialized pool. 37 | * 38 | * It will return a unique pointer within the pool (ie. between @pool 39 | * and @pool+@poolsize) which meets the alignment requirements of 40 | * @align. Note that the alignment is relative to the start of the pool, 41 | * so of @pool is not aligned, the pointer won't be either. 42 | * 43 | * Returns NULL if there is no contiguous room. 44 | * 45 | * Example: 46 | * #include 47 | * ... 48 | * double *d = alloc_get(pool, 32*1024*1024, 49 | * sizeof(*d), ALIGNOF(*d)); 50 | * if (!d) 51 | * err(1, "Failed to allocate a double"); 52 | */ 53 | void *alloc_get(void *pool, unsigned long poolsize, 54 | unsigned long size, unsigned long align); 55 | 56 | /** 57 | * alloc_free - free some allocated memory from the pool 58 | * @pool: the contiguous bytes for the allocator to use 59 | * @poolsize: the size of the pool 60 | * @p: the non-NULL pointer returned from alloc_get. 61 | * 62 | * This is "free" within an initialized pool. A pointer should only be 63 | * freed once, and must be a pointer returned from a successful alloc_get() 64 | * call. 65 | * 66 | * Example: 67 | * alloc_free(pool, 32*1024*1024, d); 68 | */ 69 | void alloc_free(void *pool, unsigned long poolsize, void *free); 70 | 71 | /** 72 | * alloc_size - get the actual size allocated by alloc_get 73 | * @pool: the contiguous bytes for the allocator to use 74 | * @poolsize: the size of the pool 75 | * @p: the non-NULL pointer returned from alloc_get. 76 | * 77 | * alloc_get() may overallocate, in which case you may use the extra 78 | * space exactly as if you had asked for it. 79 | * 80 | * The return value will always be at least the @size passed to alloc_get(). 81 | * 82 | * Example: 83 | * printf("Allocating a double actually got me %lu bytes\n", 84 | * alloc_size(pool, 32*1024*1024, d)); 85 | */ 86 | unsigned long alloc_size(void *pool, unsigned long poolsize, void *p); 87 | 88 | /** 89 | * alloc_check - check the integrity of the allocation pool 90 | * @pool: the contiguous bytes for the allocator to use 91 | * @poolsize: the size of the pool 92 | * 93 | * alloc_check() can be used for debugging suspected pool corruption. It may 94 | * be quite slow, but provides some assistance for hard-to-find overruns or 95 | * double-frees. Unlike the rest of the code, it will not crash on corrupted 96 | * pools. 97 | * 98 | * There is an internal function check_fail() which this calls on failure which 99 | * is useful for placing breakpoints and gaining more insight into the type 100 | * of the corruption detected. 101 | * 102 | * Example: 103 | * #include 104 | * ... 105 | * assert(alloc_check(pool, 32*1024*1024)); 106 | */ 107 | bool alloc_check(void *pool, unsigned long poolsize); 108 | 109 | /** 110 | * alloc_visualize - dump information about the allocation pool 111 | * @pool: the contiguous bytes for the allocator to use 112 | * @poolsize: the size of the pool 113 | * 114 | * When debugging the allocator itself, it's often useful to see how 115 | * the pool is being used. alloc_visualize() does that, but makes 116 | * assumptions about correctness (like the rest of the code) so if you 117 | * suspect corruption call alloc_check() first. 118 | * 119 | * Example: 120 | * d = alloc_get(pool, 32*1024*1024, sizeof(*d), ALIGNOF(*d)); 121 | * if (!d) { 122 | * fprintf(stderr, "Allocation failed!\n"); 123 | * if (!alloc_check(pool, 32*1024*1024)) 124 | * errx(1, "Allocation pool is corrupt"); 125 | * alloc_visualize(stderr, pool, 32*1024*1024); 126 | * exit(1); 127 | * } 128 | */ 129 | void alloc_visualize(FILE *out, void *pool, unsigned long poolsize); 130 | #endif /* ALLOC_H */ 131 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/bitops.c: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #include "bitops.h" 3 | #include "config.h" 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | unsigned int afls(unsigned long val) 10 | { 11 | BUILD_ASSERT(sizeof(val) == sizeof(u32) || sizeof(val) == sizeof(u64)); 12 | if (sizeof(val) == sizeof(u32)) 13 | return ilog32(val); 14 | else 15 | return ilog64(val); 16 | } 17 | 18 | /* FIXME: Move to bitops. */ 19 | unsigned int affsl(unsigned long val) 20 | { 21 | #if HAVE_BUILTIN_FFSL 22 | /* This is significantly faster! */ 23 | return __builtin_ffsl(val); 24 | #else 25 | unsigned int r = 1; 26 | 27 | if (!val) 28 | return 0; 29 | if (sizeof(long) == sizeof(u64)) { 30 | if (!(val & 0xffffffff)) { 31 | /* Workaround gcc warning on 32-bit: 32 | error: right shift count >= width of type */ 33 | u64 tmp = val; 34 | tmp >>= 32; 35 | val = tmp; 36 | r += 32; 37 | } 38 | } 39 | if (!(val & 0xffff)) { 40 | val >>= 16; 41 | r += 16; 42 | } 43 | if (!(val & 0xff)) { 44 | val >>= 8; 45 | r += 8; 46 | } 47 | if (!(val & 0xf)) { 48 | val >>= 4; 49 | r += 4; 50 | } 51 | if (!(val & 3)) { 52 | val >>= 2; 53 | r += 2; 54 | } 55 | if (!(val & 1)) { 56 | val >>= 1; 57 | r += 1; 58 | } 59 | return r; 60 | #endif 61 | } 62 | 63 | unsigned int apopcount(unsigned long val) 64 | { 65 | #if HAVE_BUILTIN_POPCOUNTL 66 | return __builtin_popcountl(val); 67 | #else 68 | if (sizeof(long) == sizeof(u64)) { 69 | u64 v = val; 70 | v = (v & 0x5555555555555555ULL) 71 | + ((v >> 1) & 0x5555555555555555ULL); 72 | v = (v & 0x3333333333333333ULL) 73 | + ((v >> 2) & 0x3333333333333333ULL); 74 | v = (v & 0x0F0F0F0F0F0F0F0FULL) 75 | + ((v >> 4) & 0x0F0F0F0F0F0F0F0FULL); 76 | v = (v & 0x00FF00FF00FF00FFULL) 77 | + ((v >> 8) & 0x00FF00FF00FF00FFULL); 78 | v = (v & 0x0000FFFF0000FFFFULL) 79 | + ((v >> 16) & 0x0000FFFF0000FFFFULL); 80 | v = (v & 0x00000000FFFFFFFFULL) 81 | + ((v >> 32) & 0x00000000FFFFFFFFULL); 82 | return v; 83 | } 84 | val = (val & 0x55555555ULL) + ((val >> 1) & 0x55555555ULL); 85 | val = (val & 0x33333333ULL) + ((val >> 2) & 0x33333333ULL); 86 | val = (val & 0x0F0F0F0FULL) + ((val >> 4) & 0x0F0F0F0FULL); 87 | val = (val & 0x00FF00FFULL) + ((val >> 8) & 0x00FF00FFULL); 88 | val = (val & 0x0000FFFFULL) + ((val >> 16) & 0x0000FFFFULL); 89 | return val; 90 | #endif 91 | } 92 | 93 | unsigned long align_up(unsigned long x, unsigned long align) 94 | { 95 | return (x + align - 1) & ~(align - 1); 96 | } 97 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/bitops.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #ifndef CCAN_ALLOC_BITOPS_H 3 | #define CCAN_ALLOC_BITOPS_H 4 | unsigned int afls(unsigned long val); 5 | unsigned int affsl(unsigned long val); 6 | unsigned int apopcount(unsigned long val); 7 | unsigned long align_up(unsigned long x, unsigned long align); 8 | #endif /* CCAN_ALLOC_BITOPS_H */ 9 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/tiny.c: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #include "tiny.h" 3 | #include "bitops.h" 4 | #include 5 | #include 6 | #include 7 | 8 | /* One byte header, one byte data. */ 9 | #define MIN_BLOCK_SIZE 2 10 | 11 | /* Bit 7 (in any byte) == start or end. */ 12 | #define TERM_BIT 0x80 13 | /* Bit 6 (first and last byte) == one byte long. */ 14 | #define SINGLE_BYTE 0x40 15 | /* Bit 5 (of first byte) == "is this block free?" */ 16 | #define FREE_BIT 0x20 17 | 18 | #define MAX_FREE_CACHED_SIZE 256 19 | 20 | /* Val is usually offset by MIN_BLOCK_SIZE here. */ 21 | static unsigned encode_length(unsigned long val) 22 | { 23 | unsigned int bits = afls(val); 24 | /* 5 bits in first byte. */ 25 | if (bits <= 5) 26 | return 1; 27 | /* 6 bits in last byte, 7 bits in middle ones. */ 28 | return 2 + (bits - 5) / 7; 29 | } 30 | 31 | /* Header is included in length, so we might need an extra byte. */ 32 | static unsigned encode_len_with_header(unsigned long len) 33 | { 34 | unsigned int hdrlen = 1; 35 | 36 | assert(len); 37 | while (encode_length(len + hdrlen - MIN_BLOCK_SIZE) != hdrlen) 38 | hdrlen = encode_length(len + hdrlen - MIN_BLOCK_SIZE); 39 | 40 | return hdrlen; 41 | } 42 | 43 | /* Encoding can be read from front or back; 0 is invalid at either 44 | * start or end. Returns bytes used for header. */ 45 | static unsigned encode(unsigned long len, bool free, unsigned char arr[]) 46 | { 47 | unsigned int hdrlen = 1; 48 | 49 | /* We can never have a length < MIN_BLOCK_SIZE. */ 50 | assert(len >= MIN_BLOCK_SIZE); 51 | len -= MIN_BLOCK_SIZE; 52 | 53 | /* First byte always contains free bit. */ 54 | arr[0] = TERM_BIT | (free ? FREE_BIT : 0); 55 | /* Also holds 5 bits of data (0 - 31) */ 56 | arr[0] |= (len & 0x1F); 57 | len >>= 5; 58 | 59 | /* One byte only? */ 60 | if (!len) { 61 | arr[0] |= SINGLE_BYTE; 62 | return hdrlen; 63 | } 64 | 65 | /* Middle bytes. */ 66 | while (len >= (1 << 6)) { 67 | /* Next 7 data bits */ 68 | arr[hdrlen++] = (len & 0x7F); 69 | len >>= 7; 70 | } 71 | arr[hdrlen++] = (len | TERM_BIT); 72 | return hdrlen; 73 | } 74 | 75 | /* Returns bytes used for header. */ 76 | static unsigned decode(unsigned long *len, bool *free, const unsigned char *arr) 77 | { 78 | unsigned int hdrlen = 0, bits = 5; 79 | 80 | /* Free flag is in bit 5 */ 81 | *free = (arr[hdrlen] & FREE_BIT); 82 | /* Bottom five bits are data. */ 83 | *len = (arr[hdrlen] & 0x1f); 84 | if (!(arr[hdrlen++] & SINGLE_BYTE)) { 85 | /* Multi-byte encoding? */ 86 | while (!(arr[hdrlen] & TERM_BIT)) { 87 | /* 7 more data bits. */ 88 | *len |= (arr[hdrlen] & 0x7fUL) << bits; 89 | hdrlen++; 90 | bits += 7; 91 | } 92 | /* Final byte has 6 bits. */ 93 | *len |= (arr[hdrlen] & 0x3fUL) << bits; 94 | hdrlen++; 95 | } 96 | 97 | *len += MIN_BLOCK_SIZE; 98 | return hdrlen; 99 | } 100 | 101 | /* We keep a helper array for freed mem, one byte per k. */ 102 | static unsigned long free_array_size(unsigned long poolsize) 103 | { 104 | return poolsize / 1024; 105 | } 106 | 107 | /* We have series of 69 free sizes like so: 108 | * 1, 2, 3, 4. 6, 8, 10, 12, 14, 16. 20, 24, 28, 32... 252. 109 | */ 110 | static unsigned long free_array_off(unsigned long size) 111 | { 112 | unsigned long off; 113 | 114 | if (size <= 4) 115 | off = size - 1; 116 | else if (size <= 16) 117 | off = size / 2 + 1; 118 | else 119 | off = size / 4 + 5; 120 | 121 | off *= 3; 122 | return off; 123 | } 124 | 125 | void tiny_alloc_init(void *pool, unsigned long poolsize) 126 | { 127 | /* We start with free array, and then the rest is free. */ 128 | unsigned long arrsize = free_array_size(poolsize); 129 | 130 | /* Do nothing with 1 byte or less! */ 131 | if (poolsize < MIN_BLOCK_SIZE) 132 | return; 133 | 134 | memset(pool, 0, arrsize); 135 | encode(poolsize - arrsize, true, (unsigned char *)pool + arrsize); 136 | } 137 | 138 | /* Walk through and try to coalesce */ 139 | static bool try_coalesce(unsigned char *pool, unsigned long poolsize) 140 | { 141 | unsigned long len, prev_off = 0, prev_len = 0, off; 142 | bool free, prev_free = false, coalesced = false; 143 | 144 | off = free_array_size(poolsize); 145 | do { 146 | decode(&len, &free, pool + off); 147 | if (free && prev_free) { 148 | prev_len += len; 149 | encode(prev_len, true, pool + prev_off); 150 | coalesced = true; 151 | } else { 152 | prev_free = free; 153 | prev_off = off; 154 | prev_len = len; 155 | } 156 | off += len; 157 | } while (off < poolsize); 158 | 159 | /* Clear the free array. */ 160 | if (coalesced) 161 | memset(pool, 0, free_array_size(poolsize)); 162 | 163 | return coalesced; 164 | } 165 | 166 | static bool long_enough(unsigned long offset, unsigned long len, 167 | unsigned long size, unsigned long align) 168 | { 169 | unsigned long end = offset + len; 170 | 171 | offset += encode_len_with_header(len); 172 | offset = align_up(offset, align); 173 | return offset + size <= end; 174 | } 175 | 176 | static void add_to_free_array(unsigned char *arr, 177 | unsigned long poolsize, 178 | unsigned long size, 179 | unsigned long off) 180 | { 181 | unsigned long fa_off; 182 | 183 | if (size >= MAX_FREE_CACHED_SIZE) 184 | return; 185 | 186 | for (fa_off = free_array_off(size); 187 | fa_off + 3 < free_array_size(poolsize); 188 | fa_off += free_array_off(MAX_FREE_CACHED_SIZE)) { 189 | if (!arr[fa_off] && !arr[fa_off+1] && !arr[fa_off+2]) { 190 | arr[fa_off] = (off >> 16); 191 | arr[fa_off+1] = (off >> 8); 192 | arr[fa_off+2] = off; 193 | break; 194 | } 195 | } 196 | } 197 | 198 | void *tiny_alloc_get(void *pool, unsigned long poolsize, 199 | unsigned long size, unsigned long align) 200 | { 201 | unsigned long arrsize = free_array_size(poolsize); 202 | unsigned long len, off, actual, hdr, free_bucket; 203 | long fa_off; 204 | unsigned char *arr = pool; 205 | bool free, coalesced = false; 206 | 207 | /* We can't do anything with tiny pools. */ 208 | if (poolsize < MIN_BLOCK_SIZE) 209 | return NULL; 210 | 211 | /* We don't do zero-allocs; allows 1 more offset in encoding. */ 212 | if (!size) 213 | size = 1; 214 | 215 | /* Look for entries in free array, starting from right size up. */ 216 | for (free_bucket = free_array_off(size); 217 | free_bucket < free_array_off(MAX_FREE_CACHED_SIZE); 218 | free_bucket += 3) { 219 | for (fa_off = free_bucket; 220 | fa_off + 3 < free_array_size(poolsize); 221 | fa_off += free_array_off(MAX_FREE_CACHED_SIZE)) { 222 | off = ((unsigned long)arr[fa_off]) << 16 223 | | ((unsigned long)arr[fa_off+1]) << 8 224 | | ((unsigned long)arr[fa_off+2]); 225 | if (!off) 226 | continue; 227 | 228 | decode(&len, &free, arr + off); 229 | if (long_enough(off, len, size, align)) { 230 | /* Remove it. */ 231 | memset(&arr[fa_off], 0, 3); 232 | goto found; 233 | } 234 | } 235 | } 236 | 237 | again: 238 | off = arrsize; 239 | 240 | decode(&len, &free, arr + off); 241 | while (!free || !long_enough(off, len, size, align)) { 242 | /* Refill free array as we go. */ 243 | if (free && coalesced) 244 | add_to_free_array(arr, poolsize, len, off); 245 | 246 | off += len; 247 | /* Hit end? */ 248 | if (off == poolsize) { 249 | if (!coalesced && try_coalesce(pool, poolsize)) { 250 | coalesced = true; 251 | goto again; 252 | } 253 | return NULL; 254 | } 255 | decode(&len, &free, arr + off); 256 | } 257 | 258 | found: 259 | /* We have a free block. Since we walk from front, take far end. */ 260 | actual = ((off + len - size) & ~(align - 1)); 261 | hdr = actual - encode_len_with_header(off + len - actual); 262 | 263 | 264 | /* Do we have enough room to split? */ 265 | if (hdr - off >= MIN_BLOCK_SIZE) { 266 | encode(hdr - off, true, arr + off); 267 | add_to_free_array(arr, poolsize, hdr - off, off); 268 | } else { 269 | hdr = off; 270 | } 271 | 272 | /* Make sure that we are all-zero up to actual, so we can walk back 273 | * and find header. */ 274 | memset(arr + hdr, 0, actual - hdr); 275 | 276 | /* Create header for allocated block. */ 277 | encode(off + len - hdr, false, arr + hdr); 278 | 279 | return arr + actual; 280 | } 281 | 282 | static unsigned char *to_hdr(void *p) 283 | { 284 | unsigned char *hdr = p; 285 | 286 | /* Walk back to find end of header. */ 287 | while (!*(--hdr)); 288 | assert(*hdr & TERM_BIT); 289 | 290 | /* Now walk back to find start of header. */ 291 | if (!(*hdr & SINGLE_BYTE)) { 292 | while (!(*(--hdr) & TERM_BIT)); 293 | } 294 | return hdr; 295 | } 296 | 297 | void tiny_alloc_free(void *pool, unsigned long poolsize, void *freep) 298 | { 299 | unsigned long len; 300 | unsigned char *arr = pool; 301 | unsigned char *hdr; 302 | bool free; 303 | 304 | /* Too small to do anything. */ 305 | if (poolsize < MIN_BLOCK_SIZE) 306 | return; 307 | 308 | hdr = to_hdr(freep); 309 | 310 | decode(&len, &free, hdr); 311 | assert(!free); 312 | hdr[0] |= FREE_BIT; 313 | 314 | /* If an empty slot, put this in free array. */ 315 | add_to_free_array(pool, poolsize, len, hdr - arr); 316 | } 317 | 318 | unsigned long tiny_alloc_size(void *pool, unsigned long poolsize, void *p) 319 | { 320 | unsigned char *hdr = to_hdr(p); 321 | unsigned long len, hdrlen; 322 | bool free; 323 | 324 | hdrlen = decode(&len, &free, hdr); 325 | return len - hdrlen; 326 | } 327 | 328 | /* Useful for gdb breakpoints. */ 329 | static bool tiny_check_fail(void) 330 | { 331 | return false; 332 | } 333 | 334 | static bool check_decode(const unsigned char *arr, unsigned long len) 335 | { 336 | unsigned int i; 337 | 338 | if (len == 0) 339 | return tiny_check_fail(); 340 | if (!(arr[0] & TERM_BIT)) 341 | return tiny_check_fail(); 342 | if (arr[0] & SINGLE_BYTE) 343 | return true; 344 | for (i = 1; i < len; i++) { 345 | if (arr[i] & TERM_BIT) 346 | return true; 347 | } 348 | return tiny_check_fail(); 349 | } 350 | 351 | bool tiny_alloc_check(void *pool, unsigned long poolsize) 352 | { 353 | unsigned long arrsize = free_array_size(poolsize); 354 | unsigned char *arr = pool; 355 | unsigned long len, off, hdrlen; 356 | unsigned long i, freearr[arrsize], num_freearr = 0; 357 | bool free; 358 | 359 | if (poolsize < MIN_BLOCK_SIZE) 360 | return true; 361 | 362 | for (i = 0; i + 3 < free_array_size(poolsize); i += 3) { 363 | off = ((unsigned long)arr[i]) << 16 364 | | ((unsigned long)arr[i+1]) << 8 365 | | ((unsigned long)arr[i+2]); 366 | if (!off) 367 | continue; 368 | 369 | if (off >= poolsize) 370 | return tiny_check_fail(); 371 | freearr[num_freearr++] = off; 372 | } 373 | 374 | for (off = arrsize; off < poolsize; off += len) { 375 | /* We should have a valid header. */ 376 | if (!check_decode(arr + off, poolsize - off)) 377 | return false; 378 | hdrlen = decode(&len, &free, arr + off); 379 | if (off + len > poolsize) 380 | return tiny_check_fail(); 381 | if (hdrlen != encode_length(len - MIN_BLOCK_SIZE)) 382 | return tiny_check_fail(); 383 | for (i = 0; i < num_freearr; i++) { 384 | if (freearr[i] == off) { 385 | if (!free) 386 | return tiny_check_fail(); 387 | memmove(&freearr[i], &freearr[i+1], 388 | (num_freearr-- - (i + 1)) 389 | * sizeof(freearr[i])); 390 | break; 391 | } 392 | } 393 | } 394 | 395 | /* Now we should have found everything in freearr. */ 396 | if (num_freearr) 397 | return tiny_check_fail(); 398 | 399 | /* Now check that sizes are correct. */ 400 | for (i = 0; i + 3 < free_array_size(poolsize); i += 3) { 401 | unsigned long fa_off; 402 | 403 | off = ((unsigned long)arr[i]) << 16 404 | | ((unsigned long)arr[i+1]) << 8 405 | | ((unsigned long)arr[i+2]); 406 | if (!off) 407 | continue; 408 | 409 | decode(&len, &free, arr + off); 410 | 411 | /* Would we expect to find this length in this bucket? */ 412 | if (len >= MAX_FREE_CACHED_SIZE) 413 | return tiny_check_fail(); 414 | 415 | for (fa_off = free_array_off(len); 416 | fa_off + 3 < free_array_size(poolsize); 417 | fa_off += free_array_off(MAX_FREE_CACHED_SIZE)) { 418 | if (fa_off == i) 419 | break; 420 | } 421 | if (fa_off != i) 422 | return tiny_check_fail(); 423 | } 424 | 425 | return true; 426 | } 427 | 428 | /* FIXME: Implement. */ 429 | void tiny_alloc_visualize(FILE *out, void *pool, unsigned long poolsize) 430 | { 431 | } 432 | -------------------------------------------------------------------------------- /buffer/ccan/antithread/alloc/tiny.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #ifndef CCAN_TINY_H 3 | #define CCAN_TINY_H 4 | #include 5 | #include 6 | 7 | void tiny_alloc_init(void *pool, unsigned long poolsize); 8 | void *tiny_alloc_get(void *pool, unsigned long poolsize, 9 | unsigned long size, unsigned long align); 10 | void tiny_alloc_free(void *pool, unsigned long poolsize, void *free); 11 | unsigned long tiny_alloc_size(void *pool, unsigned long poolsize, void *p); 12 | bool tiny_alloc_check(void *pool, unsigned long poolsize); 13 | void tiny_alloc_visualize(FILE *out, void *pool, unsigned long poolsize); 14 | 15 | #endif /* CCAN_TINY_H */ 16 | -------------------------------------------------------------------------------- /buffer/ccan/build_assert/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * build_assert - routines for build-time assertions 7 | * 8 | * This code provides routines which will cause compilation to fail should some 9 | * assertion be untrue: such failures are preferable to run-time assertions, 10 | * but much more limited since they can only depends on compile-time constants. 11 | * 12 | * These assertions are most useful when two parts of the code must be kept in 13 | * sync: it is better to avoid such cases if possible, but seconds best is to 14 | * detect invalid changes at build time. 15 | * 16 | * For example, a tricky piece of code might rely on a certain element being at 17 | * the start of the structure. To ensure that future changes don't break it, 18 | * you would catch such changes in your code like so: 19 | * 20 | * Example: 21 | * #include 22 | * #include 23 | * 24 | * struct foo { 25 | * char string[5]; 26 | * int x; 27 | * }; 28 | * 29 | * static char *foo_string(struct foo *foo) 30 | * { 31 | * // This trick requires that the string be first in the structure 32 | * BUILD_ASSERT(offsetof(struct foo, string) == 0); 33 | * return (char *)foo; 34 | * } 35 | * 36 | * License: CC0 (Public domain) 37 | * Author: Rusty Russell 38 | */ 39 | int main(int argc, char *argv[]) 40 | { 41 | if (argc != 2) 42 | return 1; 43 | 44 | if (strcmp(argv[1], "depends") == 0) 45 | /* Nothing. */ 46 | return 0; 47 | 48 | return 1; 49 | } 50 | -------------------------------------------------------------------------------- /buffer/ccan/build_assert/build_assert.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_BUILD_ASSERT_H 3 | #define CCAN_BUILD_ASSERT_H 4 | 5 | /** 6 | * BUILD_ASSERT - assert a build-time dependency. 7 | * @cond: the compile-time condition which must be true. 8 | * 9 | * Your compile will fail if the condition isn't true, or can't be evaluated 10 | * by the compiler. This can only be used within a function. 11 | * 12 | * Example: 13 | * #include 14 | * ... 15 | * static char *foo_to_char(struct foo *foo) 16 | * { 17 | * // This code needs string to be at start of foo. 18 | * BUILD_ASSERT(offsetof(struct foo, string) == 0); 19 | * return (char *)foo; 20 | * } 21 | */ 22 | #define BUILD_ASSERT(cond) \ 23 | do { (void) sizeof(char [1 - 2*!(cond)]); } while(0) 24 | 25 | /** 26 | * BUILD_ASSERT_OR_ZERO - assert a build-time dependency, as an expression. 27 | * @cond: the compile-time condition which must be true. 28 | * 29 | * Your compile will fail if the condition isn't true, or can't be evaluated 30 | * by the compiler. This can be used in an expression: its value is "0". 31 | * 32 | * Example: 33 | * #define foo_to_char(foo) \ 34 | * ((char *)(foo) \ 35 | * + BUILD_ASSERT_OR_ZERO(offsetof(struct foo, string) == 0)) 36 | */ 37 | #define BUILD_ASSERT_OR_ZERO(cond) \ 38 | (sizeof(char [1 - 2*!(cond)]) - 1) 39 | 40 | #endif /* CCAN_BUILD_ASSERT_H */ 41 | -------------------------------------------------------------------------------- /buffer/ccan/compiler/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * compiler - macros for common compiler extensions 7 | * 8 | * Abstracts away some compiler hints. Currently these include: 9 | * - COLD 10 | * For functions not called in fast paths (aka. cold functions) 11 | * - PRINTF_FMT 12 | * For functions which take printf-style parameters. 13 | * - CONST_FUNCTION 14 | * For functions which return the same value for same parameters. 15 | * - NEEDED 16 | * For functions and variables which must be emitted even if unused. 17 | * - UNNEEDED 18 | * For functions and variables which need not be emitted if unused. 19 | * - UNUSED 20 | * For parameters which are not used. 21 | * - IS_COMPILE_CONSTANT() 22 | * For using different tradeoffs for compiletime vs runtime evaluation. 23 | * 24 | * License: CC0 (Public domain) 25 | * Author: Rusty Russell 26 | * 27 | * Example: 28 | * #include 29 | * #include 30 | * #include 31 | * 32 | * // Example of a (slow-path) logging function. 33 | * static int log_threshold = 2; 34 | * static void COLD PRINTF_FMT(2,3) 35 | * logger(int level, const char *fmt, ...) 36 | * { 37 | * va_list ap; 38 | * va_start(ap, fmt); 39 | * if (level >= log_threshold) 40 | * vfprintf(stderr, fmt, ap); 41 | * va_end(ap); 42 | * } 43 | * 44 | * int main(int argc, char *argv[]) 45 | * { 46 | * if (argc != 1) { 47 | * logger(3, "Don't want %i arguments!\n", argc-1); 48 | * return 1; 49 | * } 50 | * return 0; 51 | * } 52 | */ 53 | int main(int argc, char *argv[]) 54 | { 55 | /* Expect exactly one argument */ 56 | if (argc != 2) 57 | return 1; 58 | 59 | if (strcmp(argv[1], "depends") == 0) { 60 | return 0; 61 | } 62 | 63 | return 1; 64 | } 65 | -------------------------------------------------------------------------------- /buffer/ccan/compiler/compiler.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_COMPILER_H 3 | #define CCAN_COMPILER_H 4 | #include "config.h" 5 | 6 | #ifndef COLD 7 | #if HAVE_ATTRIBUTE_COLD 8 | /** 9 | * COLD - a function is unlikely to be called. 10 | * 11 | * Used to mark an unlikely code path and optimize appropriately. 12 | * It is usually used on logging or error routines. 13 | * 14 | * Example: 15 | * static void COLD moan(const char *reason) 16 | * { 17 | * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); 18 | * } 19 | */ 20 | #define COLD __attribute__((cold)) 21 | #else 22 | #define COLD 23 | #endif 24 | #endif 25 | 26 | #ifndef NORETURN 27 | #if HAVE_ATTRIBUTE_NORETURN 28 | /** 29 | * NORETURN - a function does not return 30 | * 31 | * Used to mark a function which exits; useful for suppressing warnings. 32 | * 33 | * Example: 34 | * static void NORETURN fail(const char *reason) 35 | * { 36 | * fprintf(stderr, "Error: %s (%s)\n", reason, strerror(errno)); 37 | * exit(1); 38 | * } 39 | */ 40 | #define NORETURN __attribute__((noreturn)) 41 | #else 42 | #define NORETURN 43 | #endif 44 | #endif 45 | 46 | #ifndef PRINTF_FMT 47 | #if HAVE_ATTRIBUTE_PRINTF 48 | /** 49 | * PRINTF_FMT - a function takes printf-style arguments 50 | * @nfmt: the 1-based number of the function's format argument. 51 | * @narg: the 1-based number of the function's first variable argument. 52 | * 53 | * This allows the compiler to check your parameters as it does for printf(). 54 | * 55 | * Example: 56 | * void PRINTF_FMT(2,3) my_printf(const char *prefix, const char *fmt, ...); 57 | */ 58 | #define PRINTF_FMT(nfmt, narg) \ 59 | __attribute__((format(__printf__, nfmt, narg))) 60 | #else 61 | #define PRINTF_FMT(nfmt, narg) 62 | #endif 63 | #endif 64 | 65 | #ifndef CONST_FUNCTION 66 | #if HAVE_ATTRIBUTE_CONST 67 | /** 68 | * CONST_FUNCTION - a function's return depends only on its argument 69 | * 70 | * This allows the compiler to assume that the function will return the exact 71 | * same value for the exact same arguments. This implies that the function 72 | * must not use global variables, or dereference pointer arguments. 73 | */ 74 | #define CONST_FUNCTION __attribute__((const)) 75 | #else 76 | #define CONST_FUNCTION 77 | #endif 78 | #endif 79 | 80 | #if HAVE_ATTRIBUTE_UNUSED 81 | #ifndef UNNEEDED 82 | /** 83 | * UNNEEDED - a variable/function may not be needed 84 | * 85 | * This suppresses warnings about unused variables or functions, but tells 86 | * the compiler that if it is unused it need not emit it into the source code. 87 | * 88 | * Example: 89 | * // With some preprocessor options, this is unnecessary. 90 | * static UNNEEDED int counter; 91 | * 92 | * // With some preprocessor options, this is unnecessary. 93 | * static UNNEEDED void add_to_counter(int add) 94 | * { 95 | * counter += add; 96 | * } 97 | */ 98 | #define UNNEEDED __attribute__((unused)) 99 | #endif 100 | 101 | #ifndef NEEDED 102 | #if HAVE_ATTRIBUTE_USED 103 | /** 104 | * NEEDED - a variable/function is needed 105 | * 106 | * This suppresses warnings about unused variables or functions, but tells 107 | * the compiler that it must exist even if it (seems) unused. 108 | * 109 | * Example: 110 | * // Even if this is unused, these are vital for debugging. 111 | * static NEEDED int counter; 112 | * static NEEDED void dump_counter(void) 113 | * { 114 | * printf("Counter is %i\n", counter); 115 | * } 116 | */ 117 | #define NEEDED __attribute__((used)) 118 | #else 119 | /* Before used, unused functions and vars were always emitted. */ 120 | #define NEEDED __attribute__((unused)) 121 | #endif 122 | #endif 123 | 124 | #ifndef UNUSED 125 | /** 126 | * UNUSED - a parameter is unused 127 | * 128 | * Some compilers (eg. gcc with -W or -Wunused) warn about unused 129 | * function parameters. This suppresses such warnings and indicates 130 | * to the reader that it's deliberate. 131 | * 132 | * Example: 133 | * // This is used as a callback, so needs to have this prototype. 134 | * static int some_callback(void *unused UNUSED) 135 | * { 136 | * return 0; 137 | * } 138 | */ 139 | #define UNUSED __attribute__((unused)) 140 | #endif 141 | #else 142 | #ifndef UNNEEDED 143 | #define UNNEEDED 144 | #endif 145 | #ifndef NEEDED 146 | #define NEEDED 147 | #endif 148 | #ifndef UNUSED 149 | #define UNUSED 150 | #endif 151 | #endif 152 | 153 | #ifndef IS_COMPILE_CONSTANT 154 | #if HAVE_BUILTIN_CONSTANT_P 155 | /** 156 | * IS_COMPILE_CONSTANT - does the compiler know the value of this expression? 157 | * @expr: the expression to evaluate 158 | * 159 | * When an expression manipulation is complicated, it is usually better to 160 | * implement it in a function. However, if the expression being manipulated is 161 | * known at compile time, it is better to have the compiler see the entire 162 | * expression so it can simply substitute the result. 163 | * 164 | * This can be done using the IS_COMPILE_CONSTANT() macro. 165 | * 166 | * Example: 167 | * enum greek { ALPHA, BETA, GAMMA, DELTA, EPSILON }; 168 | * 169 | * // Out-of-line version. 170 | * const char *greek_name(enum greek greek); 171 | * 172 | * // Inline version. 173 | * static inline const char *_greek_name(enum greek greek) 174 | * { 175 | * switch (greek) { 176 | * case ALPHA: return "alpha"; 177 | * case BETA: return "beta"; 178 | * case GAMMA: return "gamma"; 179 | * case DELTA: return "delta"; 180 | * case EPSILON: return "epsilon"; 181 | * default: return "**INVALID**"; 182 | * } 183 | * } 184 | * 185 | * // Use inline if compiler knows answer. Otherwise call function 186 | * // to avoid copies of the same code everywhere. 187 | * #define greek_name(g) \ 188 | * (IS_COMPILE_CONSTANT(greek) ? _greek_name(g) : greek_name(g)) 189 | */ 190 | #define IS_COMPILE_CONSTANT(expr) __builtin_constant_p(expr) 191 | #else 192 | /* If we don't know, assume it's not. */ 193 | #define IS_COMPILE_CONSTANT(expr) 0 194 | #endif 195 | #endif 196 | 197 | #ifndef WARN_UNUSED_RESULT 198 | #if HAVE_WARN_UNUSED_RESULT 199 | /** 200 | * WARN_UNUSED_RESULT - warn if a function return value is unused. 201 | * 202 | * Used to mark a function where it is extremely unlikely that the caller 203 | * can ignore the result, eg realloc(). 204 | * 205 | * Example: 206 | * // buf param may be freed by this; need return value! 207 | * static char *WARN_UNUSED_RESULT enlarge(char *buf, unsigned *size) 208 | * { 209 | * return realloc(buf, (*size) *= 2); 210 | * } 211 | */ 212 | #define WARN_UNUSED_RESULT __attribute__((warn_unused_result)) 213 | #else 214 | #define WARN_UNUSED_RESULT 215 | #endif 216 | #endif 217 | #endif /* CCAN_COMPILER_H */ 218 | -------------------------------------------------------------------------------- /buffer/ccan/ilog/_info: -------------------------------------------------------------------------------- 1 | /** 2 | * ilog - Integer logarithm. 3 | * 4 | * ilog_32() and ilog_64() compute the minimum number of bits required to store 5 | * an unsigned 32-bit or 64-bit value without any leading zero bits. 6 | * This can also be thought of as the location of the highest set bit, with 7 | * counting starting from one (so that 0 returns 0, 1 returns 1, and 2**31 8 | * returns 32). 9 | * When the value is known to be non-zero ilog32_nz() and ilog64_nz() can 10 | * compile into as few as two instructions, one of which may get optimized out 11 | * later. 12 | * STATIC_ILOG_32 and STATIC_ILOG_64 allow computation on compile-time 13 | * constants, so other compile-time constants can be derived from them. 14 | * 15 | * Example: 16 | * #include 17 | * #include 18 | * #include 19 | * 20 | * int main(void){ 21 | * int i; 22 | * printf("ilog32(0x%08X)=%i\n",0,ilog32(0)); 23 | * for(i=1;i<=STATIC_ILOG_32(USHRT_MAX);i++){ 24 | * uint32_t v; 25 | * v=(uint32_t)1U<<(i-1); 26 | * //Here we know v is non-zero, so we can use ilog32_nz(). 27 | * printf("ilog32(0x%08X)=%i\n",v,ilog32_nz(v)); 28 | * } 29 | * return 0; 30 | * } 31 | * 32 | * License: LGPL (v2.1 or any later version) 33 | * Author: Timothy B. Terriberry 34 | */ 35 | #include 36 | #include 37 | #include "config.h" 38 | 39 | int main(int _argc,const char *_argv[]){ 40 | /*Expect exactly one argument.*/ 41 | if(_argc!=2)return 1; 42 | if(strcmp(_argv[1],"depends")==0){ 43 | printf("ccan/compiler\n"); 44 | return 0; 45 | } 46 | return 1; 47 | } 48 | -------------------------------------------------------------------------------- /buffer/ccan/ilog/ilog.c: -------------------------------------------------------------------------------- 1 | /*(C) Timothy B. Terriberry (tterribe@xiph.org) 2001-2009 LGPL (v2 or later). 2 | * See LICENSE file for details. */ 3 | #include "ilog.h" 4 | #include 5 | 6 | /*The fastest fallback strategy for platforms with fast multiplication appears 7 | to be based on de Bruijn sequences~\cite{LP98}. 8 | Tests confirmed this to be true even on an ARM11, where it is actually faster 9 | than using the native clz instruction. 10 | Define ILOG_NODEBRUIJN to use a simpler fallback on platforms where 11 | multiplication or table lookups are too expensive. 12 | 13 | @UNPUBLISHED{LP98, 14 | author="Charles E. Leiserson and Harald Prokop", 15 | title="Using de {Bruijn} Sequences to Index a 1 in a Computer Word", 16 | month=Jun, 17 | year=1998, 18 | note="\url{http://supertech.csail.mit.edu/papers/debruijn.pdf}" 19 | }*/ 20 | static UNNEEDED const unsigned char DEBRUIJN_IDX32[32]={ 21 | 0, 1,28, 2,29,14,24, 3,30,22,20,15,25,17, 4, 8, 22 | 31,27,13,23,21,19,16, 7,26,12,18, 6,11, 5,10, 9 23 | }; 24 | 25 | /* We always compile these in, in case someone takes address of function. */ 26 | #undef ilog32_nz 27 | #undef ilog32 28 | #undef ilog64_nz 29 | #undef ilog64 30 | 31 | int ilog32(uint32_t _v){ 32 | /*On a Pentium M, this branchless version tested as the fastest version without 33 | multiplications on 1,000,000,000 random 32-bit integers, edging out a 34 | similar version with branches, and a 256-entry LUT version.*/ 35 | # if defined(ILOG_NODEBRUIJN) 36 | int ret; 37 | int m; 38 | ret=_v>0; 39 | m=(_v>0xFFFFU)<<4; 40 | _v>>=m; 41 | ret|=m; 42 | m=(_v>0xFFU)<<3; 43 | _v>>=m; 44 | ret|=m; 45 | m=(_v>0xFU)<<2; 46 | _v>>=m; 47 | ret|=m; 48 | m=(_v>3)<<1; 49 | _v>>=m; 50 | ret|=m; 51 | ret+=_v>1; 52 | return ret; 53 | /*This de Bruijn sequence version is faster if you have a fast multiplier.*/ 54 | # else 55 | int ret; 56 | ret=_v>0; 57 | _v|=_v>>1; 58 | _v|=_v>>2; 59 | _v|=_v>>4; 60 | _v|=_v>>8; 61 | _v|=_v>>16; 62 | _v=(_v>>1)+1; 63 | ret+=DEBRUIJN_IDX32[_v*0x77CB531U>>27&0x1F]; 64 | return ret; 65 | # endif 66 | } 67 | 68 | int ilog32_nz(uint32_t _v) 69 | { 70 | return ilog32(_v); 71 | } 72 | 73 | int ilog64(uint64_t _v){ 74 | # if defined(ILOG_NODEBRUIJN) 75 | uint32_t v; 76 | int ret; 77 | int m; 78 | ret=_v>0; 79 | m=(_v>0xFFFFFFFFU)<<5; 80 | v=(uint32_t)(_v>>m); 81 | ret|=m; 82 | m=(v>0xFFFFU)<<4; 83 | v>>=m; 84 | ret|=m; 85 | m=(v>0xFFU)<<3; 86 | v>>=m; 87 | ret|=m; 88 | m=(v>0xFU)<<2; 89 | v>>=m; 90 | ret|=m; 91 | m=(v>3)<<1; 92 | v>>=m; 93 | ret|=m; 94 | ret+=v>1; 95 | return ret; 96 | # else 97 | /*If we don't have a 64-bit word, split it into two 32-bit halves.*/ 98 | # if LONG_MAX<9223372036854775807LL 99 | uint32_t v; 100 | int ret; 101 | int m; 102 | ret=_v>0; 103 | m=(_v>0xFFFFFFFFU)<<5; 104 | v=(uint32_t)(_v>>m); 105 | ret|=m; 106 | v|=v>>1; 107 | v|=v>>2; 108 | v|=v>>4; 109 | v|=v>>8; 110 | v|=v>>16; 111 | v=(v>>1)+1; 112 | ret+=DEBRUIJN_IDX32[v*0x77CB531U>>27&0x1F]; 113 | return ret; 114 | /*Otherwise do it in one 64-bit operation.*/ 115 | # else 116 | static const unsigned char DEBRUIJN_IDX64[64]={ 117 | 0, 1, 2, 7, 3,13, 8,19, 4,25,14,28, 9,34,20,40, 118 | 5,17,26,38,15,46,29,48,10,31,35,54,21,50,41,57, 119 | 63, 6,12,18,24,27,33,39,16,37,45,47,30,53,49,56, 120 | 62,11,23,32,36,44,52,55,61,22,43,51,60,42,59,58 121 | }; 122 | int ret; 123 | ret=_v>0; 124 | _v|=_v>>1; 125 | _v|=_v>>2; 126 | _v|=_v>>4; 127 | _v|=_v>>8; 128 | _v|=_v>>16; 129 | _v|=_v>>32; 130 | _v=(_v>>1)+1; 131 | ret+=DEBRUIJN_IDX64[_v*0x218A392CD3D5DBF>>58&0x3F]; 132 | return ret; 133 | # endif 134 | # endif 135 | } 136 | 137 | int ilog64_nz(uint64_t _v) 138 | { 139 | return ilog64(_v); 140 | } 141 | 142 | -------------------------------------------------------------------------------- /buffer/ccan/ilog/ilog.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #if !defined(_ilog_H) 3 | # define _ilog_H (1) 4 | # include "config.h" 5 | # include 6 | # include 7 | # include 8 | 9 | /** 10 | * ilog32 - Integer binary logarithm of a 32-bit value. 11 | * @_v: A 32-bit value. 12 | * Returns floor(log2(_v))+1, or 0 if _v==0. 13 | * This is the number of bits that would be required to represent _v in two's 14 | * complement notation with all of the leading zeros stripped. 15 | * Note that many uses will resolve to the fast macro version instead. 16 | * 17 | * See Also: 18 | * ilog32_nz(), ilog64() 19 | * 20 | * Example: 21 | * // Rounds up to next power of 2 (if not a power of 2). 22 | * static uint32_t round_up32(uint32_t i) 23 | * { 24 | * assert(i != 0); 25 | * return 1U << ilog32(i-1); 26 | * } 27 | */ 28 | int ilog32(uint32_t _v) CONST_FUNCTION; 29 | 30 | /** 31 | * ilog32_nz - Integer binary logarithm of a non-zero 32-bit value. 32 | * @_v: A 32-bit value. 33 | * Returns floor(log2(_v))+1, or undefined if _v==0. 34 | * This is the number of bits that would be required to represent _v in two's 35 | * complement notation with all of the leading zeros stripped. 36 | * Note that many uses will resolve to the fast macro version instead. 37 | * See Also: 38 | * ilog32(), ilog64_nz() 39 | * Example: 40 | * // Find Last Set (ie. highest bit set, 0 to 31). 41 | * static uint32_t fls32(uint32_t i) 42 | * { 43 | * assert(i != 0); 44 | * return ilog32_nz(i) - 1; 45 | * } 46 | */ 47 | int ilog32_nz(uint32_t _v) CONST_FUNCTION; 48 | 49 | /** 50 | * ilog64 - Integer binary logarithm of a 64-bit value. 51 | * @_v: A 64-bit value. 52 | * Returns floor(log2(_v))+1, or 0 if _v==0. 53 | * This is the number of bits that would be required to represent _v in two's 54 | * complement notation with all of the leading zeros stripped. 55 | * Note that many uses will resolve to the fast macro version instead. 56 | * See Also: 57 | * ilog64_nz(), ilog32() 58 | */ 59 | int ilog64(uint64_t _v) CONST_FUNCTION; 60 | 61 | /** 62 | * ilog64_nz - Integer binary logarithm of a non-zero 64-bit value. 63 | * @_v: A 64-bit value. 64 | * Returns floor(log2(_v))+1, or undefined if _v==0. 65 | * This is the number of bits that would be required to represent _v in two's 66 | * complement notation with all of the leading zeros stripped. 67 | * Note that many uses will resolve to the fast macro version instead. 68 | * See Also: 69 | * ilog64(), ilog32_nz() 70 | */ 71 | int ilog64_nz(uint64_t _v) CONST_FUNCTION; 72 | 73 | /** 74 | * STATIC_ILOG_32 - The integer logarithm of an (unsigned, 32-bit) constant. 75 | * @_v: A non-negative 32-bit constant. 76 | * Returns floor(log2(_v))+1, or 0 if _v==0. 77 | * This is the number of bits that would be required to represent _v in two's 78 | * complement notation with all of the leading zeros stripped. 79 | * This macro should only be used when you need a compile-time constant, 80 | * otherwise ilog32 or ilog32_nz are just as fast and more flexible. 81 | * 82 | * Example: 83 | * #define MY_PAGE_SIZE 4096 84 | * #define MY_PAGE_BITS (STATIC_ILOG_32(PAGE_SIZE) - 1) 85 | */ 86 | #define STATIC_ILOG_32(_v) (STATIC_ILOG5((uint32_t)(_v))) 87 | 88 | /** 89 | * STATIC_ILOG_64 - The integer logarithm of an (unsigned, 64-bit) constant. 90 | * @_v: A non-negative 64-bit constant. 91 | * Returns floor(log2(_v))+1, or 0 if _v==0. 92 | * This is the number of bits that would be required to represent _v in two's 93 | * complement notation with all of the leading zeros stripped. 94 | * This macro should only be used when you need a compile-time constant, 95 | * otherwise ilog64 or ilog64_nz are just as fast and more flexible. 96 | */ 97 | #define STATIC_ILOG_64(_v) (STATIC_ILOG6((uint64_t)(_v))) 98 | 99 | /* Private implementation details */ 100 | 101 | /*Note the casts to (int) below: this prevents "upgrading" 102 | the type of an entire expression to an (unsigned) size_t.*/ 103 | #if INT_MAX>=2147483647 && HAVE_BUILTIN_CLZ 104 | #define builtin_ilog32_nz(v) \ 105 | (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v)) 106 | #elif LONG_MAX>=2147483647L && HAVE_BUILTIN_CLZL 107 | #define builtin_ilog32_nz(v) \ 108 | (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clzl(v)) 109 | #endif 110 | 111 | #if INT_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZ 112 | #define builtin_ilog64_nz(v) \ 113 | (((int)sizeof(unsigned)*CHAR_BIT) - __builtin_clz(v)) 114 | #elif LONG_MAX>=9223372036854775807LL && HAVE_BUILTIN_CLZL 115 | #define builtin_ilog64_nz(v) \ 116 | (((int)sizeof(unsigned long)*CHAR_BIT) - __builtin_clzl(v)) 117 | #elif HAVE_BUILTIN_CLZLL 118 | #define builtin_ilog64_nz(v) \ 119 | (((int)sizeof(unsigned long long)*CHAR_BIT) - __builtin_clzll(v)) 120 | #endif 121 | 122 | #ifdef builtin_ilog32_nz 123 | #define ilog32(_v) (builtin_ilog32_nz(_v)&-!!(_v)) 124 | #define ilog32_nz(_v) builtin_ilog32_nz(_v) 125 | #else 126 | #define ilog32_nz(_v) ilog32(_v) 127 | #define ilog32(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_32(_v) : ilog32(_v)) 128 | #endif /* builtin_ilog32_nz */ 129 | 130 | #ifdef builtin_ilog64_nz 131 | #define ilog64(_v) (builtin_ilog64_nz(_v)&-!!(_v)) 132 | #define ilog64_nz(_v) builtin_ilog64_nz(_v) 133 | #else 134 | #define ilog64_nz(_v) ilog64(_v) 135 | #define ilog64(_v) (IS_COMPILE_CONSTANT(_v) ? STATIC_ILOG_64(_v) : ilog64(_v)) 136 | #endif /* builtin_ilog64_nz */ 137 | 138 | /* Macros for evaluating compile-time constant ilog. */ 139 | # define STATIC_ILOG0(_v) (!!(_v)) 140 | # define STATIC_ILOG1(_v) (((_v)&0x2)?2:STATIC_ILOG0(_v)) 141 | # define STATIC_ILOG2(_v) (((_v)&0xC)?2+STATIC_ILOG1((_v)>>2):STATIC_ILOG1(_v)) 142 | # define STATIC_ILOG3(_v) \ 143 | (((_v)&0xF0)?4+STATIC_ILOG2((_v)>>4):STATIC_ILOG2(_v)) 144 | # define STATIC_ILOG4(_v) \ 145 | (((_v)&0xFF00)?8+STATIC_ILOG3((_v)>>8):STATIC_ILOG3(_v)) 146 | # define STATIC_ILOG5(_v) \ 147 | (((_v)&0xFFFF0000)?16+STATIC_ILOG4((_v)>>16):STATIC_ILOG4(_v)) 148 | # define STATIC_ILOG6(_v) \ 149 | (((_v)&0xFFFFFFFF00000000ULL)?32+STATIC_ILOG5((_v)>>32):STATIC_ILOG5(_v)) 150 | 151 | #endif /* _ilog_H */ 152 | -------------------------------------------------------------------------------- /buffer/ccan/short_types/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * short_types - shorter names for standard integer types 7 | * 8 | * "C is a Spartan language, and so should your naming be." 9 | * -- Linus Torvalds 10 | * 11 | * The short_types header provides for convenient abbreviations for the 12 | * posixly-damned uint32_t types. It also provides be32/le32 for explicitly 13 | * annotating types of specific endian. 14 | * 15 | * Include this header, if only to stop people using these identifiers 16 | * for other things! 17 | * 18 | * Example: 19 | * #include 20 | * #include 21 | * #include 22 | * #include 23 | * 24 | * // Print nonsensical numerical comparison of POSIX vs. short_types. 25 | * #define stringify_1(x) #x 26 | * #define stringify(x) stringify_1(x) 27 | * 28 | * static void evaluate(size_t size, const char *posix, const char *sht, 29 | * unsigned int *posix_total, unsigned int *sht_total, 30 | * unsigned int *size_total) 31 | * { 32 | * printf("\t%ssigned %s: POSIX %zu%%, short %zu%%\n", 33 | * sht[0] == 'u' ? "un" : "", 34 | * sht+1, 35 | * strlen(posix)*100 / size, 36 | * strlen(sht)*100 / size); 37 | * *posix_total += strlen(posix); 38 | * *sht_total += strlen(sht); 39 | * *size_total += size; 40 | * } 41 | * 42 | * #define EVALUATE(psx, short, pt, st, t) \ 43 | * evaluate(sizeof(psx), stringify(psx), stringify(sht), pt, st, t) 44 | * 45 | * int main(void) 46 | * { 47 | * unsigned int posix_total = 0, sht_total = 0, size_total = 0; 48 | * 49 | * printf("Comparing size of type vs size of name:\n"); 50 | * 51 | * EVALUATE(uint8_t, u8, &posix_total, &sht_total, &size_total); 52 | * EVALUATE(int8_t, s8, &posix_total, &sht_total, &size_total); 53 | * EVALUATE(uint16_t, u16, &posix_total, &sht_total, &size_total); 54 | * EVALUATE(int16_t, s16, &posix_total, &sht_total, &size_total); 55 | * EVALUATE(uint32_t, u32, &posix_total, &sht_total, &size_total); 56 | * EVALUATE(int32_t, s32, &posix_total, &sht_total, &size_total); 57 | * EVALUATE(uint64_t, u64, &posix_total, &sht_total, &size_total); 58 | * EVALUATE(int64_t, s64, &posix_total, &sht_total, &size_total); 59 | * 60 | * printf("Conclusion:\n" 61 | * "\tPOSIX is %u%% LESS efficient than binary.\n" 62 | * "\tshort_types.h is %u%% MORE efficient than binary.\n", 63 | * (posix_total - size_total) * 100 / size_total, 64 | * (size_total - sht_total) * 100 / size_total); 65 | * return 0; 66 | * } 67 | * 68 | * License: CC0 (Public domain) 69 | * Author: Rusty Russell 70 | */ 71 | int main(int argc, char *argv[]) 72 | { 73 | if (argc != 2) 74 | return 1; 75 | 76 | if (strcmp(argv[1], "depends") == 0) { 77 | return 0; 78 | } 79 | 80 | return 1; 81 | } 82 | -------------------------------------------------------------------------------- /buffer/ccan/short_types/short_types.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_SHORT_TYPES_H 3 | #define CCAN_SHORT_TYPES_H 4 | #include 5 | 6 | /** 7 | * u64/s64/u32/s32/u16/s16/u8/s8 - short names for explicitly-sized types. 8 | */ 9 | typedef uint64_t u64; 10 | typedef int64_t s64; 11 | typedef uint32_t u32; 12 | typedef int32_t s32; 13 | typedef uint16_t u16; 14 | typedef int16_t s16; 15 | typedef uint8_t u8; 16 | typedef int8_t s8; 17 | 18 | /** 19 | * be64/be32/be16 - 64/32/16 bit big-endian representation. 20 | */ 21 | typedef uint64_t be64; 22 | typedef uint32_t be32; 23 | typedef uint16_t be16; 24 | 25 | /** 26 | * le64/le32/le16 - 64/32/16 bit little-endian representation. 27 | */ 28 | typedef uint64_t le64; 29 | typedef uint32_t le32; 30 | typedef uint16_t le16; 31 | 32 | #endif /* CCAN_SHORT_TYPES_H */ 33 | -------------------------------------------------------------------------------- /buffer/ccan/str/_info: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include "config.h" 4 | 5 | /** 6 | * str - string helper routines 7 | * 8 | * This is a grab bag of functions for string operations, designed to enhance 9 | * the standard string.h. 10 | * 11 | * Note that if you define CCAN_STR_DEBUG, you will get extra compile 12 | * checks on common misuses of the following functions (they will now 13 | * be out-of-line, so there is a runtime penalty!). 14 | * 15 | * strstr, strchr, strrchr: 16 | * Return const char * if first argument is const (gcc only). 17 | * 18 | * isalnum, isalpha, isascii, isblank, iscntrl, isdigit, isgraph, 19 | * islower, isprint, ispunct, isspace, isupper, isxdigit: 20 | * Static and runtime check that input is EOF or an *unsigned* 21 | * char, as per C standard (really!). 22 | * 23 | * Example: 24 | * #include 25 | * #include 26 | * 27 | * int main(int argc, char *argv[]) 28 | * { 29 | * if (argv[1] && streq(argv[1], "--verbose")) 30 | * printf("verbose set\n"); 31 | * if (argv[1] && strstarts(argv[1], "--")) 32 | * printf("Some option set\n"); 33 | * if (argv[1] && strends(argv[1], "cow-powers")) 34 | * printf("Magic option set\n"); 35 | * return 0; 36 | * } 37 | * 38 | * License: CC0 (Public domain) 39 | * Author: Rusty Russell 40 | */ 41 | int main(int argc, char *argv[]) 42 | { 43 | if (argc != 2) 44 | return 1; 45 | 46 | if (strcmp(argv[1], "depends") == 0) { 47 | printf("ccan/build_assert\n"); 48 | return 0; 49 | } 50 | 51 | return 1; 52 | } 53 | -------------------------------------------------------------------------------- /buffer/ccan/str/debug.c: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #include "config.h" 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #ifdef CCAN_STR_DEBUG 9 | /* Because we mug the real ones with macros, we need our own wrappers. */ 10 | int str_isalnum(int i) 11 | { 12 | assert(i >= -1 && i < 256); 13 | return isalnum(i); 14 | } 15 | 16 | int str_isalpha(int i) 17 | { 18 | assert(i >= -1 && i < 256); 19 | return isalpha(i); 20 | } 21 | 22 | int str_isascii(int i) 23 | { 24 | assert(i >= -1 && i < 256); 25 | return isascii(i); 26 | } 27 | 28 | #if HAVE_ISBLANK 29 | int str_isblank(int i) 30 | { 31 | assert(i >= -1 && i < 256); 32 | return isblank(i); 33 | } 34 | #endif 35 | 36 | int str_iscntrl(int i) 37 | { 38 | assert(i >= -1 && i < 256); 39 | return iscntrl(i); 40 | } 41 | 42 | int str_isdigit(int i) 43 | { 44 | assert(i >= -1 && i < 256); 45 | return isdigit(i); 46 | } 47 | 48 | int str_isgraph(int i) 49 | { 50 | assert(i >= -1 && i < 256); 51 | return isgraph(i); 52 | } 53 | 54 | int str_islower(int i) 55 | { 56 | assert(i >= -1 && i < 256); 57 | return islower(i); 58 | } 59 | 60 | int str_isprint(int i) 61 | { 62 | assert(i >= -1 && i < 256); 63 | return isprint(i); 64 | } 65 | 66 | int str_ispunct(int i) 67 | { 68 | assert(i >= -1 && i < 256); 69 | return ispunct(i); 70 | } 71 | 72 | int str_isspace(int i) 73 | { 74 | assert(i >= -1 && i < 256); 75 | return isspace(i); 76 | } 77 | 78 | int str_isupper(int i) 79 | { 80 | assert(i >= -1 && i < 256); 81 | return isupper(i); 82 | } 83 | 84 | int str_isxdigit(int i) 85 | { 86 | assert(i >= -1 && i < 256); 87 | return isxdigit(i); 88 | } 89 | 90 | #undef strstr 91 | #undef strchr 92 | #undef strrchr 93 | 94 | char *str_strstr(const char *haystack, const char *needle) 95 | { 96 | return strstr(haystack, needle); 97 | } 98 | 99 | char *str_strchr(const char *haystack, int c) 100 | { 101 | return strchr(haystack, c); 102 | } 103 | 104 | char *str_strrchr(const char *haystack, int c) 105 | { 106 | return strrchr(haystack, c); 107 | } 108 | #endif 109 | -------------------------------------------------------------------------------- /buffer/ccan/str/str.c: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #include 3 | 4 | size_t strcount(const char *haystack, const char *needle) 5 | { 6 | size_t i = 0, nlen = strlen(needle); 7 | 8 | while ((haystack = strstr(haystack, needle)) != NULL) { 9 | i++; 10 | haystack += nlen; 11 | } 12 | return i; 13 | } 14 | -------------------------------------------------------------------------------- /buffer/ccan/str/str.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_STR_H 3 | #define CCAN_STR_H 4 | #include "config.h" 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | /** 11 | * streq - Are two strings equal? 12 | * @a: first string 13 | * @b: first string 14 | * 15 | * This macro is arguably more readable than "!strcmp(a, b)". 16 | * 17 | * Example: 18 | * if (streq(somestring, "")) 19 | * printf("String is empty!\n"); 20 | */ 21 | #define streq(a,b) (strcmp((a),(b)) == 0) 22 | 23 | /** 24 | * strstarts - Does this string start with this prefix? 25 | * @str: string to test 26 | * @prefix: prefix to look for at start of str 27 | * 28 | * Example: 29 | * if (strstarts(somestring, "foo")) 30 | * printf("String %s begins with 'foo'!\n", somestring); 31 | */ 32 | #define strstarts(str,prefix) (strncmp((str),(prefix),strlen(prefix)) == 0) 33 | 34 | /** 35 | * strends - Does this string end with this postfix? 36 | * @str: string to test 37 | * @postfix: postfix to look for at end of str 38 | * 39 | * Example: 40 | * if (strends(somestring, "foo")) 41 | * printf("String %s end with 'foo'!\n", somestring); 42 | */ 43 | static inline bool strends(const char *str, const char *postfix) 44 | { 45 | if (strlen(str) < strlen(postfix)) 46 | return false; 47 | 48 | return streq(str + strlen(str) - strlen(postfix), postfix); 49 | } 50 | 51 | /** 52 | * stringify - Turn expression into a string literal 53 | * @expr: any C expression 54 | * 55 | * Example: 56 | * #define PRINT_COND_IF_FALSE(cond) \ 57 | * ((cond) || printf("%s is false!", stringify(cond))) 58 | */ 59 | #define stringify(expr) stringify_1(expr) 60 | /* Double-indirection required to stringify expansions */ 61 | #define stringify_1(expr) #expr 62 | 63 | /** 64 | * strcount - Count number of (non-overlapping) occurrences of a substring. 65 | * @haystack: a C string 66 | * @needle: a substring 67 | * 68 | * Example: 69 | * assert(strcount("aaa aaa", "a") == 6); 70 | * assert(strcount("aaa aaa", "ab") == 0); 71 | * assert(strcount("aaa aaa", "aa") == 2); 72 | */ 73 | size_t strcount(const char *haystack, const char *needle); 74 | 75 | /** 76 | * STR_MAX_CHARS - Maximum possible size of numeric string for this type. 77 | * @type_or_expr: a pointer or integer type or expression. 78 | * 79 | * This provides enough space for a nul-terminated string which represents the 80 | * largest possible value for the type or expression. 81 | * 82 | * Note: The implementation adds extra space so hex values or negative 83 | * values will fit (eg. sprintf(... "%p"). ) 84 | * 85 | * Example: 86 | * char str[STR_MAX_CHARS(int)]; 87 | * 88 | * sprintf(str, "%i", 7); 89 | */ 90 | #define STR_MAX_CHARS(type_or_expr) \ 91 | ((sizeof(type_or_expr) * CHAR_BIT + 8) / 9 * 3 + 2 \ 92 | + STR_MAX_CHARS_TCHECK_(type_or_expr)) 93 | 94 | #if HAVE_TYPEOF 95 | /* Only a simple type can have 0 assigned, so test that. */ 96 | #define STR_MAX_CHARS_TCHECK_(type_or_expr) \ 97 | ({ typeof(type_or_expr) x = 0; (void)x; 0; }) 98 | #else 99 | #define STR_MAX_CHARS_TCHECK_(type_or_expr) 0 100 | #endif 101 | 102 | /** 103 | * cisalnum - isalnum() which takes a char (and doesn't accept EOF) 104 | * @c: a character 105 | * 106 | * Surprisingly, the standard ctype.h isalnum() takes an int, which 107 | * must have the value of EOF (-1) or an unsigned char. This variant 108 | * takes a real char, and doesn't accept EOF. 109 | */ 110 | static inline bool cisalnum(char c) 111 | { 112 | return isalnum((unsigned char)c); 113 | } 114 | static inline bool cisalpha(char c) 115 | { 116 | return isalpha((unsigned char)c); 117 | } 118 | static inline bool cisascii(char c) 119 | { 120 | return isascii((unsigned char)c); 121 | } 122 | #if HAVE_ISBLANK 123 | static inline bool cisblank(char c) 124 | { 125 | return isblank((unsigned char)c); 126 | } 127 | #endif 128 | static inline bool ciscntrl(char c) 129 | { 130 | return iscntrl((unsigned char)c); 131 | } 132 | static inline bool cisdigit(char c) 133 | { 134 | return isdigit((unsigned char)c); 135 | } 136 | static inline bool cisgraph(char c) 137 | { 138 | return isgraph((unsigned char)c); 139 | } 140 | static inline bool cislower(char c) 141 | { 142 | return islower((unsigned char)c); 143 | } 144 | static inline bool cisprint(char c) 145 | { 146 | return isprint((unsigned char)c); 147 | } 148 | static inline bool cispunct(char c) 149 | { 150 | return ispunct((unsigned char)c); 151 | } 152 | static inline bool cisspace(char c) 153 | { 154 | return isspace((unsigned char)c); 155 | } 156 | static inline bool cisupper(char c) 157 | { 158 | return isupper((unsigned char)c); 159 | } 160 | static inline bool cisxdigit(char c) 161 | { 162 | return isxdigit((unsigned char)c); 163 | } 164 | 165 | #include 166 | 167 | /* These checks force things out of line, hence they are under DEBUG. */ 168 | #ifdef CCAN_STR_DEBUG 169 | #include 170 | 171 | /* These are commonly misused: they take -1 or an *unsigned* char value. */ 172 | #undef isalnum 173 | #undef isalpha 174 | #undef isascii 175 | #undef isblank 176 | #undef iscntrl 177 | #undef isdigit 178 | #undef isgraph 179 | #undef islower 180 | #undef isprint 181 | #undef ispunct 182 | #undef isspace 183 | #undef isupper 184 | #undef isxdigit 185 | 186 | /* You can use a char if char is unsigned. */ 187 | #if HAVE_BUILTIN_TYPES_COMPATIBLE_P && HAVE_TYPEOF 188 | #define str_check_arg_(i) \ 189 | ((i) + BUILD_ASSERT_OR_ZERO(!__builtin_types_compatible_p(typeof(i), \ 190 | char) \ 191 | || (char)255 > 0)) 192 | #else 193 | #define str_check_arg_(i) (i) 194 | #endif 195 | 196 | #define isalnum(i) str_isalnum(str_check_arg_(i)) 197 | #define isalpha(i) str_isalpha(str_check_arg_(i)) 198 | #define isascii(i) str_isascii(str_check_arg_(i)) 199 | #if HAVE_ISBLANK 200 | #define isblank(i) str_isblank(str_check_arg_(i)) 201 | #endif 202 | #define iscntrl(i) str_iscntrl(str_check_arg_(i)) 203 | #define isdigit(i) str_isdigit(str_check_arg_(i)) 204 | #define isgraph(i) str_isgraph(str_check_arg_(i)) 205 | #define islower(i) str_islower(str_check_arg_(i)) 206 | #define isprint(i) str_isprint(str_check_arg_(i)) 207 | #define ispunct(i) str_ispunct(str_check_arg_(i)) 208 | #define isspace(i) str_isspace(str_check_arg_(i)) 209 | #define isupper(i) str_isupper(str_check_arg_(i)) 210 | #define isxdigit(i) str_isxdigit(str_check_arg_(i)) 211 | 212 | #if HAVE_TYPEOF 213 | /* With GNU magic, we can make const-respecting standard string functions. */ 214 | #undef strstr 215 | #undef strchr 216 | #undef strrchr 217 | 218 | /* + 0 is needed to decay array into pointer. */ 219 | #define strstr(haystack, needle) \ 220 | ((typeof((haystack) + 0))str_strstr((haystack), (needle))) 221 | #define strchr(haystack, c) \ 222 | ((typeof((haystack) + 0))str_strchr((haystack), (c))) 223 | #define strrchr(haystack, c) \ 224 | ((typeof((haystack) + 0))str_strrchr((haystack), (c))) 225 | #endif 226 | #endif /* CCAN_STR_DEBUG */ 227 | 228 | #endif /* CCAN_STR_H */ 229 | -------------------------------------------------------------------------------- /buffer/ccan/str/str_debug.h: -------------------------------------------------------------------------------- 1 | /* CC0 (Public domain) - see LICENSE file for details */ 2 | #ifndef CCAN_STR_DEBUG_H 3 | #define CCAN_STR_DEBUG_H 4 | 5 | /* #define CCAN_STR_DEBUG 1 */ 6 | 7 | #ifdef CCAN_STR_DEBUG 8 | /* Because we mug the real ones with macros, we need our own wrappers. */ 9 | int str_isalnum(int i); 10 | int str_isalpha(int i); 11 | int str_isascii(int i); 12 | #if HAVE_ISBLANK 13 | int str_isblank(int i); 14 | #endif 15 | int str_iscntrl(int i); 16 | int str_isdigit(int i); 17 | int str_isgraph(int i); 18 | int str_islower(int i); 19 | int str_isprint(int i); 20 | int str_ispunct(int i); 21 | int str_isspace(int i); 22 | int str_isupper(int i); 23 | int str_isxdigit(int i); 24 | 25 | char *str_strstr(const char *haystack, const char *needle); 26 | char *str_strchr(const char *s, int c); 27 | char *str_strrchr(const char *s, int c); 28 | #endif /* CCAN_STR_DEBUG */ 29 | 30 | #endif /* CCAN_STR_DEBUG_H */ 31 | -------------------------------------------------------------------------------- /buffer/config.h: -------------------------------------------------------------------------------- 1 | /* Generated by CCAN configurator */ 2 | #ifndef CCAN_CONFIG_H 3 | #define CCAN_CONFIG_H 4 | #ifndef _GNU_SOURCE 5 | #define _GNU_SOURCE /* Always use GNU extensions. */ 6 | #endif 7 | #define CCAN_COMPILER "cc" 8 | #define CCAN_CFLAGS "-g3 -ggdb -Wall -Wstrict-prototypes -Wold-style-definition -Wmissing-prototypes -Wmissing-declarations -Wpointer-arith -Wwrite-strings -Wundef -DCCAN_STR_DEBUG=1" 9 | 10 | #define HAVE_CCAN 1 11 | #define HAVE_32BIT_OFF_T 1 12 | #define HAVE_ALIGNOF 1 13 | #define HAVE_ASPRINTF 1 14 | #define HAVE_ATTRIBUTE_COLD 0 15 | #define HAVE_ATTRIBUTE_CONST 1 16 | #define HAVE_ATTRIBUTE_MAY_ALIAS 1 17 | #define HAVE_ATTRIBUTE_NORETURN 1 18 | #define HAVE_ATTRIBUTE_PRINTF 1 19 | #define HAVE_ATTRIBUTE_UNUSED 1 20 | #define HAVE_ATTRIBUTE_USED 1 21 | #define HAVE_BACKTRACE 1 22 | #define HAVE_BIG_ENDIAN 0 23 | #define HAVE_BSWAP_64 1 24 | #define HAVE_BUILTIN_CHOOSE_EXPR 1 25 | #define HAVE_BUILTIN_CLZ 1 26 | #define HAVE_BUILTIN_CLZL 1 27 | #define HAVE_BUILTIN_CLZLL 1 28 | #define HAVE_BUILTIN_CONSTANT_P 1 29 | #define HAVE_BUILTIN_EXPECT 1 30 | #define HAVE_BUILTIN_FFSL 1 31 | #define HAVE_BUILTIN_FFSLL 1 32 | #define HAVE_BUILTIN_POPCOUNTL 1 33 | #define HAVE_BUILTIN_TYPES_COMPATIBLE_P 1 34 | #define HAVE_BYTESWAP_H 1 35 | #define HAVE_CLOCK_GETTIME 0 36 | #define HAVE_CLOCK_GETTIME_IN_LIBRT 1 37 | #define HAVE_COMPOUND_LITERALS 1 38 | #define HAVE_FCHDIR 1 39 | #define HAVE_ERR_H 1 40 | #define HAVE_FILE_OFFSET_BITS 1 41 | #define HAVE_FOR_LOOP_DECLARATION 0 42 | #define HAVE_FLEXIBLE_ARRAY_MEMBER 1 43 | #define HAVE_GETPAGESIZE 1 44 | #define HAVE_ISBLANK 1 45 | #define HAVE_LITTLE_ENDIAN 1 46 | #define HAVE_MEMMEM 1 47 | #define HAVE_MMAP 1 48 | #define HAVE_PROC_SELF_MAPS 1 49 | #define HAVE_QSORT_R_PRIVATE_LAST 1 50 | #define HAVE_STRUCT_TIMESPEC 1 51 | #define HAVE_SECTION_START_STOP 1 52 | #define HAVE_STACK_GROWS_UPWARDS 0 53 | #define HAVE_STATEMENT_EXPR 1 54 | #define HAVE_SYS_FILIO_H 0 55 | #define HAVE_TYPEOF 1 56 | #define HAVE_UTIME 1 57 | #define HAVE_WARN_UNUSED_RESULT 1 58 | #endif /* CCAN_CONFIG_H */ 59 | -------------------------------------------------------------------------------- /buffer/licenses/CC0: -------------------------------------------------------------------------------- 1 | Statement of Purpose 2 | 3 | The laws of most jurisdictions throughout the world automatically confer exclusive Copyright and Related Rights (defined below) upon the creator and subsequent owner(s) (each and all, an "owner") of an original work of authorship and/or a database (each, a "Work"). 4 | 5 | Certain owners wish to permanently relinquish those rights to a Work for the purpose of contributing to a commons of creative, cultural and scientific works ("Commons") that the public can reliably and without fear of later claims of infringement build upon, modify, incorporate in other works, reuse and redistribute as freely as possible in any form whatsoever and for any purposes, including without limitation commercial purposes. These owners may contribute to the Commons to promote the ideal of a free culture and the further production of creative, cultural and scientific works, or to gain reputation or greater distribution for their Work in part through the use and efforts of others. 6 | 7 | For these and/or other purposes and motivations, and without any expectation of additional consideration or compensation, the person associating CC0 with a Work (the "Affirmer"), to the extent that he or she is an owner of Copyright and Related Rights in the Work, voluntarily elects to apply CC0 to the Work and publicly distribute the Work under its terms, with knowledge of his or her Copyright and Related Rights in the Work and the meaning and intended legal effect of CC0 on those rights. 8 | 9 | 1. Copyright and Related Rights. A Work made available under CC0 may be protected by copyright and related or neighboring rights ("Copyright and Related Rights"). Copyright and Related Rights include, but are not limited to, the following: 10 | 11 | the right to reproduce, adapt, distribute, perform, display, communicate, and translate a Work; 12 | moral rights retained by the original author(s) and/or performer(s); 13 | publicity and privacy rights pertaining to a person's image or likeness depicted in a Work; 14 | rights protecting against unfair competition in regards to a Work, subject to the limitations in paragraph 4(a), below; 15 | rights protecting the extraction, dissemination, use and reuse of data in a Work; 16 | database rights (such as those arising under Directive 96/9/EC of the European Parliament and of the Council of 11 March 1996 on the legal protection of databases, and under any national implementation thereof, including any amended or successor version of such directive); and 17 | other similar, equivalent or corresponding rights throughout the world based on applicable law or treaty, and any national implementations thereof. 18 | 19 | 2. Waiver. To the greatest extent permitted by, but not in contravention of, applicable law, Affirmer hereby overtly, fully, permanently, irrevocably and unconditionally waives, abandons, and surrenders all of Affirmer's Copyright and Related Rights and associated claims and causes of action, whether now known or unknown (including existing as well as future claims and causes of action), in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each member of the public at large and to the detriment of Affirmer's heirs and successors, fully intending that such Waiver shall not be subject to revocation, rescission, cancellation, termination, or any other legal or equitable action to disrupt the quiet enjoyment of the Work by the public as contemplated by Affirmer's express Statement of Purpose. 20 | 21 | 3. Public License Fallback. Should any part of the Waiver for any reason be judged legally invalid or ineffective under applicable law, then the Waiver shall be preserved to the maximum extent permitted taking into account Affirmer's express Statement of Purpose. In addition, to the extent the Waiver is so judged Affirmer hereby grants to each affected person a royalty-free, non transferable, non sublicensable, non exclusive, irrevocable and unconditional license to exercise Affirmer's Copyright and Related Rights in the Work (i) in all territories worldwide, (ii) for the maximum duration provided by applicable law or treaty (including future time extensions), (iii) in any current or future medium and for any number of copies, and (iv) for any purpose whatsoever, including without limitation commercial, advertising or promotional purposes (the "License"). The License shall be deemed effective as of the date CC0 was applied by Affirmer to the Work. Should any part of the License for any reason be judged legally invalid or ineffective under applicable law, such partial invalidity or ineffectiveness shall not invalidate the remainder of the License, and in such case Affirmer hereby affirms that he or she will not (i) exercise any of his or her remaining Copyright and Related Rights in the Work or (ii) assert any associated claims and causes of action with respect to the Work, in either case contrary to Affirmer's express Statement of Purpose. 22 | 23 | 4. Limitations and Disclaimers. 24 | 25 | No trademark or patent rights held by Affirmer are waived, abandoned, surrendered, licensed or otherwise affected by this document. 26 | Affirmer offers the Work as-is and makes no representations or warranties of any kind concerning the Work, express, implied, statutory or otherwise, including without limitation warranties of title, merchantability, fitness for a particular purpose, non infringement, or the absence of latent or other defects, accuracy, or the present or absence of errors, whether or not discoverable, all to the greatest extent permissible under applicable law. 27 | Affirmer disclaims responsibility for clearing rights of other persons that may apply to the Work or any use thereof, including without limitation any person's Copyright and Related Rights in the Work. Further, Affirmer disclaims responsibility for obtaining any necessary consents, permissions or other rights required for any use of the Work. 28 | Affirmer understands and acknowledges that Creative Commons is not a party to this document and has no duty or obligation with respect to this CC0 or use of the Work. 29 | -------------------------------------------------------------------------------- /buffer/licenses/LGPL-2.1: -------------------------------------------------------------------------------- 1 | 2 | GNU LESSER GENERAL PUBLIC LICENSE 3 | Version 2.1, February 1999 4 | 5 | Copyright (C) 1991, 1999 Free Software Foundation, Inc. 6 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 7 | Everyone is permitted to copy and distribute verbatim copies 8 | of this license document, but changing it is not allowed. 9 | 10 | [This is the first released version of the Lesser GPL. It also counts 11 | as the successor of the GNU Library Public License, version 2, hence 12 | the version number 2.1.] 13 | 14 | Preamble 15 | 16 | The licenses for most software are designed to take away your 17 | freedom to share and change it. By contrast, the GNU General Public 18 | Licenses are intended to guarantee your freedom to share and change 19 | free software--to make sure the software is free for all its users. 20 | 21 | This license, the Lesser General Public License, applies to some 22 | specially designated software packages--typically libraries--of the 23 | Free Software Foundation and other authors who decide to use it. You 24 | can use it too, but we suggest you first think carefully about whether 25 | this license or the ordinary General Public License is the better 26 | strategy to use in any particular case, based on the explanations 27 | below. 28 | 29 | When we speak of free software, we are referring to freedom of use, 30 | not price. Our General Public Licenses are designed to make sure that 31 | you have the freedom to distribute copies of free software (and charge 32 | for this service if you wish); that you receive source code or can get 33 | it if you want it; that you can change the software and use pieces of 34 | it in new free programs; and that you are informed that you can do 35 | these things. 36 | 37 | To protect your rights, we need to make restrictions that forbid 38 | distributors to deny you these rights or to ask you to surrender these 39 | rights. These restrictions translate to certain responsibilities for 40 | you if you distribute copies of the library or if you modify it. 41 | 42 | For example, if you distribute copies of the library, whether gratis 43 | or for a fee, you must give the recipients all the rights that we gave 44 | you. You must make sure that they, too, receive or can get the source 45 | code. If you link other code with the library, you must provide 46 | complete object files to the recipients, so that they can relink them 47 | with the library after making changes to the library and recompiling 48 | it. And you must show them these terms so they know their rights. 49 | 50 | We protect your rights with a two-step method: (1) we copyright the 51 | library, and (2) we offer you this license, which gives you legal 52 | permission to copy, distribute and/or modify the library. 53 | 54 | To protect each distributor, we want to make it very clear that 55 | there is no warranty for the free library. Also, if the library is 56 | modified by someone else and passed on, the recipients should know 57 | that what they have is not the original version, so that the original 58 | author's reputation will not be affected by problems that might be 59 | introduced by others. 60 | 61 | Finally, software patents pose a constant threat to the existence of 62 | any free program. We wish to make sure that a company cannot 63 | effectively restrict the users of a free program by obtaining a 64 | restrictive license from a patent holder. Therefore, we insist that 65 | any patent license obtained for a version of the library must be 66 | consistent with the full freedom of use specified in this license. 67 | 68 | Most GNU software, including some libraries, is covered by the 69 | ordinary GNU General Public License. This license, the GNU Lesser 70 | General Public License, applies to certain designated libraries, and 71 | is quite different from the ordinary General Public License. We use 72 | this license for certain libraries in order to permit linking those 73 | libraries into non-free programs. 74 | 75 | When a program is linked with a library, whether statically or using 76 | a shared library, the combination of the two is legally speaking a 77 | combined work, a derivative of the original library. The ordinary 78 | General Public License therefore permits such linking only if the 79 | entire combination fits its criteria of freedom. The Lesser General 80 | Public License permits more lax criteria for linking other code with 81 | the library. 82 | 83 | We call this license the "Lesser" General Public License because it 84 | does Less to protect the user's freedom than the ordinary General 85 | Public License. It also provides other free software developers Less 86 | of an advantage over competing non-free programs. These disadvantages 87 | are the reason we use the ordinary General Public License for many 88 | libraries. However, the Lesser license provides advantages in certain 89 | special circumstances. 90 | 91 | For example, on rare occasions, there may be a special need to 92 | encourage the widest possible use of a certain library, so that it 93 | becomes a de-facto standard. To achieve this, non-free programs must 94 | be allowed to use the library. A more frequent case is that a free 95 | library does the same job as widely used non-free libraries. In this 96 | case, there is little to gain by limiting the free library to free 97 | software only, so we use the Lesser General Public License. 98 | 99 | In other cases, permission to use a particular library in non-free 100 | programs enables a greater number of people to use a large body of 101 | free software. For example, permission to use the GNU C Library in 102 | non-free programs enables many more people to use the whole GNU 103 | operating system, as well as its variant, the GNU/Linux operating 104 | system. 105 | 106 | Although the Lesser General Public License is Less protective of the 107 | users' freedom, it does ensure that the user of a program that is 108 | linked with the Library has the freedom and the wherewithal to run 109 | that program using a modified version of the Library. 110 | 111 | The precise terms and conditions for copying, distribution and 112 | modification follow. Pay close attention to the difference between a 113 | "work based on the library" and a "work that uses the library". The 114 | former contains code derived from the library, whereas the latter must 115 | be combined with the library in order to run. 116 | 117 | GNU LESSER GENERAL PUBLIC LICENSE 118 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 119 | 120 | 0. This License Agreement applies to any software library or other 121 | program which contains a notice placed by the copyright holder or 122 | other authorized party saying it may be distributed under the terms of 123 | this Lesser General Public License (also called "this License"). 124 | Each licensee is addressed as "you". 125 | 126 | A "library" means a collection of software functions and/or data 127 | prepared so as to be conveniently linked with application programs 128 | (which use some of those functions and data) to form executables. 129 | 130 | The "Library", below, refers to any such software library or work 131 | which has been distributed under these terms. A "work based on the 132 | Library" means either the Library or any derivative work under 133 | copyright law: that is to say, a work containing the Library or a 134 | portion of it, either verbatim or with modifications and/or translated 135 | straightforwardly into another language. (Hereinafter, translation is 136 | included without limitation in the term "modification".) 137 | 138 | "Source code" for a work means the preferred form of the work for 139 | making modifications to it. For a library, complete source code means 140 | all the source code for all modules it contains, plus any associated 141 | interface definition files, plus the scripts used to control 142 | compilation and installation of the library. 143 | 144 | Activities other than copying, distribution and modification are not 145 | covered by this License; they are outside its scope. The act of 146 | running a program using the Library is not restricted, and output from 147 | such a program is covered only if its contents constitute a work based 148 | on the Library (independent of the use of the Library in a tool for 149 | writing it). Whether that is true depends on what the Library does 150 | and what the program that uses the Library does. 151 | 152 | 1. You may copy and distribute verbatim copies of the Library's 153 | complete source code as you receive it, in any medium, provided that 154 | you conspicuously and appropriately publish on each copy an 155 | appropriate copyright notice and disclaimer of warranty; keep intact 156 | all the notices that refer to this License and to the absence of any 157 | warranty; and distribute a copy of this License along with the 158 | Library. 159 | 160 | You may charge a fee for the physical act of transferring a copy, 161 | and you may at your option offer warranty protection in exchange for a 162 | fee. 163 | 164 | 2. You may modify your copy or copies of the Library or any portion 165 | of it, thus forming a work based on the Library, and copy and 166 | distribute such modifications or work under the terms of Section 1 167 | above, provided that you also meet all of these conditions: 168 | 169 | a) The modified work must itself be a software library. 170 | 171 | b) You must cause the files modified to carry prominent notices 172 | stating that you changed the files and the date of any change. 173 | 174 | c) You must cause the whole of the work to be licensed at no 175 | charge to all third parties under the terms of this License. 176 | 177 | d) If a facility in the modified Library refers to a function or a 178 | table of data to be supplied by an application program that uses 179 | the facility, other than as an argument passed when the facility 180 | is invoked, then you must make a good faith effort to ensure that, 181 | in the event an application does not supply such function or 182 | table, the facility still operates, and performs whatever part of 183 | its purpose remains meaningful. 184 | 185 | (For example, a function in a library to compute square roots has 186 | a purpose that is entirely well-defined independent of the 187 | application. Therefore, Subsection 2d requires that any 188 | application-supplied function or table used by this function must 189 | be optional: if the application does not supply it, the square 190 | root function must still compute square roots.) 191 | 192 | These requirements apply to the modified work as a whole. If 193 | identifiable sections of that work are not derived from the Library, 194 | and can be reasonably considered independent and separate works in 195 | themselves, then this License, and its terms, do not apply to those 196 | sections when you distribute them as separate works. But when you 197 | distribute the same sections as part of a whole which is a work based 198 | on the Library, the distribution of the whole must be on the terms of 199 | this License, whose permissions for other licensees extend to the 200 | entire whole, and thus to each and every part regardless of who wrote 201 | it. 202 | 203 | Thus, it is not the intent of this section to claim rights or contest 204 | your rights to work written entirely by you; rather, the intent is to 205 | exercise the right to control the distribution of derivative or 206 | collective works based on the Library. 207 | 208 | In addition, mere aggregation of another work not based on the Library 209 | with the Library (or with a work based on the Library) on a volume of 210 | a storage or distribution medium does not bring the other work under 211 | the scope of this License. 212 | 213 | 3. You may opt to apply the terms of the ordinary GNU General Public 214 | License instead of this License to a given copy of the Library. To do 215 | this, you must alter all the notices that refer to this License, so 216 | that they refer to the ordinary GNU General Public License, version 2, 217 | instead of to this License. (If a newer version than version 2 of the 218 | ordinary GNU General Public License has appeared, then you can specify 219 | that version instead if you wish.) Do not make any other change in 220 | these notices. 221 | 222 | Once this change is made in a given copy, it is irreversible for 223 | that copy, so the ordinary GNU General Public License applies to all 224 | subsequent copies and derivative works made from that copy. 225 | 226 | This option is useful when you wish to copy part of the code of 227 | the Library into a program that is not a library. 228 | 229 | 4. You may copy and distribute the Library (or a portion or 230 | derivative of it, under Section 2) in object code or executable form 231 | under the terms of Sections 1 and 2 above provided that you accompany 232 | it with the complete corresponding machine-readable source code, which 233 | must be distributed under the terms of Sections 1 and 2 above on a 234 | medium customarily used for software interchange. 235 | 236 | If distribution of object code is made by offering access to copy 237 | from a designated place, then offering equivalent access to copy the 238 | source code from the same place satisfies the requirement to 239 | distribute the source code, even though third parties are not 240 | compelled to copy the source along with the object code. 241 | 242 | 5. A program that contains no derivative of any portion of the 243 | Library, but is designed to work with the Library by being compiled or 244 | linked with it, is called a "work that uses the Library". Such a 245 | work, in isolation, is not a derivative work of the Library, and 246 | therefore falls outside the scope of this License. 247 | 248 | However, linking a "work that uses the Library" with the Library 249 | creates an executable that is a derivative of the Library (because it 250 | contains portions of the Library), rather than a "work that uses the 251 | library". The executable is therefore covered by this License. 252 | Section 6 states terms for distribution of such executables. 253 | 254 | When a "work that uses the Library" uses material from a header file 255 | that is part of the Library, the object code for the work may be a 256 | derivative work of the Library even though the source code is not. 257 | Whether this is true is especially significant if the work can be 258 | linked without the Library, or if the work is itself a library. The 259 | threshold for this to be true is not precisely defined by law. 260 | 261 | If such an object file uses only numerical parameters, data 262 | structure layouts and accessors, and small macros and small inline 263 | functions (ten lines or less in length), then the use of the object 264 | file is unrestricted, regardless of whether it is legally a derivative 265 | work. (Executables containing this object code plus portions of the 266 | Library will still fall under Section 6.) 267 | 268 | Otherwise, if the work is a derivative of the Library, you may 269 | distribute the object code for the work under the terms of Section 6. 270 | Any executables containing that work also fall under Section 6, 271 | whether or not they are linked directly with the Library itself. 272 | 273 | 6. As an exception to the Sections above, you may also combine or 274 | link a "work that uses the Library" with the Library to produce a 275 | work containing portions of the Library, and distribute that work 276 | under terms of your choice, provided that the terms permit 277 | modification of the work for the customer's own use and reverse 278 | engineering for debugging such modifications. 279 | 280 | You must give prominent notice with each copy of the work that the 281 | Library is used in it and that the Library and its use are covered by 282 | this License. You must supply a copy of this License. If the work 283 | during execution displays copyright notices, you must include the 284 | copyright notice for the Library among them, as well as a reference 285 | directing the user to the copy of this License. Also, you must do one 286 | of these things: 287 | 288 | a) Accompany the work with the complete corresponding 289 | machine-readable source code for the Library including whatever 290 | changes were used in the work (which must be distributed under 291 | Sections 1 and 2 above); and, if the work is an executable linked 292 | with the Library, with the complete machine-readable "work that 293 | uses the Library", as object code and/or source code, so that the 294 | user can modify the Library and then relink to produce a modified 295 | executable containing the modified Library. (It is understood 296 | that the user who changes the contents of definitions files in the 297 | Library will not necessarily be able to recompile the application 298 | to use the modified definitions.) 299 | 300 | b) Use a suitable shared library mechanism for linking with the 301 | Library. A suitable mechanism is one that (1) uses at run time a 302 | copy of the library already present on the user's computer system, 303 | rather than copying library functions into the executable, and (2) 304 | will operate properly with a modified version of the library, if 305 | the user installs one, as long as the modified version is 306 | interface-compatible with the version that the work was made with. 307 | 308 | c) Accompany the work with a written offer, valid for at least 309 | three years, to give the same user the materials specified in 310 | Subsection 6a, above, for a charge no more than the cost of 311 | performing this distribution. 312 | 313 | d) If distribution of the work is made by offering access to copy 314 | from a designated place, offer equivalent access to copy the above 315 | specified materials from the same place. 316 | 317 | e) Verify that the user has already received a copy of these 318 | materials or that you have already sent this user a copy. 319 | 320 | For an executable, the required form of the "work that uses the 321 | Library" must include any data and utility programs needed for 322 | reproducing the executable from it. However, as a special exception, 323 | the materials to be distributed need not include anything that is 324 | normally distributed (in either source or binary form) with the major 325 | components (compiler, kernel, and so on) of the operating system on 326 | which the executable runs, unless that component itself accompanies 327 | the executable. 328 | 329 | It may happen that this requirement contradicts the license 330 | restrictions of other proprietary libraries that do not normally 331 | accompany the operating system. Such a contradiction means you cannot 332 | use both them and the Library together in an executable that you 333 | distribute. 334 | 335 | 7. You may place library facilities that are a work based on the 336 | Library side-by-side in a single library together with other library 337 | facilities not covered by this License, and distribute such a combined 338 | library, provided that the separate distribution of the work based on 339 | the Library and of the other library facilities is otherwise 340 | permitted, and provided that you do these two things: 341 | 342 | a) Accompany the combined library with a copy of the same work 343 | based on the Library, uncombined with any other library 344 | facilities. This must be distributed under the terms of the 345 | Sections above. 346 | 347 | b) Give prominent notice with the combined library of the fact 348 | that part of it is a work based on the Library, and explaining 349 | where to find the accompanying uncombined form of the same work. 350 | 351 | 8. You may not copy, modify, sublicense, link with, or distribute 352 | the Library except as expressly provided under this License. Any 353 | attempt otherwise to copy, modify, sublicense, link with, or 354 | distribute the Library is void, and will automatically terminate your 355 | rights under this License. However, parties who have received copies, 356 | or rights, from you under this License will not have their licenses 357 | terminated so long as such parties remain in full compliance. 358 | 359 | 9. You are not required to accept this License, since you have not 360 | signed it. However, nothing else grants you permission to modify or 361 | distribute the Library or its derivative works. These actions are 362 | prohibited by law if you do not accept this License. Therefore, by 363 | modifying or distributing the Library (or any work based on the 364 | Library), you indicate your acceptance of this License to do so, and 365 | all its terms and conditions for copying, distributing or modifying 366 | the Library or works based on it. 367 | 368 | 10. Each time you redistribute the Library (or any work based on the 369 | Library), the recipient automatically receives a license from the 370 | original licensor to copy, distribute, link with or modify the Library 371 | subject to these terms and conditions. You may not impose any further 372 | restrictions on the recipients' exercise of the rights granted herein. 373 | You are not responsible for enforcing compliance by third parties with 374 | this License. 375 | 376 | 11. If, as a consequence of a court judgment or allegation of patent 377 | infringement or for any other reason (not limited to patent issues), 378 | conditions are imposed on you (whether by court order, agreement or 379 | otherwise) that contradict the conditions of this License, they do not 380 | excuse you from the conditions of this License. If you cannot 381 | distribute so as to satisfy simultaneously your obligations under this 382 | License and any other pertinent obligations, then as a consequence you 383 | may not distribute the Library at all. For example, if a patent 384 | license would not permit royalty-free redistribution of the Library by 385 | all those who receive copies directly or indirectly through you, then 386 | the only way you could satisfy both it and this License would be to 387 | refrain entirely from distribution of the Library. 388 | 389 | If any portion of this section is held invalid or unenforceable under 390 | any particular circumstance, the balance of the section is intended to 391 | apply, and the section as a whole is intended to apply in other 392 | circumstances. 393 | 394 | It is not the purpose of this section to induce you to infringe any 395 | patents or other property right claims or to contest validity of any 396 | such claims; this section has the sole purpose of protecting the 397 | integrity of the free software distribution system which is 398 | implemented by public license practices. Many people have made 399 | generous contributions to the wide range of software distributed 400 | through that system in reliance on consistent application of that 401 | system; it is up to the author/donor to decide if he or she is willing 402 | to distribute software through any other system and a licensee cannot 403 | impose that choice. 404 | 405 | This section is intended to make thoroughly clear what is believed to 406 | be a consequence of the rest of this License. 407 | 408 | 12. If the distribution and/or use of the Library is restricted in 409 | certain countries either by patents or by copyrighted interfaces, the 410 | original copyright holder who places the Library under this License 411 | may add an explicit geographical distribution limitation excluding those 412 | countries, so that distribution is permitted only in or among 413 | countries not thus excluded. In such case, this License incorporates 414 | the limitation as if written in the body of this License. 415 | 416 | 13. The Free Software Foundation may publish revised and/or new 417 | versions of the Lesser General Public License from time to time. 418 | Such new versions will be similar in spirit to the present version, 419 | but may differ in detail to address new problems or concerns. 420 | 421 | Each version is given a distinguishing version number. If the Library 422 | specifies a version number of this License which applies to it and 423 | "any later version", you have the option of following the terms and 424 | conditions either of that version or of any later version published by 425 | the Free Software Foundation. If the Library does not specify a 426 | license version number, you may choose any version ever published by 427 | the Free Software Foundation. 428 | 429 | 14. If you wish to incorporate parts of the Library into other free 430 | programs whose distribution conditions are incompatible with these, 431 | write to the author to ask for permission. For software which is 432 | copyrighted by the Free Software Foundation, write to the Free 433 | Software Foundation; we sometimes make exceptions for this. Our 434 | decision will be guided by the two goals of preserving the free status 435 | of all derivatives of our free software and of promoting the sharing 436 | and reuse of software generally. 437 | 438 | NO WARRANTY 439 | 440 | 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO 441 | WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. 442 | EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR 443 | OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY 444 | KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE 445 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 446 | PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE 447 | LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME 448 | THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 449 | 450 | 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN 451 | WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY 452 | AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU 453 | FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR 454 | CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE 455 | LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING 456 | RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A 457 | FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF 458 | SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 459 | DAMAGES. 460 | 461 | END OF TERMS AND CONDITIONS 462 | 463 | How to Apply These Terms to Your New Libraries 464 | 465 | If you develop a new library, and you want it to be of the greatest 466 | possible use to the public, we recommend making it free software that 467 | everyone can redistribute and change. You can do so by permitting 468 | redistribution under these terms (or, alternatively, under the terms 469 | of the ordinary General Public License). 470 | 471 | To apply these terms, attach the following notices to the library. 472 | It is safest to attach them to the start of each source file to most 473 | effectively convey the exclusion of warranty; and each file should 474 | have at least the "copyright" line and a pointer to where the full 475 | notice is found. 476 | 477 | 478 | 479 | Copyright (C) 480 | 481 | This library is free software; you can redistribute it and/or 482 | modify it under the terms of the GNU Lesser General Public 483 | License as published by the Free Software Foundation; either 484 | version 2.1 of the License, or (at your option) any later version. 485 | 486 | This library is distributed in the hope that it will be useful, 487 | but WITHOUT ANY WARRANTY; without even the implied warranty of 488 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 489 | Lesser General Public License for more details. 490 | 491 | You should have received a copy of the GNU Lesser General Public 492 | License along with this library; if not, write to the Free Software 493 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 494 | 495 | Also add information on how to contact you by electronic and paper mail. 496 | 497 | You should also get your employer (if you work as a programmer) or 498 | your school, if any, to sign a "copyright disclaimer" for the library, 499 | if necessary. Here is a sample; alter the names: 500 | 501 | Yoyodyne, Inc., hereby disclaims all copyright interest in the 502 | library `Frob' (a library for tweaking knobs) written by James 503 | Random Hacker. 504 | 505 | , 1 April 1990 506 | Ty Coon, President of Vice 507 | 508 | That's all there is to it! 509 | 510 | 511 | -------------------------------------------------------------------------------- /buffer_nofree/nofree.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define NOFREE_CHECK_LEVEL 1 4 | 5 | static void nofree_check(nofree_header_t *header) 6 | { 7 | assert(header->magic_start && header->magic_start == header->magic_end); 8 | assert(header->next); 9 | } 10 | 11 | static size_t nofree_align_up(size_t size, size_t align) 12 | { 13 | return (size + align - 1) & ~(align - 1); 14 | } 15 | 16 | int nofree_init(void *buff, size_t buff_size) 17 | { 18 | nofree_header_t *header = (nofree_header_t*) buff; 19 | if (buff_size <= sizeof(nofree_header_t)) { 20 | return -1; 21 | } 22 | header->magic_start = header->magic_end = 0xdeadbeef; 23 | header->next = (char*)buff + 24 | nofree_align_up(sizeof(nofree_header_t), sizeof(long)); 25 | return 0; 26 | } 27 | 28 | void nofree_close(void *buff, size_t buff_size) 29 | { 30 | nofree_header_t *header = (nofree_header_t*) buff; 31 | nofree_check(header); 32 | memset(header, 0, sizeof(nofree_header_t)); 33 | } 34 | 35 | void* nofree_alloc(void *buff, size_t buff_size, size_t size, 36 | size_t align) 37 | { 38 | void *ptr; 39 | nofree_header_t *header = (nofree_header_t*) buff; 40 | #if NOFREE_CHECK_LEVEL > 0 41 | nofree_check(header); 42 | #endif 43 | if (size == 0) { 44 | return NULL; 45 | } 46 | if (align) { 47 | size = nofree_align_up(size, align); 48 | } 49 | ptr = header->next; 50 | header->next += size; 51 | if (header->next > (char*) buff + buff_size || (void*) header->next < buff) { 52 | header->next -= size; 53 | return NULL; 54 | } 55 | return ptr; 56 | } 57 | 58 | -------------------------------------------------------------------------------- /buffer_simple/memmgr.c: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------- 2 | // Statically-allocated memory manager 3 | // 4 | // by Eli Bendersky (eliben@gmail.com) 5 | // 6 | // This code is in the public domain. 7 | //---------------------------------------------------------------- 8 | #include 9 | #include 10 | 11 | typedef ulong Align; 12 | 13 | union mem_header_union 14 | { 15 | struct 16 | { 17 | // Pointer to the next block in the free list 18 | // 19 | union mem_header_union* next; 20 | 21 | // Size of the block (in quantas of sizeof(mem_header_t)) 22 | // 23 | ulong size; 24 | } s; 25 | 26 | // Used to align headers in memory to a boundary 27 | // 28 | Align align_dummy; 29 | }; 30 | 31 | typedef union mem_header_union mem_header_t; 32 | 33 | typedef struct { 34 | // Initial empty list 35 | // 36 | mem_header_t base; 37 | 38 | // Start of free list 39 | // 40 | mem_header_t* freep; 41 | 42 | // Static pool for new allocations 43 | // 44 | byte *pool; 45 | ulong pool_free_pos; 46 | } buff_header_t; 47 | 48 | #define MEMMGR_GET_BUFF_HEADER(B) ((buff_header_t*)(B)) 49 | #define base (buff_header->base) 50 | #define freep (buff_header->freep) 51 | #define pool (buff_header->pool) 52 | #define pool_free_pos (buff_header->pool_free_pos) 53 | #define POOL_SIZE (buff_size) 54 | 55 | void memmgr_init(void *buff, size_t buff_size) 56 | { 57 | buff_header_t *buff_header = MEMMGR_GET_BUFF_HEADER(buff); 58 | base.s.next = 0; 59 | base.s.size = 0; 60 | freep = 0; 61 | pool = (byte*) (buff_header+1); 62 | pool_free_pos = 0; 63 | } 64 | 65 | 66 | void memmgr_print_stats(void *buff, size_t buff_size) 67 | { 68 | buff_header_t *buff_header = MEMMGR_GET_BUFF_HEADER(buff); 69 | #ifdef DEBUG_MEMMGR_SUPPORT_STATS 70 | mem_header_t* p; 71 | 72 | printf("------ Memory manager stats ------\n\n"); 73 | printf( "Pool: free_pos = %lu (%lu bytes left)\n\n", 74 | pool_free_pos, POOL_SIZE - pool_free_pos); 75 | 76 | p = (mem_header_t*) pool; 77 | 78 | while (p < (mem_header_t*) (pool + pool_free_pos)) 79 | { 80 | printf( " * Addr: 0x%8lu; Size: %8lu\n", 81 | (ulong) p, p->s.size); 82 | 83 | p += p->s.size; 84 | } 85 | 86 | printf("\nFree list:\n\n"); 87 | 88 | if (freep) 89 | { 90 | p = freep; 91 | 92 | while (1) 93 | { 94 | printf( " * Addr: 0x%8lu; Size: %8lu; Next: 0x%8lu\n", 95 | (ulong) p, p->s.size, (ulong) p->s.next); 96 | 97 | p = p->s.next; 98 | 99 | if (p == freep) 100 | break; 101 | } 102 | } 103 | else 104 | { 105 | printf("Empty\n"); 106 | } 107 | 108 | printf("\n"); 109 | #endif // DEBUG_MEMMGR_SUPPORT_STATS 110 | } 111 | 112 | 113 | static mem_header_t* get_mem_from_pool(void *buff, size_t buff_size, ulong nquantas) 114 | { 115 | buff_header_t *buff_header = MEMMGR_GET_BUFF_HEADER(buff); 116 | ulong total_req_size; 117 | 118 | mem_header_t* h; 119 | 120 | if (nquantas < MIN_POOL_ALLOC_QUANTAS) 121 | nquantas = MIN_POOL_ALLOC_QUANTAS; 122 | 123 | total_req_size = nquantas * sizeof(mem_header_t); 124 | 125 | if (pool_free_pos + total_req_size <= POOL_SIZE) 126 | { 127 | h = (mem_header_t*) (pool + pool_free_pos); 128 | h->s.size = nquantas; 129 | memmgr_free(buff, buff_size, (void*) (h + 1)); 130 | pool_free_pos += total_req_size; 131 | } 132 | else 133 | { 134 | return 0; 135 | } 136 | 137 | return freep; 138 | } 139 | 140 | 141 | // Allocations are done in 'quantas' of header size. 142 | // The search for a free block of adequate size begins at the point 'freep' 143 | // where the last block was found. 144 | // If a too-big block is found, it is split and the tail is returned (this 145 | // way the header of the original needs only to have its size adjusted). 146 | // The pointer returned to the user points to the free space within the block, 147 | // which begins one quanta after the header. 148 | // 149 | void* memmgr_alloc(void *buff, size_t buff_size, ulong nbytes) 150 | { 151 | buff_header_t *buff_header = MEMMGR_GET_BUFF_HEADER(buff); 152 | mem_header_t* p; 153 | mem_header_t* prevp; 154 | 155 | // Calculate how many quantas are required: we need enough to house all 156 | // the requested bytes, plus the header. The -1 and +1 are there to make sure 157 | // that if nbytes is a multiple of nquantas, we don't allocate too much 158 | // 159 | ulong nquantas = (nbytes + sizeof(mem_header_t) - 1) / sizeof(mem_header_t) + 1; 160 | 161 | // First alloc call, and no free list yet ? Use 'base' for an initial 162 | // denegerate block of size 0, which points to itself 163 | // 164 | if ((prevp = freep) == 0) 165 | { 166 | base.s.next = freep = prevp = &base; 167 | base.s.size = 0; 168 | } 169 | 170 | for (p = prevp->s.next; ; prevp = p, p = p->s.next) 171 | { 172 | // big enough ? 173 | if (p->s.size >= nquantas) 174 | { 175 | // exactly ? 176 | if (p->s.size == nquantas) 177 | { 178 | // just eliminate this block from the free list by pointing 179 | // its prev's next to its next 180 | // 181 | prevp->s.next = p->s.next; 182 | } 183 | else // too big 184 | { 185 | p->s.size -= nquantas; 186 | p += p->s.size; 187 | p->s.size = nquantas; 188 | } 189 | 190 | freep = prevp; 191 | return (void*) (p + 1); 192 | } 193 | // Reached end of free list ? 194 | // Try to allocate the block from the pool. If that succeeds, 195 | // get_mem_from_pool adds the new block to the free list and 196 | // it will be found in the following iterations. If the call 197 | // to get_mem_from_pool doesn't succeed, we've run out of 198 | // memory 199 | // 200 | else if (p == freep) 201 | { 202 | if ((p = get_mem_from_pool(buff, buff_size, nquantas)) == 0) 203 | { 204 | #ifdef DEBUG_MEMMGR_FATAL 205 | printf("!! Memory allocation failed !!\n"); 206 | #endif 207 | return 0; 208 | } 209 | } 210 | } 211 | } 212 | 213 | 214 | // Scans the free list, starting at freep, looking the the place to insert the 215 | // free block. This is either between two existing blocks or at the end of the 216 | // list. In any case, if the block being freed is adjacent to either neighbor, 217 | // the adjacent blocks are combined. 218 | // 219 | void memmgr_free(void *buff, size_t buff_size, void* ap) 220 | { 221 | buff_header_t *buff_header = MEMMGR_GET_BUFF_HEADER(buff); 222 | mem_header_t* block; 223 | mem_header_t* p; 224 | 225 | // acquire pointer to block header 226 | block = ((mem_header_t*) ap) - 1; 227 | 228 | // Find the correct place to place the block in (the free list is sorted by 229 | // address, increasing order) 230 | // 231 | for (p = freep; !(block > p && block < p->s.next); p = p->s.next) 232 | { 233 | // Since the free list is circular, there is one link where a 234 | // higher-addressed block points to a lower-addressed block. 235 | // This condition checks if the block should be actually 236 | // inserted between them 237 | // 238 | if (p >= p->s.next && (block > p || block < p->s.next)) 239 | break; 240 | } 241 | 242 | // Try to combine with the higher neighbor 243 | // 244 | if (block + block->s.size == p->s.next) 245 | { 246 | block->s.size += p->s.next->s.size; 247 | block->s.next = p->s.next->s.next; 248 | } 249 | else 250 | { 251 | block->s.next = p->s.next; 252 | } 253 | 254 | // Try to combine with the lower neighbor 255 | // 256 | if (p + p->s.size == block) 257 | { 258 | p->s.size += block->s.size; 259 | p->s.next = block->s.next; 260 | } 261 | else 262 | { 263 | p->s.next = block; 264 | } 265 | 266 | freep = p; 267 | } 268 | -------------------------------------------------------------------------------- /buffer_slab/slab.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | static inline void slab_check(slab_header_t *header) 5 | { 6 | assert(header->magic_start && header->magic_start == header->magic_end); 7 | } 8 | 9 | static inline unsigned slab_address_to_block(slab_header_t *header, 10 | char *addr) 11 | { 12 | unsigned block; 13 | if (addr < header->blocks) { 14 | return UINT_MAX; 15 | } 16 | block = addr - header->blocks; 17 | if (block%header->block_size > 0) { 18 | return UINT_MAX; 19 | } 20 | block/=header->block_size; 21 | if (block >= header->num_blocks) { 22 | return UINT_MAX; 23 | } 24 | return block; 25 | } 26 | 27 | static inline void* slab_block_to_address(slab_header_t *header, 28 | unsigned block) 29 | { 30 | return header->blocks + block*header->block_size; 31 | } 32 | 33 | static inline unsigned slab_find_free_block(slab_header_t *header) 34 | { 35 | unsigned next_block = header->next_block; 36 | unsigned i; 37 | for (i=0;inum_blocks;i++) { 38 | if (header->bitmap[next_block] == 0) { 39 | return next_block; 40 | } 41 | next_block = (next_block+1) % header->num_blocks; 42 | } 43 | return UINT_MAX; 44 | } 45 | 46 | int slab_init(void *buff, size_t buff_size, size_t block_size) 47 | { 48 | slab_header_t *header = (slab_header_t*) buff; 49 | block_size += block_size%sizeof(long) ? 50 | sizeof(long) - block_size%sizeof(long) : 0; 51 | if (buff_size <= sizeof(slab_header_t) + block_size*2 + sizeof(long)) { 52 | return -1; 53 | } 54 | if (block_size <=0 || buff_size <=0) { 55 | return -2; 56 | } 57 | header->magic_start = header->magic_end = 0xdeadbeef; 58 | header->block_size = block_size; 59 | header->num_blocks = (buff_size-sizeof(long)) / (block_size+1); 60 | assert(header->num_blocks > 0); 61 | header->bitmap = (char*) buff + sizeof(slab_header_t); 62 | header->blocks = header->bitmap + header->num_blocks; 63 | if (((unsigned long)header->blocks)%sizeof(long) > 0) { 64 | header->blocks += sizeof(long) - 65 | ((unsigned long)header->blocks)%sizeof(long); 66 | } 67 | memset(header->bitmap, 0, sizeof(char)*header->num_blocks); 68 | header->next_block = 0; 69 | return 0; 70 | } 71 | 72 | void slab_close(void *buff) 73 | { 74 | slab_header_t *header = (slab_header_t*) buff; 75 | slab_check(header); 76 | memset(header, 0, sizeof(slab_header_t)); 77 | } 78 | 79 | void* slab_alloc(void *buff, size_t size) 80 | { 81 | slab_header_t *header = (slab_header_t*) buff; 82 | unsigned b; 83 | assert(size == header->block_size && "Invalid slab allocation size!"); 84 | b = slab_find_free_block(header); 85 | if (b == UINT_MAX) { 86 | return NULL; 87 | } 88 | header->bitmap[b]=1; 89 | header->next_block = (b+1) % header->num_blocks; 90 | return slab_block_to_address(header, b); 91 | } 92 | 93 | void slab_free(void *buff, void *ptr) 94 | { 95 | slab_header_t *header = (slab_header_t*) buff; 96 | unsigned b = slab_address_to_block(header, (char*)ptr); 97 | assert(b != UINT_MAX && "Invalid free!"); 98 | assert(header->bitmap[b] == 1 && "Double free!"); 99 | header->bitmap[b]=0; 100 | } 101 | -------------------------------------------------------------------------------- /include/buffer/alloc.h: -------------------------------------------------------------------------------- 1 | /* Licensed under LGPLv2.1+ - see LICENSE file for details */ 2 | #ifndef ALLOC_H 3 | #define ALLOC_H 4 | #include 5 | #include 6 | 7 | /** 8 | * alloc_init - initialize a pool of memory for the allocator. 9 | * @pool: the contiguous bytes for the allocator to use 10 | * @poolsize: the size of the pool 11 | * 12 | * This stores all the setup state required to perform allocation within the 13 | * pool (there is no external state). Any previous contents of @pool is 14 | * discarded. 15 | * 16 | * The same @pool and @poolsize arguments must be handed to the other alloc 17 | * functions after this. 18 | * 19 | * If the pool is too small for meaningful allocations, alloc_get will fail. 20 | * 21 | * Example: 22 | * void *pool = malloc(32*1024*1024); 23 | * if (!pool) 24 | * err(1, "Failed to allocate 32MB"); 25 | * alloc_init(pool, 32*1024*1024); 26 | */ 27 | void alloc_init(void *pool, unsigned long poolsize); 28 | 29 | /** 30 | * alloc_get - allocate some memory from the pool 31 | * @pool: the contiguous bytes for the allocator to use 32 | * @poolsize: the size of the pool 33 | * @size: the size of the desired allocation 34 | * @align: the alignment of the desired allocation (0 or power of 2) 35 | * 36 | * This is "malloc" within an initialized pool. 37 | * 38 | * It will return a unique pointer within the pool (ie. between @pool 39 | * and @pool+@poolsize) which meets the alignment requirements of 40 | * @align. Note that the alignment is relative to the start of the pool, 41 | * so of @pool is not aligned, the pointer won't be either. 42 | * 43 | * Returns NULL if there is no contiguous room. 44 | * 45 | * Example: 46 | * #include 47 | * ... 48 | * double *d = alloc_get(pool, 32*1024*1024, 49 | * sizeof(*d), ALIGNOF(*d)); 50 | * if (!d) 51 | * err(1, "Failed to allocate a double"); 52 | */ 53 | void *alloc_get(void *pool, unsigned long poolsize, 54 | unsigned long size, unsigned long align); 55 | 56 | /** 57 | * alloc_free - free some allocated memory from the pool 58 | * @pool: the contiguous bytes for the allocator to use 59 | * @poolsize: the size of the pool 60 | * @p: the non-NULL pointer returned from alloc_get. 61 | * 62 | * This is "free" within an initialized pool. A pointer should only be 63 | * freed once, and must be a pointer returned from a successful alloc_get() 64 | * call. 65 | * 66 | * Example: 67 | * alloc_free(pool, 32*1024*1024, d); 68 | */ 69 | void alloc_free(void *pool, unsigned long poolsize, void *free); 70 | 71 | /** 72 | * alloc_size - get the actual size allocated by alloc_get 73 | * @pool: the contiguous bytes for the allocator to use 74 | * @poolsize: the size of the pool 75 | * @p: the non-NULL pointer returned from alloc_get. 76 | * 77 | * alloc_get() may overallocate, in which case you may use the extra 78 | * space exactly as if you had asked for it. 79 | * 80 | * The return value will always be at least the @size passed to alloc_get(). 81 | * 82 | * Example: 83 | * printf("Allocating a double actually got me %lu bytes\n", 84 | * alloc_size(pool, 32*1024*1024, d)); 85 | */ 86 | unsigned long alloc_size(void *pool, unsigned long poolsize, void *p); 87 | 88 | /** 89 | * alloc_check - check the integrity of the allocation pool 90 | * @pool: the contiguous bytes for the allocator to use 91 | * @poolsize: the size of the pool 92 | * 93 | * alloc_check() can be used for debugging suspected pool corruption. It may 94 | * be quite slow, but provides some assistance for hard-to-find overruns or 95 | * double-frees. Unlike the rest of the code, it will not crash on corrupted 96 | * pools. 97 | * 98 | * There is an internal function check_fail() which this calls on failure which 99 | * is useful for placing breakpoints and gaining more insight into the type 100 | * of the corruption detected. 101 | * 102 | * Example: 103 | * #include 104 | * ... 105 | * assert(alloc_check(pool, 32*1024*1024)); 106 | */ 107 | bool alloc_check(void *pool, unsigned long poolsize); 108 | 109 | /** 110 | * alloc_visualize - dump information about the allocation pool 111 | * @pool: the contiguous bytes for the allocator to use 112 | * @poolsize: the size of the pool 113 | * 114 | * When debugging the allocator itself, it's often useful to see how 115 | * the pool is being used. alloc_visualize() does that, but makes 116 | * assumptions about correctness (like the rest of the code) so if you 117 | * suspect corruption call alloc_check() first. 118 | * 119 | * Example: 120 | * d = alloc_get(pool, 32*1024*1024, sizeof(*d), ALIGNOF(*d)); 121 | * if (!d) { 122 | * fprintf(stderr, "Allocation failed!\n"); 123 | * if (!alloc_check(pool, 32*1024*1024)) 124 | * errx(1, "Allocation pool is corrupt"); 125 | * alloc_visualize(stderr, pool, 32*1024*1024); 126 | * exit(1); 127 | * } 128 | */ 129 | void alloc_visualize(FILE *out, void *pool, unsigned long poolsize); 130 | #endif /* ALLOC_H */ 131 | -------------------------------------------------------------------------------- /include/buffer_nofree/nofree.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_NOFREE_H 2 | #define BUFFER_NOFREE_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* Simple buffer-based allocator implementation that never frees memory. */ 9 | typedef struct { 10 | int magic_start; 11 | char *next; 12 | int magic_end; 13 | } nofree_header_t; 14 | 15 | int nofree_init(void *buff, size_t buff_size); 16 | void nofree_close(void *buff, size_t buff_size); 17 | void* nofree_alloc(void *buff, size_t buff_size, size_t size, 18 | size_t align); 19 | 20 | #endif /* BUFFER_NOFREE_H */ 21 | 22 | -------------------------------------------------------------------------------- /include/buffer_simple/memmgr.h: -------------------------------------------------------------------------------- 1 | //---------------------------------------------------------------- 2 | // Statically-allocated memory manager 3 | // 4 | // by Eli Bendersky (eliben@gmail.com) 5 | // 6 | // This code is in the public domain. 7 | //---------------------------------------------------------------- 8 | #ifndef MEMMGR_H 9 | #define MEMMGR_H 10 | 11 | // 12 | // Memory manager: dynamically allocates memory from 13 | // a fixed pool that is allocated statically at link-time. 14 | // 15 | // Usage: after calling memmgr_init() in your 16 | // initialization routine, just use memmgr_alloc() instead 17 | // of malloc() and memmgr_free() instead of free(). 18 | // Naturally, you can use the preprocessor to define 19 | // malloc() and free() as aliases to memmgr_alloc() and 20 | // memmgr_free(). This way the manager will be a drop-in 21 | // replacement for the standard C library allocators, and can 22 | // be useful for debugging memory allocation problems and 23 | // leaks. 24 | // 25 | // Preprocessor flags you can define to customize the 26 | // memory manager: 27 | // 28 | // DEBUG_MEMMGR_FATAL 29 | // Allow printing out a message when allocations fail 30 | // 31 | // DEBUG_MEMMGR_SUPPORT_STATS 32 | // Allow printing out of stats in function 33 | // memmgr_print_stats When this is disabled, 34 | // memmgr_print_stats does nothing. 35 | // 36 | // Note that in production code on an embedded system 37 | // you'll probably want to keep those undefined, because 38 | // they cause printf to be called. 39 | // 40 | // MIN_POOL_ALLOC_QUANTAS 41 | // Internally, the memory manager allocates memory in 42 | // quantas roughly the size of two ulong objects. To 43 | // minimize pool fragmentation in case of multiple allocations 44 | // and deallocations, it is advisable to not allocate 45 | // blocks that are too small. 46 | // This flag sets the minimal ammount of quantas for 47 | // an allocation. If the size of a ulong is 4 and you 48 | // set this flag to 16, the minimal size of an allocation 49 | // will be 4 * 2 * 16 = 128 bytes 50 | // If you have a lot of small allocations, keep this value 51 | // low to conserve memory. If you have mostly large 52 | // allocations, it is best to make it higher, to avoid 53 | // fragmentation. 54 | // 55 | // Notes: 56 | // 1. This memory manager is *not thread safe*. Use it only 57 | // for single thread/task applications. 58 | // 59 | 60 | #define DEBUG_MEMMGR_SUPPORT_STATS 1 61 | 62 | #define MIN_POOL_ALLOC_QUANTAS 8 63 | 64 | 65 | typedef unsigned char byte; 66 | typedef unsigned long ulong; 67 | 68 | 69 | 70 | // Initialize the memory manager. This function should be called 71 | // only once in the beginning of the program. 72 | // 73 | void memmgr_init(void *buff, size_t buff_size); 74 | 75 | // 'malloc' clone 76 | // 77 | void* memmgr_alloc(void *buff, size_t buff_size, ulong nbytes); 78 | 79 | // 'free' clone 80 | // 81 | void memmgr_free(void *buff, size_t buff_size, void* ap); 82 | 83 | // Prints statistics about the current state of the memory 84 | // manager 85 | // 86 | void memmgr_print_stats(void *buff, size_t buff_size); 87 | 88 | 89 | #endif // MEMMGR_H 90 | -------------------------------------------------------------------------------- /include/buffer_slab/slab.h: -------------------------------------------------------------------------------- 1 | #ifndef BUFFER_SLAB_H 2 | #define BUFFER_SLAB_H 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | /* Simple buffer-based slab allocator. 9 | * Can only allocate/deallocate blocks of a predetermined size. 10 | */ 11 | typedef struct { 12 | int magic_start; 13 | size_t block_size; 14 | size_t num_blocks; 15 | char *bitmap; 16 | char *blocks; 17 | unsigned next_block; 18 | int magic_end; 19 | } slab_header_t; 20 | 21 | int slab_init(void *buff, size_t buff_size, size_t block_size); 22 | void slab_close(void *buff); 23 | void* slab_alloc(void *buff, size_t size); 24 | void slab_free(void *buff, void *ptr); 25 | 26 | #endif /* BUFFER_SLAB_H */ 27 | 28 | -------------------------------------------------------------------------------- /include/mplite/mplite.h: -------------------------------------------------------------------------------- 1 | /** 2 | * The author disclaims copyright to this source code. In place of 3 | * a legal notice, here is a blessing: 4 | * 5 | * May you do good and not evil. 6 | * May you find forgiveness for yourself and forgive others. 7 | * May you share freely, never taking more than you give. 8 | * 9 | * This file contains the APIs that implement a memory allocation subsystem 10 | * based on SQLite's memsys5 memory subsystem. Refer to 11 | * http://www.sqlite.org/malloc.html for more info. 12 | * 13 | * This version of the memory allocation subsystem omits all 14 | * use of malloc(). The application gives a block of memory 15 | * from which allocations are made and returned by the mplite_malloc() 16 | * and mplite_realloc() implementations. 17 | * 18 | * This memory allocator uses the following algorithm: 19 | * 20 | * 1. All memory allocations sizes are rounded up to a power of 2. 21 | * 22 | * 2. If two adjacent free blocks are the halves of a larger block, 23 | * then the two blocks are coalesed into the single larger block. 24 | * 25 | * 3. New memory is allocated from the first available free block. 26 | * 27 | * This algorithm is described in: J. M. Robson. "Bounds for Some Functions 28 | * Concerning Dynamic Storage Allocation". Journal of the Association for 29 | * Computing Machinery, Volume 21, Number 8, July 1974, pages 491-499. 30 | * 31 | * Let n be the size of the largest allocation divided by the minimum 32 | * allocation size (after rounding all sizes up to a power of 2.) Let M 33 | * be the maximum amount of memory ever outstanding at one time. Let 34 | * N be the total amount of memory available for allocation. Robson 35 | * proved that this memory allocator will never breakdown due to 36 | * fragmentation as long as the following constraint holds: 37 | * 38 | * N >= M*(1 + log2(n)/2) - n + 1 39 | */ 40 | #ifndef MPLITE_H 41 | #define MPLITE_H 42 | 43 | #ifdef _WIN32 44 | #include "pstdint.h" 45 | #else 46 | #include 47 | #endif /* #ifdef _WIN32 */ 48 | 49 | /** 50 | * @brief The function call returns success 51 | */ 52 | #define MPLITE_OK 0 53 | /** 54 | * @brief Invalid parameters are passed to a function 55 | */ 56 | #define MPLITE_ERR_INVPAR -1 57 | /** 58 | * @brief Macro to fix unused parameter compiler warning 59 | */ 60 | #define MPLITE_UNUSED_PARAM(param) (void)(param) 61 | /** 62 | * @brief Maximum size of any allocation is ((1 << @ref MPLITE_LOGMAX) * 63 | * mplite_t.szAtom). Since mplite_t.szAtom is always at least 8 and 64 | * 32-bit integers are used, it is not actually possible to reach this 65 | * limit. 66 | */ 67 | #define MPLITE_LOGMAX 30 68 | /** 69 | * @brief Maximum allocation size of this memory pool library. All allocations 70 | * must be a power of two and must be expressed by a 32-bit signed 71 | * integer. Hence the largest allocation is 0x40000000 or 1073741824. 72 | */ 73 | #define MPLITE_MAX_ALLOC_SIZE 0x40000000 74 | /** 75 | * @brief An indicator that a function is a public API 76 | */ 77 | #define MPLITE_API 78 | 79 | /** 80 | * @brief Lock object to be used in a threadsafe memory pool 81 | */ 82 | typedef struct mplite_lock { 83 | void *arg; /**< Argument to be passed to acquire and release function 84 | pointers */ 85 | int (*acquire)(void *arg); /**< Function pointer to acquire a lock */ 86 | int (*release)(void *arg); /**< Function pointer to release a lock */ 87 | } mplite_lock_t; 88 | 89 | /** 90 | * @brief Memory pool object 91 | */ 92 | typedef struct mplite { 93 | /*------------------------------- 94 | Memory available for allocation 95 | -------------------------------*/ 96 | int szAtom; /**< Smallest possible allocation in bytes */ 97 | int nBlock; /**< Number of szAtom sized blocks in zPool */ 98 | uint8_t *zPool; /**< Memory available to be allocated */ 99 | 100 | mplite_lock_t lock; /**< Lock to control access to the memory allocation 101 | subsystem. */ 102 | 103 | /*---------------------- 104 | Performance statistics 105 | ----------------------*/ 106 | uint64_t nAlloc; /**< Total number of calls to malloc */ 107 | uint64_t totalAlloc; /**< Total of all malloc calls - includes internal 108 | fragmentation */ 109 | uint64_t totalExcess; /**< Total internal fragmentation */ 110 | uint32_t currentOut; /**< Current checkout, including internal 111 | fragmentation */ 112 | uint32_t currentCount; /**< Current number of distinct checkouts */ 113 | uint32_t maxOut; /**< Maximum instantaneous currentOut */ 114 | uint32_t maxCount; /**< Maximum instantaneous currentCount */ 115 | uint32_t maxRequest; /**< Largest allocation (exclusive of internal frag) */ 116 | 117 | int aiFreelist[MPLITE_LOGMAX + 1]; /**< List of free blocks. aiFreelist[0] 118 | is a list of free blocks of size mplite_t.szAtom. aiFreelist[1] holds 119 | blocks of size szAtom * 2 and so forth.*/ 120 | 121 | uint8_t *aCtrl; /**< Space for tracking which blocks are checked out and the 122 | size of each block. One byte per block. */ 123 | } mplite_t; 124 | 125 | /** 126 | * @brief Print string function pointer to be passed to @ref mplite_print_stats 127 | * function. This must be same as stdio's puts function mechanism which 128 | * automatically appends a new line character in every call. 129 | */ 130 | typedef int (*mplite_putsfunc_t)(const char* stats); 131 | 132 | #ifdef __cplusplus 133 | extern "C" { 134 | #endif 135 | 136 | /** 137 | * @brief Initialize the memory pool object. 138 | * @param[in,out] handle Pointer to a @ref mplite_t object which is allocated 139 | * by the caller either from stack, heap, or application's 140 | * memory space. 141 | * @param[in] buf Pointer to a large, contiguous chunk of memory space that 142 | * @ref mplite_t will use to satisfy all of its memory 143 | * allocation needs. This might point to a static array or it 144 | * might be memory obtained from some other application-specific 145 | * mechanism. 146 | * @param[in] buf_size The number of bytes of memory space pointed to by @ref 147 | * buf 148 | * @param[in] min_alloc Minimum size of an allocation. Any call to @ref 149 | * mplite_malloc where nBytes is less than min_alloc will 150 | * be rounded up to min_alloc. min_alloc must be a power of 151 | * two. 152 | * @param[in] lock Pointer to a lock object to control access to the memory 153 | * allocation subsystem of @ref mplite_t object. If this is 154 | * @ref NULL, @ref mplite_t will be non-threadsafe and can only 155 | * be safely used by a single thread. It is safe to allocate 156 | * this in stack because it will be copied to @ref mplite_t 157 | * object. 158 | * @return @ref MPLITE_OK on success and @ref MPLITE_ERR_INVPAR on invalid 159 | * parameters error. 160 | */ 161 | MPLITE_API int mplite_init(mplite_t *handle, const void *buf, 162 | const int buf_size, const int min_alloc, 163 | const mplite_lock_t *lock); 164 | 165 | /** 166 | * @brief Allocate bytes of memory 167 | * @param[in,out] handle Pointer to an initialized @ref mplite_t object 168 | * @param[in] nBytes Number of bytes to allocate 169 | * @return Non-NULL on success, NULL otherwise 170 | */ 171 | MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes); 172 | 173 | /** 174 | * @brief Free memory 175 | * @param[in,out] handle Pointer to an initialized @ref mplite_t object 176 | * @param[in] pPrior Allocated buffer 177 | */ 178 | MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior); 179 | 180 | /** 181 | * @brief Change the size of an existing memory allocation. 182 | * @param[in,out] handle Pointer to an initialized @ref mplite_t object 183 | * @param[in] pPrior Existing allocated memory 184 | * @param[in] nBytes Size of the new memory allocation. This is always a value 185 | * obtained from a prior call to mplite_roundup(). Hence, 186 | * this is always a non-negative power of two. If nBytes == 0 187 | * that means that an oversize allocation (an allocation 188 | * larger than @ref MPLITE_MAX_ALLOC_SIZE) was requested and 189 | * this routine should return NULL without freeing pPrior. 190 | * @return Non-NULL on success, NULL otherwise 191 | */ 192 | MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior, 193 | const int nBytes); 194 | 195 | /** 196 | * @brief Round up a request size to the next valid allocation size. 197 | * @param[in,out] handle Pointer to an initialized @ref mplite_t object 198 | * @param[in] n Request size 199 | * @return Positive non-zero value if the size can be allocated or zero if the 200 | * allocation is too large to be handled. 201 | */ 202 | MPLITE_API int mplite_roundup(mplite_t *handle, const int n); 203 | 204 | /** 205 | * @brief Print the statistics of the memory pool object 206 | * @param[in,out] handle Pointer to an initialized @ref mplite_t object 207 | * @param[in] logfunc Non-NULL log function of the caller. Refer to 208 | * @ref mplite_logfunc_t for the prototype of this function. 209 | */ 210 | MPLITE_API void mplite_print_stats(const mplite_t * const handle, 211 | const mplite_putsfunc_t logfunc); 212 | 213 | /** 214 | * @brief Macro to return the number of times mplite_malloc() has been called. 215 | */ 216 | #define mplite_alloc_count(handle) (((handle) != NULL)? (handle)->nAlloc : 0) 217 | 218 | #ifdef __cplusplus 219 | } 220 | #endif 221 | 222 | #endif /* #ifndef MPLITE_H */ 223 | -------------------------------------------------------------------------------- /include/mplite/pstdint.h: -------------------------------------------------------------------------------- 1 | /* A portable stdint.h 2 | **************************************************************************** 3 | * BSD License: 4 | **************************************************************************** 5 | * 6 | * Copyright (c) 2005-2007 Paul Hsieh 7 | * All rights reserved. 8 | * 9 | * Redistribution and use in source and binary forms, with or without 10 | * modification, are permitted provided that the following conditions 11 | * are met: 12 | * 13 | * 1. Redistributions of source code must retain the above copyright 14 | * notice, this list of conditions and the following disclaimer. 15 | * 2. Redistributions in binary form must reproduce the above copyright 16 | * notice, this list of conditions and the following disclaimer in the 17 | * documentation and/or other materials provided with the distribution. 18 | * 3. The name of the author may not be used to endorse or promote products 19 | * derived from this software without specific prior written permission. 20 | * 21 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 23 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 24 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 25 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 26 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 30 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 | * 32 | **************************************************************************** 33 | * 34 | * Version 0.1.11 35 | * 36 | * The ANSI C standard committee, for the C99 standard, specified the 37 | * inclusion of a new standard include file called stdint.h. This is 38 | * a very useful and long desired include file which contains several 39 | * very precise definitions for integer scalar types that is 40 | * critically important for making portable several classes of 41 | * applications including cryptography, hashing, variable length 42 | * integer libraries and so on. But for most developers its likely 43 | * useful just for programming sanity. 44 | * 45 | * The problem is that most compiler vendors have decided not to 46 | * implement the C99 standard, and the next C++ language standard 47 | * (which has a lot more mindshare these days) will be a long time in 48 | * coming and its unknown whether or not it will include stdint.h or 49 | * how much adoption it will have. Either way, it will be a long time 50 | * before all compilers come with a stdint.h and it also does nothing 51 | * for the extremely large number of compilers available today which 52 | * do not include this file, or anything comparable to it. 53 | * 54 | * So that's what this file is all about. Its an attempt to build a 55 | * single universal include file that works on as many platforms as 56 | * possible to deliver what stdint.h is supposed to. A few things 57 | * that should be noted about this file: 58 | * 59 | * 1) It is not guaranteed to be portable and/or present an identical 60 | * interface on all platforms. The extreme variability of the 61 | * ANSI C standard makes this an impossibility right from the 62 | * very get go. Its really only meant to be useful for the vast 63 | * majority of platforms that possess the capability of 64 | * implementing usefully and precisely defined, standard sized 65 | * integer scalars. Systems which are not intrinsically 2s 66 | * complement may produce invalid constants. 67 | * 68 | * 2) There is an unavoidable use of non-reserved symbols. 69 | * 70 | * 3) Other standard include files are invoked. 71 | * 72 | * 4) This file may come in conflict with future platforms that do 73 | * include stdint.h. The hope is that one or the other can be 74 | * used with no real difference. 75 | * 76 | * 5) In the current verison, if your platform can't represent 77 | * int32_t, int16_t and int8_t, it just dumps out with a compiler 78 | * error. 79 | * 80 | * 6) 64 bit integers may or may not be defined. Test for their 81 | * presence with the test: #ifdef INT64_MAX or #ifdef UINT64_MAX. 82 | * Note that this is different from the C99 specification which 83 | * requires the existence of 64 bit support in the compiler. If 84 | * this is not defined for your platform, yet it is capable of 85 | * dealing with 64 bits then it is because this file has not yet 86 | * been extended to cover all of your system's capabilities. 87 | * 88 | * 7) (u)intptr_t may or may not be defined. Test for its presence 89 | * with the test: #ifdef PTRDIFF_MAX. If this is not defined 90 | * for your platform, then it is because this file has not yet 91 | * been extended to cover all of your system's capabilities, not 92 | * because its optional. 93 | * 94 | * 8) The following might not been defined even if your platform is 95 | * capable of defining it: 96 | * 97 | * WCHAR_MIN 98 | * WCHAR_MAX 99 | * (u)int64_t 100 | * PTRDIFF_MIN 101 | * PTRDIFF_MAX 102 | * (u)intptr_t 103 | * 104 | * 9) The following have not been defined: 105 | * 106 | * WINT_MIN 107 | * WINT_MAX 108 | * 109 | * 10) The criteria for defining (u)int_least(*)_t isn't clear, 110 | * except for systems which don't have a type that precisely 111 | * defined 8, 16, or 32 bit types (which this include file does 112 | * not support anyways). Default definitions have been given. 113 | * 114 | * 11) The criteria for defining (u)int_fast(*)_t isn't something I 115 | * would trust to any particular compiler vendor or the ANSI C 116 | * committee. It is well known that "compatible systems" are 117 | * commonly created that have very different performance 118 | * characteristics from the systems they are compatible with, 119 | * especially those whose vendors make both the compiler and the 120 | * system. Default definitions have been given, but its strongly 121 | * recommended that users never use these definitions for any 122 | * reason (they do *NOT* deliver any serious guarantee of 123 | * improved performance -- not in this file, nor any vendor's 124 | * stdint.h). 125 | * 126 | * 12) The following macros: 127 | * 128 | * PRINTF_INTMAX_MODIFIER 129 | * PRINTF_INT64_MODIFIER 130 | * PRINTF_INT32_MODIFIER 131 | * PRINTF_INT16_MODIFIER 132 | * PRINTF_LEAST64_MODIFIER 133 | * PRINTF_LEAST32_MODIFIER 134 | * PRINTF_LEAST16_MODIFIER 135 | * PRINTF_INTPTR_MODIFIER 136 | * 137 | * are strings which have been defined as the modifiers required 138 | * for the "d", "u" and "x" printf formats to correctly output 139 | * (u)intmax_t, (u)int64_t, (u)int32_t, (u)int16_t, (u)least64_t, 140 | * (u)least32_t, (u)least16_t and (u)intptr_t types respectively. 141 | * PRINTF_INTPTR_MODIFIER is not defined for some systems which 142 | * provide their own stdint.h. PRINTF_INT64_MODIFIER is not 143 | * defined if INT64_MAX is not defined. These are an extension 144 | * beyond what C99 specifies must be in stdint.h. 145 | * 146 | * In addition, the following macros are defined: 147 | * 148 | * PRINTF_INTMAX_HEX_WIDTH 149 | * PRINTF_INT64_HEX_WIDTH 150 | * PRINTF_INT32_HEX_WIDTH 151 | * PRINTF_INT16_HEX_WIDTH 152 | * PRINTF_INT8_HEX_WIDTH 153 | * PRINTF_INTMAX_DEC_WIDTH 154 | * PRINTF_INT64_DEC_WIDTH 155 | * PRINTF_INT32_DEC_WIDTH 156 | * PRINTF_INT16_DEC_WIDTH 157 | * PRINTF_INT8_DEC_WIDTH 158 | * 159 | * Which specifies the maximum number of characters required to 160 | * print the number of that type in either hexadecimal or decimal. 161 | * These are an extension beyond what C99 specifies must be in 162 | * stdint.h. 163 | * 164 | * Compilers tested (all with 0 warnings at their highest respective 165 | * settings): Borland Turbo C 2.0, WATCOM C/C++ 11.0 (16 bits and 32 166 | * bits), Microsoft Visual C++ 6.0 (32 bit), Microsoft Visual Studio 167 | * .net (VC7), Intel C++ 4.0, GNU gcc v3.3.3 168 | * 169 | * This file should be considered a work in progress. Suggestions for 170 | * improvements, especially those which increase coverage are strongly 171 | * encouraged. 172 | * 173 | * Acknowledgements 174 | * 175 | * The following people have made significant contributions to the 176 | * development and testing of this file: 177 | * 178 | * Chris Howie 179 | * John Steele Scott 180 | * Dave Thorup 181 | * 182 | */ 183 | 184 | #include 185 | #include 186 | #include 187 | 188 | /* 189 | * For gcc with _STDINT_H, fill in the PRINTF_INT*_MODIFIER macros, and 190 | * do nothing else. On the Mac OS X version of gcc this is _STDINT_H_. 191 | */ 192 | 193 | #if ((defined(__STDC__) && __STDC__ && __STDC_VERSION__ >= 199901L) || (defined (__WATCOMC__) && (defined (_STDINT_H_INCLUDED) || __WATCOMC__ >= 1250)) || (defined(__GNUC__) && (defined(_STDINT_H) || defined(_STDINT_H_)) )) && !defined (_PSTDINT_H_INCLUDED) 194 | #include 195 | #define _PSTDINT_H_INCLUDED 196 | # ifndef PRINTF_INT64_MODIFIER 197 | # define PRINTF_INT64_MODIFIER "ll" 198 | # endif 199 | # ifndef PRINTF_INT32_MODIFIER 200 | # define PRINTF_INT32_MODIFIER "l" 201 | # endif 202 | # ifndef PRINTF_INT16_MODIFIER 203 | # define PRINTF_INT16_MODIFIER "h" 204 | # endif 205 | # ifndef PRINTF_INTMAX_MODIFIER 206 | # define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER 207 | # endif 208 | # ifndef PRINTF_INT64_HEX_WIDTH 209 | # define PRINTF_INT64_HEX_WIDTH "16" 210 | # endif 211 | # ifndef PRINTF_INT32_HEX_WIDTH 212 | # define PRINTF_INT32_HEX_WIDTH "8" 213 | # endif 214 | # ifndef PRINTF_INT16_HEX_WIDTH 215 | # define PRINTF_INT16_HEX_WIDTH "4" 216 | # endif 217 | # ifndef PRINTF_INT8_HEX_WIDTH 218 | # define PRINTF_INT8_HEX_WIDTH "2" 219 | # endif 220 | # ifndef PRINTF_INT64_DEC_WIDTH 221 | # define PRINTF_INT64_DEC_WIDTH "20" 222 | # endif 223 | # ifndef PRINTF_INT32_DEC_WIDTH 224 | # define PRINTF_INT32_DEC_WIDTH "10" 225 | # endif 226 | # ifndef PRINTF_INT16_DEC_WIDTH 227 | # define PRINTF_INT16_DEC_WIDTH "5" 228 | # endif 229 | # ifndef PRINTF_INT8_DEC_WIDTH 230 | # define PRINTF_INT8_DEC_WIDTH "3" 231 | # endif 232 | # ifndef PRINTF_INTMAX_HEX_WIDTH 233 | # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH 234 | # endif 235 | # ifndef PRINTF_INTMAX_DEC_WIDTH 236 | # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH 237 | # endif 238 | 239 | /* 240 | * Something really weird is going on with Open Watcom. Just pull some of 241 | * these duplicated definitions from Open Watcom's stdint.h file for now. 242 | */ 243 | 244 | # if defined (__WATCOMC__) && __WATCOMC__ >= 1250 245 | # if !defined (INT64_C) 246 | # define INT64_C(x) (x + (INT64_MAX - INT64_MAX)) 247 | # endif 248 | # if !defined (UINT64_C) 249 | # define UINT64_C(x) (x + (UINT64_MAX - UINT64_MAX)) 250 | # endif 251 | # if !defined (INT32_C) 252 | # define INT32_C(x) (x + (INT32_MAX - INT32_MAX)) 253 | # endif 254 | # if !defined (UINT32_C) 255 | # define UINT32_C(x) (x + (UINT32_MAX - UINT32_MAX)) 256 | # endif 257 | # if !defined (INT16_C) 258 | # define INT16_C(x) (x) 259 | # endif 260 | # if !defined (UINT16_C) 261 | # define UINT16_C(x) (x) 262 | # endif 263 | # if !defined (INT8_C) 264 | # define INT8_C(x) (x) 265 | # endif 266 | # if !defined (UINT8_C) 267 | # define UINT8_C(x) (x) 268 | # endif 269 | # if !defined (UINT64_MAX) 270 | # define UINT64_MAX 18446744073709551615ULL 271 | # endif 272 | # if !defined (INT64_MAX) 273 | # define INT64_MAX 9223372036854775807LL 274 | # endif 275 | # if !defined (UINT32_MAX) 276 | # define UINT32_MAX 4294967295UL 277 | # endif 278 | # if !defined (INT32_MAX) 279 | # define INT32_MAX 2147483647L 280 | # endif 281 | # if !defined (INTMAX_MAX) 282 | # define INTMAX_MAX INT64_MAX 283 | # endif 284 | # if !defined (INTMAX_MIN) 285 | # define INTMAX_MIN INT64_MIN 286 | # endif 287 | # endif 288 | #endif 289 | 290 | #ifndef _PSTDINT_H_INCLUDED 291 | #define _PSTDINT_H_INCLUDED 292 | 293 | #ifndef SIZE_MAX 294 | # define SIZE_MAX (~(size_t)0) 295 | #endif 296 | 297 | /* 298 | * Deduce the type assignments from limits.h under the assumption that 299 | * integer sizes in bits are powers of 2, and follow the ANSI 300 | * definitions. 301 | */ 302 | 303 | #ifndef UINT8_MAX 304 | # define UINT8_MAX 0xff 305 | #endif 306 | #ifndef uint8_t 307 | # if (UCHAR_MAX == UINT8_MAX) || defined (S_SPLINT_S) 308 | typedef unsigned char uint8_t; 309 | # define UINT8_C(v) ((uint8_t) v) 310 | # else 311 | # error "Platform not supported" 312 | # endif 313 | #endif 314 | 315 | #ifndef INT8_MAX 316 | # define INT8_MAX 0x7f 317 | #endif 318 | #ifndef INT8_MIN 319 | # define INT8_MIN INT8_C(0x80) 320 | #endif 321 | #ifndef int8_t 322 | # if (SCHAR_MAX == INT8_MAX) || defined (S_SPLINT_S) 323 | typedef signed char int8_t; 324 | # define INT8_C(v) ((int8_t) v) 325 | # else 326 | # error "Platform not supported" 327 | # endif 328 | #endif 329 | 330 | #ifndef UINT16_MAX 331 | # define UINT16_MAX 0xffff 332 | #endif 333 | #ifndef uint16_t 334 | #if (UINT_MAX == UINT16_MAX) || defined (S_SPLINT_S) 335 | typedef unsigned int uint16_t; 336 | # ifndef PRINTF_INT16_MODIFIER 337 | # define PRINTF_INT16_MODIFIER "" 338 | # endif 339 | # define UINT16_C(v) ((uint16_t) (v)) 340 | #elif (USHRT_MAX == UINT16_MAX) 341 | typedef unsigned short uint16_t; 342 | # define UINT16_C(v) ((uint16_t) (v)) 343 | # ifndef PRINTF_INT16_MODIFIER 344 | # define PRINTF_INT16_MODIFIER "h" 345 | # endif 346 | #else 347 | #error "Platform not supported" 348 | #endif 349 | #endif 350 | 351 | #ifndef INT16_MAX 352 | # define INT16_MAX 0x7fff 353 | #endif 354 | #ifndef INT16_MIN 355 | # define INT16_MIN INT16_C(0x8000) 356 | #endif 357 | #ifndef int16_t 358 | #if (INT_MAX == INT16_MAX) || defined (S_SPLINT_S) 359 | typedef signed int int16_t; 360 | # define INT16_C(v) ((int16_t) (v)) 361 | # ifndef PRINTF_INT16_MODIFIER 362 | # define PRINTF_INT16_MODIFIER "" 363 | # endif 364 | #elif (SHRT_MAX == INT16_MAX) 365 | typedef signed short int16_t; 366 | # define INT16_C(v) ((int16_t) (v)) 367 | # ifndef PRINTF_INT16_MODIFIER 368 | # define PRINTF_INT16_MODIFIER "h" 369 | # endif 370 | #else 371 | #error "Platform not supported" 372 | #endif 373 | #endif 374 | 375 | #ifndef UINT32_MAX 376 | # define UINT32_MAX (0xffffffffUL) 377 | #endif 378 | #ifndef uint32_t 379 | #if (ULONG_MAX == UINT32_MAX) || defined (S_SPLINT_S) 380 | typedef unsigned long uint32_t; 381 | # define UINT32_C(v) v ## UL 382 | # ifndef PRINTF_INT32_MODIFIER 383 | # define PRINTF_INT32_MODIFIER "l" 384 | # endif 385 | #elif (UINT_MAX == UINT32_MAX) 386 | typedef unsigned int uint32_t; 387 | # ifndef PRINTF_INT32_MODIFIER 388 | # define PRINTF_INT32_MODIFIER "" 389 | # endif 390 | # define UINT32_C(v) v ## U 391 | #elif (USHRT_MAX == UINT32_MAX) 392 | typedef unsigned short uint32_t; 393 | # define UINT32_C(v) ((unsigned short) (v)) 394 | # ifndef PRINTF_INT32_MODIFIER 395 | # define PRINTF_INT32_MODIFIER "" 396 | # endif 397 | #else 398 | #error "Platform not supported" 399 | #endif 400 | #endif 401 | 402 | #ifndef INT32_MAX 403 | # define INT32_MAX (0x7fffffffL) 404 | #endif 405 | #ifndef INT32_MIN 406 | # define INT32_MIN INT32_C(0x80000000) 407 | #endif 408 | #ifndef int32_t 409 | #if (LONG_MAX == INT32_MAX) || defined (S_SPLINT_S) 410 | typedef signed long int32_t; 411 | # define INT32_C(v) v ## L 412 | # ifndef PRINTF_INT32_MODIFIER 413 | # define PRINTF_INT32_MODIFIER "l" 414 | # endif 415 | #elif (INT_MAX == INT32_MAX) 416 | typedef signed int int32_t; 417 | # define INT32_C(v) v 418 | # ifndef PRINTF_INT32_MODIFIER 419 | # define PRINTF_INT32_MODIFIER "" 420 | # endif 421 | #elif (SHRT_MAX == INT32_MAX) 422 | typedef signed short int32_t; 423 | # define INT32_C(v) ((short) (v)) 424 | # ifndef PRINTF_INT32_MODIFIER 425 | # define PRINTF_INT32_MODIFIER "" 426 | # endif 427 | #else 428 | #error "Platform not supported" 429 | #endif 430 | #endif 431 | 432 | /* 433 | * The macro stdint_int64_defined is temporarily used to record 434 | * whether or not 64 integer support is available. It must be 435 | * defined for any 64 integer extensions for new platforms that are 436 | * added. 437 | */ 438 | 439 | #undef stdint_int64_defined 440 | #if (defined(__STDC__) && defined(__STDC_VERSION__)) || defined (S_SPLINT_S) 441 | # if (__STDC__ && __STDC_VERSION >= 199901L) || defined (S_SPLINT_S) 442 | # define stdint_int64_defined 443 | typedef long long int64_t; 444 | typedef unsigned long long uint64_t; 445 | # define UINT64_C(v) v ## ULL 446 | # define INT64_C(v) v ## LL 447 | # ifndef PRINTF_INT64_MODIFIER 448 | # define PRINTF_INT64_MODIFIER "ll" 449 | # endif 450 | # endif 451 | #endif 452 | 453 | #if !defined (stdint_int64_defined) 454 | # if defined(__GNUC__) 455 | # define stdint_int64_defined 456 | __extension__ typedef long long int64_t; 457 | __extension__ typedef unsigned long long uint64_t; 458 | # define UINT64_C(v) v ## ULL 459 | # define INT64_C(v) v ## LL 460 | # ifndef PRINTF_INT64_MODIFIER 461 | # define PRINTF_INT64_MODIFIER "ll" 462 | # endif 463 | # elif defined(__MWERKS__) || defined (__SUNPRO_C) || defined (__SUNPRO_CC) || defined (__APPLE_CC__) || defined (_LONG_LONG) || defined (_CRAYC) || defined (S_SPLINT_S) 464 | # define stdint_int64_defined 465 | typedef long long int64_t; 466 | typedef unsigned long long uint64_t; 467 | # define UINT64_C(v) v ## ULL 468 | # define INT64_C(v) v ## LL 469 | # ifndef PRINTF_INT64_MODIFIER 470 | # define PRINTF_INT64_MODIFIER "ll" 471 | # endif 472 | # elif (defined(__WATCOMC__) && defined(__WATCOM_INT64__)) || (defined(_MSC_VER) && _INTEGRAL_MAX_BITS >= 64) || (defined (__BORLANDC__) && __BORLANDC__ > 0x460) || defined (__alpha) || defined (__DECC) 473 | # define stdint_int64_defined 474 | typedef __int64 int64_t; 475 | typedef unsigned __int64 uint64_t; 476 | # define UINT64_C(v) v ## UI64 477 | # define INT64_C(v) v ## I64 478 | # ifndef PRINTF_INT64_MODIFIER 479 | # define PRINTF_INT64_MODIFIER "I64" 480 | # endif 481 | # endif 482 | #endif 483 | 484 | #if !defined (LONG_LONG_MAX) && defined (INT64_C) 485 | # define LONG_LONG_MAX INT64_C (9223372036854775807) 486 | #endif 487 | #ifndef ULONG_LONG_MAX 488 | # define ULONG_LONG_MAX UINT64_C (18446744073709551615) 489 | #endif 490 | 491 | #if !defined (INT64_MAX) && defined (INT64_C) 492 | # define INT64_MAX INT64_C (9223372036854775807) 493 | #endif 494 | #if !defined (INT64_MIN) && defined (INT64_C) 495 | # define INT64_MIN INT64_C (-9223372036854775808) 496 | #endif 497 | #if !defined (UINT64_MAX) && defined (INT64_C) 498 | # define UINT64_MAX UINT64_C (18446744073709551615) 499 | #endif 500 | 501 | /* 502 | * Width of hexadecimal for number field. 503 | */ 504 | 505 | #ifndef PRINTF_INT64_HEX_WIDTH 506 | # define PRINTF_INT64_HEX_WIDTH "16" 507 | #endif 508 | #ifndef PRINTF_INT32_HEX_WIDTH 509 | # define PRINTF_INT32_HEX_WIDTH "8" 510 | #endif 511 | #ifndef PRINTF_INT16_HEX_WIDTH 512 | # define PRINTF_INT16_HEX_WIDTH "4" 513 | #endif 514 | #ifndef PRINTF_INT8_HEX_WIDTH 515 | # define PRINTF_INT8_HEX_WIDTH "2" 516 | #endif 517 | 518 | #ifndef PRINTF_INT64_DEC_WIDTH 519 | # define PRINTF_INT64_DEC_WIDTH "20" 520 | #endif 521 | #ifndef PRINTF_INT32_DEC_WIDTH 522 | # define PRINTF_INT32_DEC_WIDTH "10" 523 | #endif 524 | #ifndef PRINTF_INT16_DEC_WIDTH 525 | # define PRINTF_INT16_DEC_WIDTH "5" 526 | #endif 527 | #ifndef PRINTF_INT8_DEC_WIDTH 528 | # define PRINTF_INT8_DEC_WIDTH "3" 529 | #endif 530 | 531 | /* 532 | * Ok, lets not worry about 128 bit integers for now. Moore's law says 533 | * we don't need to worry about that until about 2040 at which point 534 | * we'll have bigger things to worry about. 535 | */ 536 | 537 | #ifdef stdint_int64_defined 538 | typedef int64_t intmax_t; 539 | typedef uint64_t uintmax_t; 540 | # define INTMAX_MAX INT64_MAX 541 | # define INTMAX_MIN INT64_MIN 542 | # define UINTMAX_MAX UINT64_MAX 543 | # define UINTMAX_C(v) UINT64_C(v) 544 | # define INTMAX_C(v) INT64_C(v) 545 | # ifndef PRINTF_INTMAX_MODIFIER 546 | # define PRINTF_INTMAX_MODIFIER PRINTF_INT64_MODIFIER 547 | # endif 548 | # ifndef PRINTF_INTMAX_HEX_WIDTH 549 | # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT64_HEX_WIDTH 550 | # endif 551 | # ifndef PRINTF_INTMAX_DEC_WIDTH 552 | # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT64_DEC_WIDTH 553 | # endif 554 | #else 555 | typedef int32_t intmax_t; 556 | typedef uint32_t uintmax_t; 557 | # define INTMAX_MAX INT32_MAX 558 | # define UINTMAX_MAX UINT32_MAX 559 | # define UINTMAX_C(v) UINT32_C(v) 560 | # define INTMAX_C(v) INT32_C(v) 561 | # ifndef PRINTF_INTMAX_MODIFIER 562 | # define PRINTF_INTMAX_MODIFIER PRINTF_INT32_MODIFIER 563 | # endif 564 | # ifndef PRINTF_INTMAX_HEX_WIDTH 565 | # define PRINTF_INTMAX_HEX_WIDTH PRINTF_INT32_HEX_WIDTH 566 | # endif 567 | # ifndef PRINTF_INTMAX_DEC_WIDTH 568 | # define PRINTF_INTMAX_DEC_WIDTH PRINTF_INT32_DEC_WIDTH 569 | # endif 570 | #endif 571 | 572 | /* 573 | * Because this file currently only supports platforms which have 574 | * precise powers of 2 as bit sizes for the default integers, the 575 | * least definitions are all trivial. Its possible that a future 576 | * version of this file could have different definitions. 577 | */ 578 | 579 | #ifndef stdint_least_defined 580 | typedef int8_t int_least8_t; 581 | typedef uint8_t uint_least8_t; 582 | typedef int16_t int_least16_t; 583 | typedef uint16_t uint_least16_t; 584 | typedef int32_t int_least32_t; 585 | typedef uint32_t uint_least32_t; 586 | # define PRINTF_LEAST32_MODIFIER PRINTF_INT32_MODIFIER 587 | # define PRINTF_LEAST16_MODIFIER PRINTF_INT16_MODIFIER 588 | # define UINT_LEAST8_MAX UINT8_MAX 589 | # define INT_LEAST8_MAX INT8_MAX 590 | # define UINT_LEAST16_MAX UINT16_MAX 591 | # define INT_LEAST16_MAX INT16_MAX 592 | # define UINT_LEAST32_MAX UINT32_MAX 593 | # define INT_LEAST32_MAX INT32_MAX 594 | # define INT_LEAST8_MIN INT8_MIN 595 | # define INT_LEAST16_MIN INT16_MIN 596 | # define INT_LEAST32_MIN INT32_MIN 597 | # ifdef stdint_int64_defined 598 | typedef int64_t int_least64_t; 599 | typedef uint64_t uint_least64_t; 600 | # define PRINTF_LEAST64_MODIFIER PRINTF_INT64_MODIFIER 601 | # define UINT_LEAST64_MAX UINT64_MAX 602 | # define INT_LEAST64_MAX INT64_MAX 603 | # define INT_LEAST64_MIN INT64_MIN 604 | # endif 605 | #endif 606 | #undef stdint_least_defined 607 | 608 | /* 609 | * The ANSI C committee pretending to know or specify anything about 610 | * performance is the epitome of misguided arrogance. The mandate of 611 | * this file is to *ONLY* ever support that absolute minimum 612 | * definition of the fast integer types, for compatibility purposes. 613 | * No extensions, and no attempt to suggest what may or may not be a 614 | * faster integer type will ever be made in this file. Developers are 615 | * warned to stay away from these types when using this or any other 616 | * stdint.h. 617 | */ 618 | 619 | typedef int_least8_t int_fast8_t; 620 | typedef uint_least8_t uint_fast8_t; 621 | typedef int_least16_t int_fast16_t; 622 | typedef uint_least16_t uint_fast16_t; 623 | typedef int_least32_t int_fast32_t; 624 | typedef uint_least32_t uint_fast32_t; 625 | #define UINT_FAST8_MAX UINT_LEAST8_MAX 626 | #define INT_FAST8_MAX INT_LEAST8_MAX 627 | #define UINT_FAST16_MAX UINT_LEAST16_MAX 628 | #define INT_FAST16_MAX INT_LEAST16_MAX 629 | #define UINT_FAST32_MAX UINT_LEAST32_MAX 630 | #define INT_FAST32_MAX INT_LEAST32_MAX 631 | #define INT_FAST8_MIN INT_LEAST8_MIN 632 | #define INT_FAST16_MIN INT_LEAST16_MIN 633 | #define INT_FAST32_MIN INT_LEAST32_MIN 634 | #ifdef stdint_int64_defined 635 | typedef int_least64_t int_fast64_t; 636 | typedef uint_least64_t uint_fast64_t; 637 | # define UINT_FAST64_MAX UINT_LEAST64_MAX 638 | # define INT_FAST64_MAX INT_LEAST64_MAX 639 | # define INT_FAST64_MIN INT_LEAST64_MIN 640 | #endif 641 | 642 | #undef stdint_int64_defined 643 | 644 | /* 645 | * Whatever piecemeal, per compiler thing we can do about the wchar_t 646 | * type limits. 647 | */ 648 | 649 | #if defined(__WATCOMC__) || defined(_MSC_VER) || defined (__GNUC__) 650 | # include 651 | # ifndef WCHAR_MIN 652 | # define WCHAR_MIN 0 653 | # endif 654 | # ifndef WCHAR_MAX 655 | # define WCHAR_MAX ((wchar_t)-1) 656 | # endif 657 | #endif 658 | 659 | /* 660 | * Whatever piecemeal, per compiler/platform thing we can do about the 661 | * (u)intptr_t types and limits. 662 | */ 663 | 664 | #if defined (_MSC_VER) && defined (_UINTPTR_T_DEFINED) 665 | # define STDINT_H_UINTPTR_T_DEFINED 666 | #endif 667 | 668 | #ifndef STDINT_H_UINTPTR_T_DEFINED 669 | # if defined (__alpha__) || defined (__ia64__) || defined (__x86_64__) || defined (_WIN64) 670 | # define stdint_intptr_bits 64 671 | # elif defined (__WATCOMC__) || defined (__TURBOC__) 672 | # if defined(__TINY__) || defined(__SMALL__) || defined(__MEDIUM__) 673 | # define stdint_intptr_bits 16 674 | # else 675 | # define stdint_intptr_bits 32 676 | # endif 677 | # elif defined (__i386__) || defined (_WIN32) || defined (WIN32) 678 | # define stdint_intptr_bits 32 679 | # elif defined (__INTEL_COMPILER) 680 | /* TODO -- what will Intel do about x86-64? */ 681 | # endif 682 | 683 | # ifdef stdint_intptr_bits 684 | # define stdint_intptr_glue3_i(a,b,c) a##b##c 685 | # define stdint_intptr_glue3(a,b,c) stdint_intptr_glue3_i(a,b,c) 686 | # ifndef PRINTF_INTPTR_MODIFIER 687 | # define PRINTF_INTPTR_MODIFIER stdint_intptr_glue3(PRINTF_INT,stdint_intptr_bits,_MODIFIER) 688 | # endif 689 | # ifndef PTRDIFF_MAX 690 | # define PTRDIFF_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) 691 | # endif 692 | # ifndef PTRDIFF_MIN 693 | # define PTRDIFF_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) 694 | # endif 695 | # ifndef UINTPTR_MAX 696 | # define UINTPTR_MAX stdint_intptr_glue3(UINT,stdint_intptr_bits,_MAX) 697 | # endif 698 | # ifndef INTPTR_MAX 699 | # define INTPTR_MAX stdint_intptr_glue3(INT,stdint_intptr_bits,_MAX) 700 | # endif 701 | # ifndef INTPTR_MIN 702 | # define INTPTR_MIN stdint_intptr_glue3(INT,stdint_intptr_bits,_MIN) 703 | # endif 704 | # ifndef INTPTR_C 705 | # define INTPTR_C(x) stdint_intptr_glue3(INT,stdint_intptr_bits,_C)(x) 706 | # endif 707 | # ifndef UINTPTR_C 708 | # define UINTPTR_C(x) stdint_intptr_glue3(UINT,stdint_intptr_bits,_C)(x) 709 | # endif 710 | typedef stdint_intptr_glue3(uint,stdint_intptr_bits,_t) uintptr_t; 711 | typedef stdint_intptr_glue3( int,stdint_intptr_bits,_t) intptr_t; 712 | # else 713 | /* TODO -- This following is likely wrong for some platforms, and does 714 | nothing for the definition of uintptr_t. */ 715 | typedef ptrdiff_t intptr_t; 716 | # endif 717 | # define STDINT_H_UINTPTR_T_DEFINED 718 | #endif 719 | 720 | /* 721 | * Assumes sig_atomic_t is signed and we have a 2s complement machine. 722 | */ 723 | 724 | #ifndef SIG_ATOMIC_MAX 725 | # define SIG_ATOMIC_MAX ((((sig_atomic_t) 1) << (sizeof (sig_atomic_t)*CHAR_BIT-1)) - 1) 726 | #endif 727 | 728 | #endif 729 | 730 | #if defined (__TEST_PSTDINT_FOR_CORRECTNESS) 731 | 732 | /* 733 | * Please compile with the maximum warning settings to make sure macros are not 734 | * defined more than once. 735 | */ 736 | 737 | #include 738 | #include 739 | #include 740 | 741 | #define glue3_aux(x,y,z) x ## y ## z 742 | #define glue3(x,y,z) glue3_aux(x,y,z) 743 | 744 | #define DECLU(bits) glue3(uint,bits,_t) glue3(u,bits,=) glue3(UINT,bits,_C) (0); 745 | #define DECLI(bits) glue3(int,bits,_t) glue3(i,bits,=) glue3(INT,bits,_C) (0); 746 | 747 | #define DECL(us,bits) glue3(DECL,us,) (bits) 748 | 749 | #define TESTUMAX(bits) glue3(u,bits,=) glue3(~,u,bits); if (glue3(UINT,bits,_MAX) glue3(!=,u,bits)) printf ("Something wrong with UINT%d_MAX\n", bits) 750 | 751 | int main () { 752 | DECL(I,8) 753 | DECL(U,8) 754 | DECL(I,16) 755 | DECL(U,16) 756 | DECL(I,32) 757 | DECL(U,32) 758 | #ifdef INT64_MAX 759 | DECL(I,64) 760 | DECL(U,64) 761 | #endif 762 | intmax_t imax = INTMAX_C(0); 763 | uintmax_t umax = UINTMAX_C(0); 764 | char str0[256], str1[256]; 765 | 766 | sprintf (str0, "%d %x\n", 0, ~0); 767 | 768 | sprintf (str1, "%d %x\n", i8, ~0); 769 | if (0 != strcmp (str0, str1)) printf ("Something wrong with i8 : %s\n", str1); 770 | sprintf (str1, "%u %x\n", u8, ~0); 771 | if (0 != strcmp (str0, str1)) printf ("Something wrong with u8 : %s\n", str1); 772 | sprintf (str1, "%d %x\n", i16, ~0); 773 | if (0 != strcmp (str0, str1)) printf ("Something wrong with i16 : %s\n", str1); 774 | sprintf (str1, "%u %x\n", u16, ~0); 775 | if (0 != strcmp (str0, str1)) printf ("Something wrong with u16 : %s\n", str1); 776 | sprintf (str1, "%" PRINTF_INT32_MODIFIER "d %x\n", i32, ~0); 777 | if (0 != strcmp (str0, str1)) printf ("Something wrong with i32 : %s\n", str1); 778 | sprintf (str1, "%" PRINTF_INT32_MODIFIER "u %x\n", u32, ~0); 779 | if (0 != strcmp (str0, str1)) printf ("Something wrong with u32 : %s\n", str1); 780 | #ifdef INT64_MAX 781 | sprintf (str1, "%" PRINTF_INT64_MODIFIER "d %x\n", i64, ~0); 782 | if (0 != strcmp (str0, str1)) printf ("Something wrong with i64 : %s\n", str1); 783 | #endif 784 | sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "d %x\n", imax, ~0); 785 | if (0 != strcmp (str0, str1)) printf ("Something wrong with imax : %s\n", str1); 786 | sprintf (str1, "%" PRINTF_INTMAX_MODIFIER "u %x\n", umax, ~0); 787 | if (0 != strcmp (str0, str1)) printf ("Something wrong with umax : %s\n", str1); 788 | 789 | TESTUMAX(8); 790 | TESTUMAX(16); 791 | TESTUMAX(32); 792 | #ifdef INT64_MAX 793 | TESTUMAX(64); 794 | #endif 795 | 796 | return EXIT_SUCCESS; 797 | } 798 | 799 | #endif 800 | -------------------------------------------------------------------------------- /include/shalloc/shalloc.h: -------------------------------------------------------------------------------- 1 | #ifndef SHALLOC_H 2 | #define SHALLOC_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | /* 13 | * Remove the definition of mmap_flags from magic_structs.h 14 | */ 15 | #ifdef _MAGIC_STRUCTS_H 16 | #undef mmap_flags 17 | #endif 18 | /* 19 | * A shadow allocator which supports a number of independent heaps in a 20 | * "shadow" space allocated in a fixed (and reserved) address space region. 21 | * Relies on independent buffer-based allocators to manage individual heaps 22 | * and regions within heaps. 23 | */ 24 | 25 | /* General definitions. */ 26 | #define SHALLOC_PAGE_SIZE ((size_t) 0x1000) 27 | 28 | #ifndef SHALLOC_PRIVATE_HEAP_SIZE 29 | # define SHALLOC_PRIVATE_HEAP_SIZE (SHALLOC_PAGE_SIZE) 30 | #endif 31 | 32 | #ifndef SHALLOC_DEFAULT_MMAP_FLAGS 33 | # define SHALLOC_DEFAULT_MMAP_FLAGS (MAP_ANONYMOUS|MAP_PRIVATE) 34 | #endif 35 | 36 | #ifndef SHALLOC_BASE_ADDR 37 | # ifdef __MINIX 38 | # define SHALLOC_BASE_ADDR ((unsigned) 0xA0000000) 39 | # define SHALLOC_LAST_ADDR ((unsigned) 0xBFFFFFFF) 40 | # else 41 | # define SHALLOC_BASE_ADDR ((unsigned) 0x80000000) 42 | # define SHALLOC_LAST_ADDR ((unsigned) 0xBFFFFFFF) 43 | # endif 44 | #endif 45 | 46 | #ifndef SHALLOC_USE_GUARD_PAGES 47 | # ifdef __MINIX 48 | # define SHALLOC_USE_GUARD_PAGES 0 49 | # else 50 | # define SHALLOC_USE_GUARD_PAGES 1 51 | # endif 52 | #endif 53 | 54 | #define SHALLOC_BASE_SIZE \ 55 | ((size_t)(SHALLOC_LAST_ADDR - SHALLOC_BASE_ADDR + 1)) 56 | #define SHALLOC_SPACE_SIZE (shalloc_space->data.size) 57 | 58 | #define SHALLOC_OFFSET_OF(T,M) ((size_t)(&((T *)0)->M)) 59 | #define SHALLOC_CONTAINER_OF(ptr, type, member) \ 60 | (type *)( (char *)(ptr) - SHALLOC_OFFSET_OF(type,member) ) 61 | 62 | /* Shalloc flags */ 63 | enum shalloc_flags { 64 | HEAP = 0, 65 | NON_RESIZABLE, 66 | ELASTIC, 67 | __NUM_SHALLOC_FLAGS 68 | }; 69 | #define SHALLOC_FLAG(F) (1 << (F)) 70 | 71 | /* Allocator functions. */ 72 | typedef int (*shalloc_create_t)(void* ref); 73 | typedef void (*shalloc_destroy_t)(void* ref); 74 | typedef void* (*shalloc_malloc_t)(void* ref, size_t size); 75 | typedef void (*shalloc_free_t)(void* ref, void *ptr); 76 | typedef void* (*shalloc_calloc_t)(void* ref, size_t nmemb, 77 | size_t size); 78 | 79 | void* gen_memset_calloc(void *ref, size_t nmemb, size_t size); 80 | void gen_empty_destroy(void *ref); 81 | 82 | /* Shadow buffer definitions. */ 83 | enum shalloc_buff_alloc_type { 84 | SHALLOC_BUFF_ALLOC_TYPE_NONE = 0, 85 | SHALLOC_BUFF_ALLOC_TYPE_BUFFER, 86 | SHALLOC_BUFF_ALLOC_TYPE_SIMPLE, 87 | SHALLOC_BUFF_ALLOC_TYPE_MPLITE, 88 | SHALLOC_BUFF_ALLOC_TYPE_NOFREE, 89 | SHALLOC_BUFF_ALLOC_TYPE_SLAB, 90 | __NUM_SHALLOC_BUFF_ALLOC_TYPES 91 | }; 92 | 93 | typedef struct shalloc_buff_op_s { 94 | shalloc_create_t create; 95 | shalloc_destroy_t destroy; 96 | shalloc_malloc_t malloc; 97 | shalloc_free_t free; 98 | shalloc_calloc_t calloc; 99 | } shalloc_buff_op_t; 100 | 101 | typedef struct shalloc_buff_s { 102 | void *start; 103 | void *end; 104 | size_t size; 105 | size_t unused_size; 106 | size_t block_size; 107 | struct shalloc_buff_s *next; 108 | enum shalloc_buff_alloc_type alloc_type; 109 | shalloc_buff_op_t *op; 110 | } shalloc_buff_t; 111 | 112 | #define SHALLOC_BUFF_ALLOC_SIZE(S) ((size_t)(2.1*((double)(S)))) 113 | #define SHALLOC_BUFF_MIN_SIZE (SHALLOC_PAGE_SIZE/4) 114 | #define SHALLOC_IS_BUFF_ADDR(B, A) (((void*)(A)) >= (B)->start && \ 115 | ((void*)(A)) <= (B)->end) 116 | 117 | /* Shadow region definitions. */ 118 | typedef struct shalloc_region_s { 119 | shalloc_buff_t *data_head; 120 | shalloc_buff_t *data_tail; 121 | shalloc_buff_t default_data; 122 | int flags; 123 | struct shalloc_region_s *parent; 124 | } shalloc_region_t; 125 | 126 | typedef struct { 127 | int num_buffs; 128 | size_t tot_buff_size; 129 | size_t last_buff_size; 130 | } shalloc_region_info_t; 131 | 132 | #define SHALLOC_REGION_TYPE_DEFAULT SHALLOC_BUFF_ALLOC_TYPE_NOFREE 133 | #define SHALLOC_REGION_BUFF_SIZE_DEFAULT SHALLOC_PAGE_SIZE 134 | #define SHALLOC_REGION_BUFF_ITER(R,PREV,CURR,DO) do { \ 135 | PREV=CURR=NULL; \ 136 | if((R)->data_head) { \ 137 | while(!(CURR) || (CURR)->next) { \ 138 | PREV = CURR; \ 139 | CURR = !(CURR) ? (R)->data_head : (CURR)->next; \ 140 | DO \ 141 | } \ 142 | } \ 143 | } while(0) 144 | 145 | /* Shadow heap definitions. */ 146 | typedef struct { 147 | shalloc_buff_t base; 148 | shalloc_region_t region; 149 | int inherit_id; 150 | int mmap_flags; 151 | } shalloc_heap_t; 152 | 153 | #define SHALLOC_MAX_INHERIT_HEAPS 10 154 | #define SHALLOC_INHERIT_ID "inherit_id" 155 | #define SHALLOC_MAP_INHERIT 0x0800 156 | #define SHALLOC_GET_EXEC_ENVP() (SHALLOC_CONTROL_DATA->inherit_envp) 157 | 158 | /* Shadow magic info */ 159 | typedef struct { 160 | char *inherit_envp[2]; 161 | char inherit_envp_buff[32]; 162 | int inherit_id; 163 | int num_heaps; 164 | shalloc_heap_t heap_list[SHALLOC_MAX_INHERIT_HEAPS]; 165 | } shalloc_magic_t; 166 | 167 | /* Make SHALLOC_BUFF_ALLOC_TYPE_MPLITE the default heap allocator. 168 | * - SHALLOC_BUFF_ALLOC_TYPE_MPLITE wastes more memory (see MPLITE_MIN_ALLOC) 169 | * - SHALLOC_BUFF_ALLOC_TYPE_SIMPLE seems buggy 170 | * - SHALLOC_BUFF_ALLOC_TYPE_BUFFER has problems with large allocations 171 | */ 172 | #define SHALLOC_HEAP_TYPE_DEFAULT SHALLOC_BUFF_ALLOC_TYPE_MPLITE 173 | 174 | /* Shadow space definitions. */ 175 | typedef struct { 176 | shalloc_buff_t base; 177 | shalloc_buff_t data; 178 | void *magic_control_page; 179 | void *magic_inherit_page; 180 | int num_heaps; 181 | int has_noninherit_heaps; 182 | int mmap_flags; 183 | shalloc_heap_t *priv_heap; 184 | shalloc_buff_op_t buff_ops[__NUM_SHALLOC_BUFF_ALLOC_TYPES]; 185 | } shalloc_space_t; 186 | extern shalloc_space_t *shalloc_space; 187 | extern shalloc_buff_op_t shalloc_space_buff_ops[__NUM_SHALLOC_BUFF_ALLOC_TYPES]; 188 | 189 | #define SHALLOC_IS_SPACE_ADDR(A) SHALLOC_IS_BUFF_ADDR(&shalloc_space->data, A) 190 | 191 | /* Printing functions. */ 192 | #define shalloc_printf printf 193 | 194 | void shalloc_space_print(); 195 | void shalloc_buff_print(shalloc_buff_t *buff); 196 | void shalloc_heap_print(shalloc_heap_t *heap); 197 | void shalloc_region_print(shalloc_region_t *region); 198 | 199 | /* Shalloc allocator interface. */ 200 | void shalloc_buff_reset(shalloc_buff_t* buff); 201 | 202 | shalloc_heap_t* shalloc_heap_create(size_t size, int mmap_flags, 203 | enum shalloc_buff_alloc_type type); 204 | shalloc_region_t* shalloc_heap_to_region(shalloc_heap_t* heap); 205 | shalloc_buff_t* shalloc_heap_to_buff(shalloc_heap_t* heap); 206 | shalloc_heap_t* shalloc_region_to_heap(shalloc_region_t* region); 207 | 208 | shalloc_region_t* shalloc_region_create(shalloc_region_t *region, 209 | size_t init_size, size_t buff_size, size_t block_size, int flags, 210 | enum shalloc_buff_alloc_type type); 211 | void shalloc_region_destroy(shalloc_region_t* region); 212 | void shalloc_region_reset(shalloc_region_t* region); 213 | void shalloc_region_get_info(shalloc_region_t* region, 214 | shalloc_region_info_t *info); 215 | 216 | void* shalloc_malloc(shalloc_region_t *region, size_t size); 217 | void shalloc_free(shalloc_region_t *region, void *ptr); 218 | void* shalloc_calloc(shalloc_region_t *region, size_t nmemb, size_t size); 219 | void* shalloc_orealloc(shalloc_region_t *region, void *ptr, size_t size, 220 | size_t old_size); 221 | 222 | void shalloc_space_init(); 223 | void shalloc_space_close(); 224 | void shalloc_space_freeze(); 225 | #define SHALLOC_INHERIT_DATA (shalloc_space->magic_inherit_page) 226 | #define SHALLOC_CONTROL_DATA ((shalloc_magic_t*)shalloc_space->magic_control_page) 227 | 228 | #endif /* SHALLOC_H */ 229 | 230 | -------------------------------------------------------------------------------- /mplite/mplite.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | /* 9 | ** A minimum allocation is an instance of the following structure. 10 | ** Larger allocations are an array of these structures where the 11 | ** size of the array is a power of 2. 12 | ** 13 | ** The size of this object must be a power of two. That fact is 14 | ** verified in mplite_init(). 15 | */ 16 | typedef struct mplite_link mplite_link_t; 17 | 18 | struct mplite_link { 19 | int next; /* Index of next free chunk */ 20 | int prev; /* Index of previous free chunk */ 21 | }; 22 | 23 | /* 24 | ** Masks used for mplite_t.aCtrl[] elements. 25 | */ 26 | #define MPLITE_CTRL_LOGSIZE 0x1f /* Log2 Size of this block */ 27 | #define MPLITE_CTRL_FREE 0x20 /* True if not checked out */ 28 | 29 | #ifdef _WIN32 30 | #define snprintf(buf, buf_size, format, ...) _snprintf(buf, buf_size, format, ## __VA_ARGS__) 31 | #endif /* #ifdef _WIN32 */ 32 | 33 | /* 34 | ** Assuming mplite_t.zPool is divided up into an array of mplite_link_t 35 | ** structures, return a pointer to the idx-th such lik. 36 | */ 37 | #define mplite_getlink(handle, idx) ((mplite_link_t *) \ 38 | (&handle->zPool[(idx) * handle->szAtom])) 39 | 40 | #define mplite_enter(handle) if((handle != NULL) && \ 41 | ((handle)->lock.acquire != NULL)) \ 42 | { (handle)->lock.acquire((handle)->lock.arg); } 43 | #define mplite_leave(handle) if((handle != NULL) && \ 44 | ((handle)->lock.release != NULL)) \ 45 | { (handle)->lock.release((handle)->lock.arg); } 46 | 47 | static int mplite_logarithm(const int iValue); 48 | static int mplite_size(const mplite_t *handle, const void *p); 49 | static void mplite_link(mplite_t *handle, const int i, 50 | const int iLogsize); 51 | static void mplite_unlink(mplite_t *handle, const int i, 52 | const int iLogsize); 53 | static int mplite_unlink_first(mplite_t *handle, 54 | const int iLogsize); 55 | static void *mplite_malloc_unsafe(mplite_t *handle, 56 | const int nByte); 57 | static void mplite_free_unsafe(mplite_t *handle, 58 | const void *pOld); 59 | 60 | MPLITE_API int mplite_init(mplite_t *handle, const void *buf, 61 | const int buf_size, const int min_alloc, 62 | const mplite_lock_t *lock) 63 | { 64 | int ii; /* Loop counter */ 65 | int nByte; /* Number of bytes of memory available to this allocator */ 66 | uint8_t *zByte; /* Memory usable by this allocator */ 67 | int nMinLog; /* Log base 2 of minimum allocation size in bytes */ 68 | int iOffset; /* An offset into handle->aCtrl[] */ 69 | 70 | /* Check the parameters */ 71 | if ((NULL == handle) || (NULL == buf) || (buf_size <= 0) || 72 | (min_alloc <= 0)) { 73 | return MPLITE_ERR_INVPAR; 74 | } 75 | 76 | /* Initialize the mplite_t object */ 77 | memset(handle, 0, sizeof (*handle)); 78 | 79 | /* Copy the lock if it is not NULL */ 80 | if (lock != NULL) { 81 | memcpy(&handle->lock, lock, sizeof (handle->lock)); 82 | } 83 | 84 | /* The size of a mplite_link_t object must be a power of two. Verify that 85 | ** this is case. 86 | */ 87 | assert((sizeof (mplite_link_t)&(sizeof (mplite_link_t) - 1)) == 0); 88 | 89 | nByte = buf_size; 90 | zByte = (uint8_t*) buf; 91 | 92 | nMinLog = mplite_logarithm(min_alloc); 93 | handle->szAtom = (1 << nMinLog); 94 | while ((int) sizeof (mplite_link_t) > handle->szAtom) { 95 | handle->szAtom = handle->szAtom << 1; 96 | } 97 | 98 | handle->nBlock = (nByte / (handle->szAtom + sizeof (uint8_t))); 99 | handle->zPool = zByte; 100 | handle->aCtrl = (uint8_t *) & handle->zPool[handle->nBlock * handle->szAtom]; 101 | 102 | for (ii = 0; ii <= MPLITE_LOGMAX; ii++) { 103 | handle->aiFreelist[ii] = -1; 104 | } 105 | 106 | iOffset = 0; 107 | for (ii = MPLITE_LOGMAX; ii >= 0; ii--) { 108 | int nAlloc = (1 << ii); 109 | if ((iOffset + nAlloc) <= handle->nBlock) { 110 | handle->aCtrl[iOffset] = (uint8_t) (ii | MPLITE_CTRL_FREE); 111 | mplite_link(handle, iOffset, ii); 112 | iOffset += nAlloc; 113 | } 114 | assert((iOffset + nAlloc) > handle->nBlock); 115 | } 116 | 117 | return MPLITE_OK; 118 | } 119 | 120 | MPLITE_API void *mplite_malloc(mplite_t *handle, const int nBytes) 121 | { 122 | int64_t *p = 0; 123 | 124 | /* Check the parameters */ 125 | if ((NULL == handle) || (nBytes <= 0)) { 126 | return NULL; 127 | } 128 | 129 | mplite_enter(handle); 130 | p = mplite_malloc_unsafe(handle, nBytes); 131 | mplite_leave(handle); 132 | 133 | return (void*) p; 134 | } 135 | 136 | MPLITE_API void mplite_free(mplite_t *handle, const void *pPrior) 137 | { 138 | /* Check the parameters */ 139 | if ((NULL == handle) || (NULL == pPrior)) { 140 | return; 141 | } 142 | 143 | mplite_enter(handle); 144 | mplite_free_unsafe(handle, pPrior); 145 | mplite_leave(handle); 146 | } 147 | 148 | MPLITE_API void *mplite_realloc(mplite_t *handle, const void *pPrior, 149 | const int nBytes) 150 | { 151 | int nOld; 152 | void *p; 153 | 154 | /* Check the parameters */ 155 | if ((NULL == handle) || (NULL == pPrior) || (nBytes <= 0) || 156 | (nBytes & (nBytes - 1))) { 157 | return NULL; 158 | } 159 | 160 | nOld = mplite_size(handle, pPrior); 161 | if (nBytes <= nOld) { 162 | return (void *) pPrior; 163 | } 164 | mplite_enter(handle); 165 | p = mplite_malloc_unsafe(handle, nBytes); 166 | if (p) { 167 | memcpy(p, pPrior, nOld); 168 | mplite_free_unsafe(handle, pPrior); 169 | } 170 | mplite_leave(handle); 171 | 172 | return p; 173 | } 174 | 175 | MPLITE_API int mplite_roundup(mplite_t *handle, const int n) 176 | { 177 | int iFullSz; 178 | 179 | /* Check the parameters */ 180 | if ((NULL == handle) || (n > MPLITE_MAX_ALLOC_SIZE)) { 181 | return 0; 182 | } 183 | 184 | for (iFullSz = handle->szAtom; iFullSz < n; iFullSz *= 2); 185 | 186 | return iFullSz; 187 | } 188 | 189 | MPLITE_API void mplite_print_stats(const mplite_t * const handle, 190 | const mplite_putsfunc_t putsfunc) 191 | { 192 | if ((handle != NULL) && (putsfunc != NULL)) { 193 | char zStats[256]; 194 | snprintf(zStats, sizeof (zStats), "Total number of calls to malloc: %u", 195 | (unsigned) handle->nAlloc); 196 | putsfunc(zStats); 197 | 198 | snprintf(zStats, sizeof (zStats), "Total of all malloc calls - includes " 199 | "internal fragmentation: %u", (unsigned) handle->totalAlloc); 200 | putsfunc(zStats); 201 | 202 | snprintf(zStats, sizeof (zStats), "Total internal fragmentation: %u", 203 | (unsigned) handle->totalExcess); 204 | putsfunc(zStats); 205 | 206 | snprintf(zStats, sizeof (zStats), "Current checkout, including internal " 207 | "fragmentation: %u", handle->currentOut); 208 | putsfunc(zStats); 209 | 210 | snprintf(zStats, sizeof (zStats), "Current number of distinct checkouts: %u", 211 | handle->currentCount); 212 | putsfunc(zStats); 213 | 214 | snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentOut: %u", 215 | handle->maxOut); 216 | putsfunc(zStats); 217 | 218 | snprintf(zStats, sizeof (zStats), "Maximum instantaneous currentCount: %u", 219 | handle->maxCount); 220 | putsfunc(zStats); 221 | 222 | snprintf(zStats, sizeof (zStats), "Largest allocation (exclusive of " 223 | "internal frag): %u", handle->maxRequest); 224 | putsfunc(zStats); 225 | } 226 | } 227 | 228 | /* 229 | ** Return the ceiling of the logarithm base 2 of iValue. 230 | ** 231 | ** Examples: mplite_logarithm(1) -> 0 232 | ** mplite_logarithm(2) -> 1 233 | ** mplite_logarithm(4) -> 2 234 | ** mplite_logarithm(5) -> 3 235 | ** mplite_logarithm(8) -> 3 236 | ** mplite_logarithm(9) -> 4 237 | */ 238 | static int mplite_logarithm(const int iValue) 239 | { 240 | int iLog; 241 | for (iLog = 0; (1 << iLog) < iValue; iLog++); 242 | return iLog; 243 | } 244 | 245 | /* 246 | ** Return the size of an outstanding allocation, in bytes. The 247 | ** size returned omits the 8-byte header overhead. This only 248 | ** works for chunks that are currently checked out. 249 | */ 250 | static int mplite_size(const mplite_t *handle, const void *p) 251 | { 252 | int iSize = 0; 253 | if (p) { 254 | int i = ((uint8_t *) p - handle->zPool) / handle->szAtom; 255 | assert(i >= 0 && i < handle->nBlock); 256 | iSize = handle->szAtom * 257 | (1 << (handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE)); 258 | } 259 | return iSize; 260 | } 261 | 262 | /* 263 | ** Link the chunk at handle->aPool[i] so that is on the iLogsize 264 | ** free list. 265 | */ 266 | static void mplite_link(mplite_t *handle, const int i, 267 | const int iLogsize) 268 | { 269 | int x; 270 | assert(i >= 0 && i < handle->nBlock); 271 | assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX); 272 | assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize); 273 | 274 | x = mplite_getlink(handle, i)->next = handle->aiFreelist[iLogsize]; 275 | mplite_getlink(handle, i)->prev = -1; 276 | if (x >= 0) { 277 | assert(x < handle->nBlock); 278 | mplite_getlink(handle, x)->prev = i; 279 | } 280 | handle->aiFreelist[iLogsize] = i; 281 | } 282 | 283 | /* 284 | ** Unlink the chunk at handle->aPool[i] from list it is currently 285 | ** on. It should be found on handle->aiFreelist[iLogsize]. 286 | */ 287 | static void mplite_unlink(mplite_t *handle, const int i, 288 | const int iLogsize) 289 | { 290 | int next, prev; 291 | assert(i >= 0 && i < handle->nBlock); 292 | assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX); 293 | assert((handle->aCtrl[i] & MPLITE_CTRL_LOGSIZE) == iLogsize); 294 | 295 | next = mplite_getlink(handle, i)->next; 296 | prev = mplite_getlink(handle, i)->prev; 297 | if (prev < 0) { 298 | handle->aiFreelist[iLogsize] = next; 299 | } 300 | else { 301 | mplite_getlink(handle, prev)->next = next; 302 | } 303 | if (next >= 0) { 304 | mplite_getlink(handle, next)->prev = prev; 305 | } 306 | } 307 | 308 | /* 309 | ** Find the first entry on the freelist iLogsize. Unlink that 310 | ** entry and return its index. 311 | */ 312 | static int mplite_unlink_first(mplite_t *handle, 313 | const int iLogsize) 314 | { 315 | int i; 316 | int iFirst; 317 | 318 | assert(iLogsize >= 0 && iLogsize <= MPLITE_LOGMAX); 319 | i = iFirst = handle->aiFreelist[iLogsize]; 320 | assert(iFirst >= 0); 321 | while (i > 0) { 322 | if (i < iFirst) iFirst = i; 323 | i = mplite_getlink(handle, i)->next; 324 | } 325 | mplite_unlink(handle, iFirst, iLogsize); 326 | return iFirst; 327 | } 328 | 329 | /* 330 | ** Return a block of memory of at least nBytes in size. 331 | ** Return NULL if unable. Return NULL if nBytes==0. 332 | ** 333 | ** The caller guarantees that nByte positive. 334 | ** 335 | ** The caller has obtained a lock prior to invoking this 336 | ** routine so there is never any chance that two or more 337 | ** threads can be in this routine at the same time. 338 | */ 339 | static void *mplite_malloc_unsafe(mplite_t *handle, 340 | const int nByte) 341 | { 342 | int i; /* Index of a handle->aPool[] slot */ 343 | int iBin; /* Index into handle->aiFreelist[] */ 344 | int iFullSz; /* Size of allocation rounded up to power of 2 */ 345 | int iLogsize; /* Log2 of iFullSz/POW2_MIN */ 346 | 347 | /* nByte must be a positive */ 348 | assert(nByte > 0); 349 | 350 | /* Keep track of the maximum allocation request. Even unfulfilled 351 | ** requests are counted */ 352 | if ((uint32_t) nByte > handle->maxRequest) { 353 | handle->maxRequest = nByte; 354 | } 355 | 356 | /* Abort if the requested allocation size is larger than the largest 357 | ** power of two that we can represent using 32-bit signed integers. 358 | */ 359 | if (nByte > MPLITE_MAX_ALLOC_SIZE) { 360 | return NULL; 361 | } 362 | 363 | /* Round nByte up to the next valid power of two */ 364 | for (iFullSz = handle->szAtom, iLogsize = 0; iFullSz < nByte; iFullSz *= 2, 365 | iLogsize++) { 366 | } 367 | 368 | /* Make sure handle->aiFreelist[iLogsize] contains at least one free 369 | ** block. If not, then split a block of the next larger power of 370 | ** two in order to create a new free block of size iLogsize. 371 | */ 372 | for (iBin = iLogsize; handle->aiFreelist[iBin] < 0 && iBin <= MPLITE_LOGMAX; 373 | iBin++) { 374 | } 375 | if (iBin > MPLITE_LOGMAX) { 376 | return NULL; 377 | } 378 | i = mplite_unlink_first(handle, iBin); 379 | while (iBin > iLogsize) { 380 | int newSize; 381 | 382 | iBin--; 383 | newSize = 1 << iBin; 384 | handle->aCtrl[i + newSize] = (uint8_t) (MPLITE_CTRL_FREE | iBin); 385 | mplite_link(handle, i + newSize, iBin); 386 | } 387 | handle->aCtrl[i] = (uint8_t) iLogsize; 388 | 389 | /* Update allocator performance statistics. */ 390 | handle->nAlloc++; 391 | handle->totalAlloc += iFullSz; 392 | handle->totalExcess += iFullSz - nByte; 393 | handle->currentCount++; 394 | handle->currentOut += iFullSz; 395 | if (handle->maxCount < handle->currentCount) { 396 | handle->maxCount = handle->currentCount; 397 | } 398 | if (handle->maxOut < handle->currentOut) { 399 | handle->maxOut = handle->currentOut; 400 | } 401 | 402 | /* Return a pointer to the allocated memory. */ 403 | return (void*) &handle->zPool[i * handle->szAtom]; 404 | } 405 | 406 | /* 407 | ** Free an outstanding memory allocation. 408 | */ 409 | static void mplite_free_unsafe(mplite_t *handle, 410 | const void *pOld) 411 | { 412 | uint32_t size, iLogsize; 413 | int iBlock; 414 | 415 | /* Set iBlock to the index of the block pointed to by pOld in 416 | ** the array of handle->szAtom byte blocks pointed to by handle->zPool. 417 | */ 418 | iBlock = ((uint8_t *) pOld - handle->zPool) / handle->szAtom; 419 | 420 | /* Check that the pointer pOld points to a valid, non-free block. */ 421 | assert(iBlock >= 0 && iBlock < handle->nBlock); 422 | assert(((uint8_t *) pOld - handle->zPool) % handle->szAtom == 0); 423 | assert((handle->aCtrl[iBlock] & MPLITE_CTRL_FREE) == 0); 424 | 425 | iLogsize = handle->aCtrl[iBlock] & MPLITE_CTRL_LOGSIZE; 426 | size = 1 << iLogsize; 427 | assert(iBlock + size - 1 < (uint32_t) handle->nBlock); 428 | 429 | handle->aCtrl[iBlock] |= MPLITE_CTRL_FREE; 430 | handle->aCtrl[iBlock + size - 1] |= MPLITE_CTRL_FREE; 431 | assert(handle->currentCount > 0); 432 | assert(handle->currentOut >= (size * handle->szAtom)); 433 | handle->currentCount--; 434 | handle->currentOut -= size * handle->szAtom; 435 | assert(handle->currentOut > 0 || handle->currentCount == 0); 436 | assert(handle->currentCount > 0 || handle->currentOut == 0); 437 | 438 | handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize); 439 | while (iLogsize < MPLITE_LOGMAX) { 440 | int iBuddy; 441 | if ((iBlock >> iLogsize) & 1) { 442 | iBuddy = iBlock - size; 443 | } 444 | else { 445 | iBuddy = iBlock + size; 446 | } 447 | assert(iBuddy >= 0); 448 | if ((iBuddy + (1 << iLogsize)) > handle->nBlock) break; 449 | if (handle->aCtrl[iBuddy] != (MPLITE_CTRL_FREE | iLogsize)) break; 450 | mplite_unlink(handle, iBuddy, iLogsize); 451 | iLogsize++; 452 | if (iBuddy < iBlock) { 453 | handle->aCtrl[iBuddy] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize); 454 | handle->aCtrl[iBlock] = 0; 455 | iBlock = iBuddy; 456 | } 457 | else { 458 | handle->aCtrl[iBlock] = (uint8_t) (MPLITE_CTRL_FREE | iLogsize); 459 | handle->aCtrl[iBuddy] = 0; 460 | } 461 | size *= 2; 462 | } 463 | mplite_link(handle, iBlock, iLogsize); 464 | } 465 | -------------------------------------------------------------------------------- /shalloc/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "include/util.h" 3 | #include "include/interface.h" 4 | 5 | /* Allocator function definitions. */ 6 | shalloc_buff_op_t shalloc_space_buff_ops[__NUM_SHALLOC_BUFF_ALLOC_TYPES] = { 7 | /* SHALLOC_BUFF_ALLOC_TYPE_NONE */ 8 | { 0, 0, 0, 0, 0 }, 9 | 10 | /* SHALLOC_BUFF_ALLOC_TYPE_BUFFER */ 11 | { 12 | _buffer_create, 13 | gen_empty_destroy, 14 | _buffer_malloc, 15 | _buffer_free, 16 | gen_memset_calloc 17 | }, 18 | 19 | /* SHALLOC_BUFF_ALLOC_TYPE_SIMPLE */ 20 | { 21 | _simple_create, 22 | gen_empty_destroy, 23 | _simple_malloc, 24 | _simple_free, 25 | gen_memset_calloc 26 | }, 27 | 28 | /* SHALLOC_BUFF_ALLOC_TYPE_MPLITE */ 29 | { 30 | _mplite_create, 31 | gen_empty_destroy, 32 | _mplite_malloc, 33 | _mplite_free, 34 | gen_memset_calloc 35 | }, 36 | 37 | /* SHALLOC_BUFF_ALLOC_TYPE_NOFREE */ 38 | { 39 | _nofree_create, 40 | _nofree_destroy, 41 | _nofree_malloc, 42 | _nofree_free, 43 | gen_memset_calloc, 44 | }, 45 | 46 | /* SHALLOC_BUFF_ALLOC_TYPE_SLAB */ 47 | { 48 | _slab_create, 49 | _slab_destroy, 50 | _slab_malloc, 51 | _slab_free, 52 | gen_memset_calloc 53 | } 54 | }; 55 | 56 | /* Utility functions. */ 57 | shalloc_buff_t* shalloc_get_buff(shalloc_buff_t *buff, 58 | void *start, size_t size, size_t block_size, 59 | enum shalloc_buff_alloc_type type, 60 | enum shalloc_buff_alloc_type default_type) 61 | { 62 | if (start && size < SHALLOC_BUFF_MIN_SIZE) { 63 | size = SHALLOC_BUFF_MIN_SIZE; 64 | } 65 | memset(buff, 0, sizeof(shalloc_buff_t)); 66 | buff->start = start; 67 | buff->end = (char*)start + size - 1; 68 | buff->size = size; 69 | buff->unused_size = size; 70 | buff->block_size = block_size; 71 | if (!type) { 72 | type = default_type; 73 | } 74 | assert(type < __NUM_SHALLOC_BUFF_ALLOC_TYPES); 75 | buff->alloc_type = type; 76 | if (type != SHALLOC_BUFF_ALLOC_TYPE_NONE && shalloc_space) { 77 | buff->op = &shalloc_space->buff_ops[type]; 78 | } 79 | 80 | return buff; 81 | } 82 | 83 | shalloc_buff_t* shalloc_clone_buff(shalloc_buff_t *buff, 84 | void *start, size_t size, shalloc_buff_t *from_buff) 85 | { 86 | shalloc_get_buff(buff, start, size, from_buff->block_size, 87 | from_buff->alloc_type, from_buff->alloc_type); 88 | 89 | return buff; 90 | } 91 | 92 | /* Shalloc allocator interface. */ 93 | void shalloc_buff_reset(shalloc_buff_t *buff) 94 | { 95 | int ret; 96 | buff->op->destroy(buff); 97 | ret = buff->op->create(buff); 98 | assert(ret >= 0 && "Corrupted buffer?"); 99 | } 100 | -------------------------------------------------------------------------------- /shalloc/heap.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "include/util.h" 3 | 4 | /* Heap utility functions. */ 5 | shalloc_heap_t* shalloc_get_heap(shalloc_heap_t *heap, char *addr, 6 | size_t size, int mmap_flags, enum shalloc_buff_alloc_type type) 7 | { 8 | size_t data_size, base_size; 9 | shalloc_buff_t *buff; 10 | 11 | /* Page align. */ 12 | assert(size > 0); 13 | if (size % SHALLOC_PAGE_SIZE > 0) { 14 | size = (size/SHALLOC_PAGE_SIZE)*SHALLOC_PAGE_SIZE; 15 | if (size == 0) { 16 | size += SHALLOC_PAGE_SIZE; 17 | } 18 | } 19 | 20 | /* Compute size. */ 21 | data_size = size; 22 | #if SHALLOC_USE_GUARD_PAGES 23 | if (size > 100*SHALLOC_PAGE_SIZE) { 24 | data_size -= SHALLOC_PAGE_SIZE; 25 | } 26 | base_size = data_size + SHALLOC_PAGE_SIZE; 27 | #else 28 | base_size = data_size; 29 | #endif 30 | 31 | /* Fill in information. */ 32 | buff = &heap->base; 33 | shalloc_get_buff(buff, addr, base_size, 0, 0, 0); 34 | shalloc_get_region(&heap->region, NULL, data_size, 0, 35 | SHALLOC_FLAG(HEAP)|SHALLOC_FLAG(NON_RESIZABLE), 36 | SHALLOC_HEAP_TYPE_DEFAULT); 37 | buff = &heap->region.default_data; 38 | heap->region.data_head = heap->region.data_tail = buff; 39 | shalloc_get_buff(buff, addr, data_size, 0, 40 | type, SHALLOC_HEAP_TYPE_DEFAULT); 41 | heap->mmap_flags = mmap_flags; 42 | 43 | return heap; 44 | } 45 | 46 | int shalloc_map_heap(shalloc_heap_t *heap) 47 | { 48 | shalloc_buff_t *data = shalloc_heap_to_buff(heap); 49 | int remapped = 0, inherit_mem_id; 50 | char *inherit_mem_ptr; 51 | 52 | if (heap->mmap_flags & SHALLOC_MAP_INHERIT) { 53 | if (heap->inherit_id == -1) { 54 | inherit_mem_id = shmget(IPC_PRIVATE, data->size, SHM_R | SHM_W); 55 | assert(inherit_mem_id != -1); 56 | inherit_mem_ptr = shmat(inherit_mem_id, data->start, SHM_REMAP); 57 | assert(inherit_mem_ptr != MAP_FAILED); 58 | heap->inherit_id = inherit_mem_id; 59 | 60 | // mark for delete 61 | shmctl(inherit_mem_id, IPC_RMID, NULL); 62 | } else { 63 | inherit_mem_ptr = shmat(heap->inherit_id, data->start, SHM_REMAP); 64 | assert(inherit_mem_ptr != MAP_FAILED); 65 | } 66 | remapped = 1; 67 | 68 | } else if (heap->mmap_flags != SHALLOC_DEFAULT_MMAP_FLAGS) { 69 | /* Remap the heap with the right flags if necessary. */ 70 | shalloc_map_fixed_pages(data->start, data->size, 71 | PROT_READ|PROT_WRITE, heap->mmap_flags); 72 | remapped = 1; 73 | } 74 | 75 | if (heap->base.size > data->size) { 76 | /* Add guard page. */ 77 | shalloc_map_fixed_pages((char*)data->start+data->size, 78 | SHALLOC_PAGE_SIZE, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE); 79 | remapped = 1; 80 | } 81 | 82 | return remapped; 83 | } 84 | 85 | void shalloc_heap_destroy(shalloc_heap_t* heap) 86 | { 87 | shalloc_buff_t *data; 88 | shalloc_magic_t *magic_info; 89 | 90 | data = shalloc_heap_to_buff(heap); 91 | 92 | if (heap->mmap_flags & SHALLOC_MAP_INHERIT) { 93 | if (heap->inherit_id != -1) { 94 | shmdt(data->start); 95 | shmctl(heap->inherit_id, IPC_RMID, NULL); 96 | heap->inherit_id = -1; 97 | } 98 | magic_info = (shalloc_magic_t *) shalloc_space->magic_control_page; 99 | magic_info->num_heaps--; 100 | } else { 101 | shalloc_free(shalloc_heap_to_region(shalloc_space->priv_heap), heap); 102 | } 103 | 104 | munmap(heap->base.start, heap->base.size); 105 | } 106 | 107 | /* Shalloc heap allocator interface. */ 108 | shalloc_heap_t* shalloc_heap_create(size_t size, int mmap_flags, 109 | enum shalloc_buff_alloc_type type) 110 | { 111 | shalloc_heap_t *heap; 112 | shalloc_buff_t *data; 113 | shalloc_region_t *priv_region; 114 | shalloc_magic_t *magic_info; 115 | int remapped; 116 | char *addr; 117 | 118 | /* Allocate heap object. */ 119 | assert(shalloc_space && "shalloc_space not initialized"); 120 | if (mmap_flags & SHALLOC_MAP_INHERIT) { 121 | magic_info = (shalloc_magic_t *) shalloc_space->magic_control_page; 122 | assert(magic_info->num_heaps < SHALLOC_MAX_INHERIT_HEAPS && "Out of space for inherit heaps"); 123 | heap = &magic_info->heap_list[magic_info->num_heaps]; 124 | heap->inherit_id = -1; 125 | magic_info->num_heaps++; 126 | } else { 127 | priv_region = shalloc_heap_to_region(shalloc_space->priv_heap); 128 | heap = shalloc_malloc(priv_region, sizeof(shalloc_heap_t)); 129 | assert(heap && "Out of private heap memory!"); 130 | } 131 | 132 | /* Figure out if we have enough space for the new heap. */ 133 | addr = (char*)shalloc_space->data.start + shalloc_space->data.size 134 | - shalloc_space->data.unused_size; 135 | assert(addr <= (char*)shalloc_space->data.end); 136 | shalloc_get_heap(heap, addr, size, mmap_flags, type); 137 | if (addr + heap->base.size > (char*)shalloc_space->data.end+1) { 138 | if (mmap_flags & SHALLOC_MAP_INHERIT) { 139 | magic_info = (shalloc_magic_t *) shalloc_space->magic_control_page; 140 | magic_info->num_heaps--; 141 | } else { 142 | shalloc_free(priv_region, heap); 143 | } 144 | return NULL; 145 | } 146 | 147 | /* Map the new heap. */ 148 | remapped = shalloc_map_heap(heap); 149 | 150 | /* Create data buffer. */ 151 | data = shalloc_heap_to_buff(heap); 152 | if (data->op->create(data) < 0) { 153 | if (remapped) { 154 | /* Detach if shared */ 155 | if (mmap_flags & SHALLOC_MAP_INHERIT) { 156 | shmdt(data->start); 157 | shmctl(heap->inherit_id, IPC_RMID, NULL); 158 | heap->inherit_id = -1; 159 | } 160 | shalloc_map_fixed_pages(data->start, data->size, 161 | PROT_READ|PROT_WRITE, SHALLOC_DEFAULT_MMAP_FLAGS); 162 | } 163 | if (mmap_flags & SHALLOC_MAP_INHERIT) { 164 | magic_info = (shalloc_magic_t *) shalloc_space->magic_control_page; 165 | magic_info->num_heaps--; 166 | } else { 167 | shalloc_free(priv_region, heap); 168 | } 169 | return NULL; 170 | } 171 | 172 | /* Update shadow space. */ 173 | shalloc_space_new_heap(heap); 174 | 175 | return heap; 176 | } 177 | 178 | shalloc_region_t* shalloc_heap_to_region(shalloc_heap_t* heap) 179 | { 180 | return heap ? &heap->region : NULL; 181 | } 182 | 183 | shalloc_buff_t* shalloc_heap_to_buff(shalloc_heap_t* heap) 184 | { 185 | shalloc_buff_t *data; 186 | if (!heap) { 187 | return NULL; 188 | } 189 | data = shalloc_heap_to_region(heap)->data_tail; 190 | assert(data); 191 | return data; 192 | } 193 | 194 | shalloc_heap_t* shalloc_region_to_heap(shalloc_region_t* region) 195 | { 196 | if (!region || !(region->flags & SHALLOC_FLAG(HEAP))) { 197 | return NULL; 198 | } 199 | return SHALLOC_CONTAINER_OF(region, shalloc_heap_t, region); 200 | } 201 | 202 | -------------------------------------------------------------------------------- /shalloc/include/interface.h: -------------------------------------------------------------------------------- 1 | #ifndef SHALLOC_INTERFACE_H 2 | #define SHALLOC_INTERFACE_H 3 | 4 | /* Buffer allocator interface. */ 5 | int _buffer_create(void *ref); 6 | void* _buffer_malloc(void *ref, size_t size); 7 | void _buffer_free(void *ref, void *ptr); 8 | 9 | /* Simple allocator interface. */ 10 | int _simple_create(void *ref); 11 | void* _simple_malloc(void *ref, size_t size); 12 | void _simple_free(void *ref, void *ptr); 13 | 14 | /* Mplite allocator interface. */ 15 | int _mplite_create(void *ref); 16 | void* _mplite_malloc(void *ref, size_t size); 17 | void _mplite_free(void *ref, void *ptr); 18 | 19 | /* No-free allocator interface. */ 20 | int _nofree_create(void *ref); 21 | void _nofree_destroy(void *ref); 22 | void* _nofree_malloc(void *ref, size_t size); 23 | void _nofree_free(void *ref, void *ptr); 24 | 25 | /* Slab allocator interface. */ 26 | int _slab_create(void *ref); 27 | void _slab_destroy(void *ref); 28 | void* _slab_malloc(void *ref, size_t size); 29 | void _slab_free(void *ref, void *ptr); 30 | 31 | #endif /* SHALLOC_INTERFACE_H */ 32 | 33 | -------------------------------------------------------------------------------- /shalloc/include/util.h: -------------------------------------------------------------------------------- 1 | #ifndef SHALLOC_UTIL_H 2 | #define SHALLOC_UTIL_H 3 | 4 | /* Utility functions. */ 5 | void shalloc_space_new_heap(shalloc_heap_t *heap); 6 | void shalloc_map_fixed_pages(void *addr, size_t size, int prot, 7 | int mmap_flags); 8 | 9 | shalloc_buff_t* shalloc_get_buff(shalloc_buff_t *buff, 10 | void *start, size_t size, size_t block_size, 11 | enum shalloc_buff_alloc_type type, 12 | enum shalloc_buff_alloc_type default_type); 13 | shalloc_buff_t* shalloc_clone_buff(shalloc_buff_t *buff, 14 | void *start, size_t size, shalloc_buff_t *from_buff); 15 | 16 | shalloc_heap_t* shalloc_get_heap(shalloc_heap_t *heap, char *addr, 17 | size_t size, int mmap_flags, enum shalloc_buff_alloc_type type); 18 | int shalloc_map_heap(shalloc_heap_t *heap); 19 | void shalloc_heap_destroy(shalloc_heap_t* heap); 20 | 21 | shalloc_region_t* shalloc_get_region(shalloc_region_t *region, 22 | shalloc_region_t *parent, size_t buff_size, size_t block_size, int flags, 23 | enum shalloc_buff_alloc_type type); 24 | 25 | #endif /* SHALLOC_UTIL_H */ 26 | -------------------------------------------------------------------------------- /shalloc/interface/buffer.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Buffer allocator interface. */ 5 | int _buffer_create(void *ref) 6 | { 7 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 8 | alloc_init(buff->start, buff->size); 9 | return 0; 10 | } 11 | 12 | void* _buffer_malloc(void *ref, size_t size) 13 | { 14 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 15 | return alloc_get(buff->start, buff->size, size, sizeof(long)); 16 | } 17 | 18 | void _buffer_free(void *ref, void *ptr) 19 | { 20 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 21 | alloc_free(buff->start, buff->size, ptr); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /shalloc/interface/buffer_nofree.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* No-free buffer-based allocator interface. */ 5 | int _nofree_create(void *ref) 6 | { 7 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 8 | return nofree_init(buff->start, buff->size); 9 | } 10 | 11 | void _nofree_destroy(void *ref) 12 | { 13 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 14 | nofree_close(buff->start, buff->size); 15 | } 16 | 17 | void* _nofree_malloc(void *ref, size_t size) 18 | { 19 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 20 | return nofree_alloc(buff->start, buff->size, size, sizeof(long)); 21 | } 22 | 23 | void _nofree_free(void *ref, void *ptr) 24 | { 25 | } 26 | 27 | -------------------------------------------------------------------------------- /shalloc/interface/buffer_simple.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Simple allocator interface. */ 5 | int _simple_create(void *ref) 6 | { 7 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 8 | memmgr_init(buff->start, buff->size); 9 | return 0; 10 | } 11 | 12 | void* _simple_malloc(void *ref, size_t size) 13 | { 14 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 15 | return memmgr_alloc(buff->start, buff->size, size); 16 | } 17 | 18 | void _simple_free(void *ref, void *ptr) 19 | { 20 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 21 | memmgr_free(buff->start, buff->size, ptr); 22 | } 23 | -------------------------------------------------------------------------------- /shalloc/interface/buffer_slab.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* Buffer slab allocator interface. */ 5 | int _slab_create(void *ref) 6 | { 7 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 8 | slab_init(buff->start, buff->size, buff->block_size); 9 | return 0; 10 | } 11 | 12 | void _slab_destroy(void *ref) 13 | { 14 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 15 | slab_close(buff->start); 16 | } 17 | 18 | void* _slab_malloc(void *ref, size_t size) 19 | { 20 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 21 | return slab_alloc(buff->start, size); 22 | } 23 | 24 | void _slab_free(void *ref, void *ptr) 25 | { 26 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 27 | slab_free(buff->start, ptr); 28 | } 29 | -------------------------------------------------------------------------------- /shalloc/interface/mplite.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define MPLITE_MIN_ALLOC 64 5 | 6 | /* Mplite allocator interface. */ 7 | int _mplite_create(void *ref) 8 | { 9 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 10 | mplite_t *handle = (mplite_t*) buff->start; 11 | int ret; 12 | if (buff->size <= sizeof(mplite_t)) { 13 | return -1; 14 | } 15 | ret = mplite_init(handle, handle+1, buff->size-sizeof(mplite_t), 16 | MPLITE_MIN_ALLOC, NULL); 17 | return ret == MPLITE_OK ? 0 : -1; 18 | } 19 | 20 | void* _mplite_malloc(void *ref, size_t size) 21 | { 22 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 23 | mplite_t *handle = (mplite_t*) buff->start; 24 | return mplite_malloc(handle, size); 25 | } 26 | 27 | void _mplite_free(void *ref, void *ptr) 28 | { 29 | shalloc_buff_t *buff = (shalloc_buff_t*) ref; 30 | mplite_t *handle = (mplite_t*) buff->start; 31 | mplite_free(handle, ptr); 32 | } 33 | -------------------------------------------------------------------------------- /shalloc/region.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "include/util.h" 3 | 4 | /* Region utility functions. */ 5 | static shalloc_buff_t* shalloc_region_alloc_buff(shalloc_region_t *region, 6 | size_t size) 7 | { 8 | shalloc_buff_t *data; 9 | size_t default_data_size = region->default_data.size; 10 | if (region->flags & SHALLOC_FLAG(ELASTIC)) { 11 | default_data_size *= 2; 12 | } 13 | if (default_data_size > size) { 14 | size = default_data_size; 15 | } 16 | 17 | assert(region->parent); 18 | data = (shalloc_buff_t*) shalloc_malloc(region->parent, 19 | sizeof(shalloc_buff_t) + size); 20 | if (!data) { 21 | return NULL; 22 | } 23 | shalloc_clone_buff(data, data+1, size, ®ion->default_data); 24 | if (data->op->create(data) < 0) { 25 | shalloc_free(region->parent, data); 26 | return NULL; 27 | } 28 | region->default_data.size = default_data_size; 29 | 30 | return data; 31 | } 32 | 33 | static void shalloc_region_free_buff(shalloc_region_t *region, 34 | shalloc_buff_t *data) 35 | { 36 | data->op->destroy(data); 37 | if (region->parent) { 38 | shalloc_free(region->parent, data); 39 | } 40 | } 41 | 42 | static int shalloc_region_grow(shalloc_region_t *region, size_t size) 43 | { 44 | shalloc_buff_t *buff; 45 | assert(size > 0); 46 | if (region->data_tail && (region->flags & SHALLOC_FLAG(NON_RESIZABLE))) { 47 | return -1; 48 | } 49 | buff = shalloc_region_alloc_buff(region, size); 50 | if (!buff) { 51 | return -1; 52 | } 53 | if (!region->data_tail) { 54 | assert(!region->data_head); 55 | region->data_head = region->data_tail = buff; 56 | } 57 | else { 58 | region->data_tail->next = buff; 59 | region->data_tail = buff; 60 | } 61 | buff->next = NULL; 62 | 63 | return 0; 64 | } 65 | 66 | shalloc_region_t* shalloc_get_region(shalloc_region_t *region, 67 | shalloc_region_t *parent, size_t buff_size, size_t block_size, int flags, 68 | enum shalloc_buff_alloc_type type) 69 | { 70 | shalloc_buff_t *data; 71 | 72 | /* Fill in information. */ 73 | if (buff_size == 0) { 74 | buff_size = SHALLOC_REGION_BUFF_SIZE_DEFAULT; 75 | } 76 | data = ®ion->default_data; 77 | shalloc_get_buff(data, (void*)-1, buff_size, block_size, 78 | type, SHALLOC_REGION_TYPE_DEFAULT); 79 | region->data_head = NULL; 80 | region->data_tail = NULL; 81 | region->parent = parent; 82 | region->flags = flags; 83 | 84 | return region; 85 | } 86 | 87 | /* Shalloc region allocator interface. */ 88 | shalloc_region_t* shalloc_region_create(shalloc_region_t *parent, 89 | size_t init_size, size_t buff_size, size_t block_size, int flags, 90 | enum shalloc_buff_alloc_type type) 91 | { 92 | shalloc_region_t *region; 93 | 94 | /* Allocate region object. */ 95 | assert(parent && "Bad parent!"); 96 | if (flags & SHALLOC_FLAG(HEAP)) { 97 | return NULL; 98 | } 99 | region = shalloc_malloc(parent, sizeof(shalloc_region_t)); 100 | if (!region) { 101 | return NULL; 102 | } 103 | shalloc_get_region(region, parent, buff_size, block_size, flags, type); 104 | if (init_size > 0) { 105 | if (shalloc_region_grow(region, init_size) < 0) { 106 | shalloc_region_destroy(region); 107 | return NULL; 108 | } 109 | } 110 | 111 | return region; 112 | } 113 | 114 | void shalloc_region_destroy(shalloc_region_t* region) 115 | { 116 | shalloc_region_reset(region); 117 | if (region->parent) { 118 | shalloc_free(region->parent, region); 119 | } 120 | if (region->flags & SHALLOC_FLAG(HEAP)) { 121 | shalloc_heap_destroy(shalloc_region_to_heap(region)); 122 | return; 123 | } 124 | } 125 | 126 | void shalloc_region_reset(shalloc_region_t* region) 127 | { 128 | shalloc_buff_t *prev, *curr; 129 | 130 | SHALLOC_REGION_BUFF_ITER(region, prev, curr, 131 | if (prev && prev != region->data_head) { 132 | shalloc_region_free_buff(region, prev); 133 | } 134 | ); 135 | if (region->data_head) { 136 | shalloc_buff_reset(region->data_head); 137 | region->data_head->next = NULL; 138 | region->data_tail = region->data_head; 139 | } 140 | } 141 | 142 | void shalloc_region_get_info(shalloc_region_t* region, 143 | shalloc_region_info_t *info) 144 | { 145 | shalloc_buff_t *prev, *curr; 146 | 147 | memset(info, 0, sizeof(shalloc_region_info_t)); 148 | SHALLOC_REGION_BUFF_ITER(region, prev, curr, 149 | info->tot_buff_size += curr->size; 150 | info->num_buffs++; 151 | ); 152 | if (curr) { 153 | info->last_buff_size = curr->size; 154 | } 155 | } 156 | 157 | void* shalloc_malloc(shalloc_region_t *region, size_t size) 158 | { 159 | void *ptr; 160 | shalloc_buff_t *data_tail = region->data_tail; 161 | if (!size) { 162 | return NULL; 163 | } 164 | ptr = NULL; 165 | if (data_tail) { 166 | ptr = data_tail->op->malloc(data_tail, size); 167 | } 168 | if (!ptr) { 169 | if (shalloc_region_grow(region, SHALLOC_BUFF_ALLOC_SIZE(size)) == 0) { 170 | data_tail = region->data_tail; 171 | ptr = data_tail->op->malloc(data_tail, size); 172 | } 173 | } 174 | return ptr; 175 | } 176 | 177 | void shalloc_free(shalloc_region_t *region, void *ptr) 178 | { 179 | shalloc_buff_t *data_tail = region->data_tail; 180 | if (!ptr) { 181 | return; 182 | } 183 | 184 | /* We only support deallocation in the last data buffer. */ 185 | if (data_tail && SHALLOC_IS_BUFF_ADDR(data_tail, ptr)) { 186 | data_tail->op->free(data_tail, ptr); 187 | } 188 | } 189 | 190 | void* shalloc_calloc(shalloc_region_t *region, size_t nmemb, size_t size) 191 | { 192 | void *ptr; 193 | shalloc_buff_t *data_tail = region->data_tail; 194 | size_t tot_size = nmemb*size; 195 | if (tot_size == 0) { 196 | return NULL; 197 | } 198 | ptr = NULL; 199 | if (data_tail) { 200 | ptr = data_tail->op->calloc(data_tail, nmemb, size); 201 | } 202 | if (!ptr) { 203 | if (shalloc_region_grow(region, 204 | SHALLOC_BUFF_ALLOC_SIZE(tot_size)) == 0) { 205 | data_tail = region->data_tail; 206 | ptr = data_tail->op->calloc(data_tail, nmemb, size); 207 | } 208 | } 209 | return ptr; 210 | } 211 | 212 | void* shalloc_orealloc(shalloc_region_t *region, void *ptr, size_t size, 213 | size_t old_size) 214 | { 215 | void *new_ptr; 216 | 217 | if (ptr == NULL) { 218 | return shalloc_malloc(region, size); 219 | } 220 | if (size == 0) { 221 | shalloc_free(region, ptr); 222 | return NULL; 223 | } 224 | if (size <= old_size) { 225 | return ptr; 226 | } 227 | 228 | new_ptr = shalloc_malloc(region, size); 229 | if (!new_ptr) { 230 | return NULL; 231 | } 232 | memcpy(new_ptr, ptr, old_size); 233 | shalloc_free(region, ptr); 234 | return new_ptr; 235 | } 236 | 237 | -------------------------------------------------------------------------------- /shalloc/shalloc.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "include/util.h" 3 | 4 | shalloc_space_t *shalloc_space = NULL; 5 | 6 | /* Generic allocator functions. */ 7 | void* gen_memset_calloc(void *ref, size_t nmemb, size_t size) 8 | { 9 | shalloc_buff_t *data = (shalloc_buff_t*) ref; 10 | void *ptr = data->op->malloc(data, size*nmemb); 11 | if (ptr) { 12 | memset(ptr, 0, size*nmemb); 13 | } 14 | return ptr; 15 | } 16 | 17 | void gen_empty_destroy(void *ref) 18 | { 19 | } 20 | 21 | /* Utility functions. */ 22 | void shalloc_map_fixed_pages(void *addr, size_t size, int prot, 23 | int mmap_flags) 24 | { 25 | void *real_addr = mmap(addr, size, prot, mmap_flags|MAP_FIXED, -1, 0); 26 | assert(addr == real_addr); 27 | } 28 | 29 | void shalloc_space_new_heap(shalloc_heap_t *heap) 30 | { 31 | if (heap->mmap_flags & SHALLOC_MAP_INHERIT) { 32 | assert(!shalloc_space->has_noninherit_heaps && "Inherit heaps should always be created first!"); 33 | } 34 | else { 35 | shalloc_space->has_noninherit_heaps = 1; 36 | } 37 | 38 | assert(shalloc_space->data.unused_size >= heap->base.size); 39 | shalloc_space->data.unused_size -= heap->base.size; 40 | shalloc_space->num_heaps++; 41 | } 42 | 43 | /* Printing functions. */ 44 | void shalloc_space_print() 45 | { 46 | shalloc_printf("SPACE:{"); 47 | shalloc_printf(" .base="); 48 | shalloc_buff_print(&shalloc_space->base); 49 | shalloc_printf(" .data="); 50 | shalloc_buff_print(&shalloc_space->data); 51 | shalloc_printf(" .num_heaps=%d", shalloc_space->num_heaps); 52 | shalloc_printf(" .mmap_flags=0x%08x", shalloc_space->mmap_flags); 53 | shalloc_printf(" .priv_heap="); 54 | shalloc_heap_print(shalloc_space->priv_heap); 55 | shalloc_printf(" }"); 56 | } 57 | 58 | void shalloc_buff_print(shalloc_buff_t *buff) 59 | { 60 | shalloc_printf("BUFF:{"); 61 | shalloc_printf(" .start=%p", (void*) buff->start); 62 | shalloc_printf(" .end=%p", (void*) buff->end); 63 | shalloc_printf(" .size=%zu", buff->size); 64 | shalloc_printf(" .unused_size=%zu", buff->unused_size); 65 | shalloc_printf(" .next=%p", (void*) buff->next); 66 | shalloc_printf(" }"); 67 | } 68 | 69 | void shalloc_heap_print(shalloc_heap_t *heap) 70 | { 71 | shalloc_printf("HEAP:{"); 72 | shalloc_printf(" .base="); 73 | shalloc_buff_print(&heap->base); 74 | shalloc_printf(" .region="); 75 | shalloc_region_print(&heap->region); 76 | shalloc_printf(" .mmap_flags=0x%08x", heap->mmap_flags); 77 | shalloc_printf(" }"); 78 | } 79 | 80 | void shalloc_region_print(shalloc_region_t *region) 81 | { 82 | shalloc_printf("REGION:{"); 83 | shalloc_printf(" .data_head=%p", (void*) region->data_head); 84 | shalloc_printf(" .data_tail=%p", (void*) region->data_tail); 85 | shalloc_printf(" .default_data="); 86 | shalloc_buff_print(®ion->default_data); 87 | shalloc_printf(" .flags=0x%08x", region->flags); 88 | shalloc_printf(" .parent=%p", (void*) region->parent); 89 | shalloc_printf(" }"); 90 | } 91 | 92 | /* Shalloc allocator interface. */ 93 | void shalloc_space_init() 94 | { 95 | char *base_addr, *addr; 96 | int ret, i; 97 | shalloc_heap_t heap, *priv_heap; 98 | shalloc_buff_t *buff; 99 | shalloc_region_t *priv_region; 100 | shalloc_magic_t *magic_info; 101 | int inherit_mem_id; 102 | char *inherit_mem_ptr; 103 | 104 | if (shalloc_space) { 105 | return; 106 | } 107 | 108 | /* Check configuration. */ 109 | assert(SHALLOC_BASE_SIZE >= 3*SHALLOC_PRIVATE_HEAP_SIZE); 110 | assert(SHALLOC_DEFAULT_MMAP_FLAGS != 0); 111 | 112 | /* Map (and reserve) shadow space memory. */ 113 | base_addr=mmap((void*)SHALLOC_BASE_ADDR, SHALLOC_BASE_SIZE, 114 | PROT_READ|PROT_WRITE, SHALLOC_DEFAULT_MMAP_FLAGS|MAP_FIXED, -1, 0); 115 | assert(base_addr != MAP_FAILED); 116 | addr = base_addr; 117 | 118 | #if SHALLOC_USE_GUARD_PAGES 119 | /* Map first guard page. */ 120 | shalloc_map_fixed_pages(addr, SHALLOC_PAGE_SIZE, PROT_NONE, 121 | MAP_ANONYMOUS|MAP_PRIVATE); 122 | addr += SHALLOC_PAGE_SIZE; 123 | #endif 124 | 125 | /* Create private heap for our own data structures. */ 126 | shalloc_get_heap(&heap, addr, SHALLOC_PRIVATE_HEAP_SIZE, 127 | MAP_ANONYMOUS|MAP_PRIVATE, 0); 128 | shalloc_map_heap(&heap); 129 | buff = shalloc_heap_to_buff(&heap); 130 | buff->op = &shalloc_space_buff_ops[SHALLOC_HEAP_TYPE_DEFAULT]; 131 | ret = buff->op->create(buff); 132 | assert(ret == 0); 133 | priv_region = shalloc_heap_to_region(&heap); 134 | priv_heap = shalloc_malloc(priv_region, sizeof(shalloc_heap_t)); 135 | assert(priv_heap); 136 | memcpy(priv_heap, &heap, sizeof(shalloc_heap_t)); 137 | priv_region = shalloc_heap_to_region(priv_heap); 138 | priv_region->data_head = priv_region->data_tail = 139 | &priv_region->default_data; 140 | addr += priv_heap->base.size; 141 | 142 | /* Create inherited magic pages. */ 143 | if (getenv(SHALLOC_INHERIT_ID) == NULL) { 144 | inherit_mem_id = shmget(IPC_PRIVATE, 2*SHALLOC_PAGE_SIZE, SHM_R | SHM_W); 145 | assert(inherit_mem_id != -1); 146 | inherit_mem_ptr = shmat(inherit_mem_id, addr, SHM_REMAP); 147 | assert(inherit_mem_ptr != MAP_FAILED); 148 | 149 | // mark for delete 150 | shmctl(inherit_mem_id, IPC_RMID, NULL); 151 | 152 | magic_info = (shalloc_magic_t *) inherit_mem_ptr; 153 | magic_info->inherit_id = inherit_mem_id; 154 | sprintf(magic_info->inherit_envp_buff, "%s=%d", 155 | SHALLOC_INHERIT_ID, inherit_mem_id); 156 | magic_info->inherit_envp[0] = magic_info->inherit_envp_buff; 157 | magic_info->inherit_envp[1] = NULL; 158 | magic_info->num_heaps = 0; 159 | } else { 160 | inherit_mem_ptr = shmat(atoi(getenv(SHALLOC_INHERIT_ID)), addr, SHM_REMAP); //TODO: 161 | assert(inherit_mem_ptr != MAP_FAILED); 162 | unsetenv(SHALLOC_INHERIT_ID); 163 | 164 | magic_info = (shalloc_magic_t *) inherit_mem_ptr; 165 | for (i = 0; i < magic_info->num_heaps; i++) { 166 | shalloc_heap_t inherit_heap = magic_info->heap_list[i]; 167 | shalloc_buff_t *data = shalloc_heap_to_buff(&inherit_heap); 168 | inherit_mem_ptr = shmat(inherit_heap.inherit_id, data->start, SHM_REMAP); 169 | assert(inherit_mem_ptr != MAP_FAILED); 170 | } 171 | } 172 | 173 | /* Initialize shalloc space. */ 174 | shalloc_space = shalloc_malloc(priv_region, sizeof(shalloc_space_t)); 175 | assert(shalloc_space); 176 | buff = &shalloc_space->base; 177 | shalloc_get_buff(buff, base_addr, SHALLOC_BASE_SIZE, 0, 0, 0); 178 | 179 | shalloc_space->magic_control_page = addr; 180 | shalloc_space->magic_inherit_page = addr + SHALLOC_PAGE_SIZE; 181 | addr += 2*SHALLOC_PAGE_SIZE; 182 | 183 | buff = &shalloc_space->data; 184 | shalloc_get_buff(buff, addr, 185 | (char*)shalloc_space->base.end - (char*)addr + 1, 0, 0, 0); 186 | shalloc_space->mmap_flags = SHALLOC_DEFAULT_MMAP_FLAGS; 187 | shalloc_space->num_heaps = 0; 188 | shalloc_space->has_noninherit_heaps = 0; 189 | shalloc_space->priv_heap = priv_heap; 190 | memcpy(shalloc_space->buff_ops, shalloc_space_buff_ops, 191 | sizeof(shalloc_buff_op_t)*__NUM_SHALLOC_BUFF_ALLOC_TYPES); 192 | 193 | /* Fix up our own private heap alloc operations. */ 194 | buff = shalloc_heap_to_buff(priv_heap); 195 | buff->op = &shalloc_space->buff_ops[SHALLOC_HEAP_TYPE_DEFAULT]; 196 | 197 | /* Update shalloc space size information when inheriting heaps. */ 198 | for (i = 0; i < magic_info->num_heaps; i++) { 199 | shalloc_heap_t *inherit_heap = &magic_info->heap_list[i]; 200 | shalloc_space_new_heap(inherit_heap); 201 | } 202 | } 203 | 204 | void shalloc_space_close() 205 | { 206 | int i, inherit_id; 207 | shalloc_magic_t *magic_info; 208 | 209 | if (!shalloc_space) { 210 | return; 211 | } 212 | 213 | magic_info = (shalloc_magic_t *)shalloc_space->magic_control_page; 214 | for (i = 0; i < magic_info->num_heaps; i++) { 215 | shalloc_heap_t inherit_heap = magic_info->heap_list[i]; 216 | shalloc_buff_t *data = shalloc_heap_to_buff(&inherit_heap); 217 | shmdt(data->start); 218 | shmctl(inherit_heap.inherit_id, IPC_RMID, NULL); 219 | } 220 | inherit_id = magic_info->inherit_id; 221 | shmdt(shalloc_space->magic_control_page); 222 | shmctl(inherit_id, IPC_RMID, NULL); 223 | 224 | munmap(shalloc_space->base.start, shalloc_space->base.size); 225 | shalloc_space = NULL; 226 | } 227 | 228 | void shalloc_space_freeze() 229 | { 230 | /* Freeze shalloc space. No more heaps can be create/modified from now on.*/ 231 | int ret = mprotect(shalloc_space->priv_heap->base.start, 232 | shalloc_space->priv_heap->base.size, PROT_READ); 233 | assert(ret == 0); 234 | } 235 | 236 | --------------------------------------------------------------------------------