123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117 |
- // SPDX-License-Identifier: GPL-3.0-or-later
- // Copyright © 2018-2019 Ariadne Devos
- #ifndef _sHT_BLOCK_H
- #define _sHT_BLOCK_H
- #include <stddef.h>
- #ifndef _WIN32
- # include <sys/mman.h>
- #endif
- /** Memory blocks
- A read-write byte region backed by physical memory, contiguously addressable
- from virtual memory. On their own, they do not have a particular layout or
- type.
- To be allocated efficiently, space and time-wise, they should be at
- the very least one page large (4KiB on x86). (However, within the kernel,
- it should usually be exactly a single page, see Linux
- Documentation/flexible-arrays.txt).
- Allocation can be done in batch using @var{sHT_block_alloc_batch} and
- @var{sHT_block_free_batch}, or one at a time with @var{sHT_block_alloc}
- and @var{sHT_block_free}.
- This API is effectively an abstraction with a specification around:
- Unix userspace: mmap(2) or malloc(3).
- W32: VirtualAlloc(2).
- Linux kernel: alloc_pages (requires little pages). */
- #ifndef _WIN32
- /** A special value indicating a memory allocation failure, returned
- by @var{sHT_block_alloc}. It is not necessarily @code{NULL}.
- TODO: this is NULL on W32
- (<https://msdn.microsoft.com/en-us/library/Aa366887(v=VS.85).aspx>). */
- #define sHT_BLOCK_ALLOC_FAILED (MAP_FAILED)
- #else
- #define sHT_BLOCK_ALLOC_FAILED (NULL)
- #endif
- /** A minimal alignment of a blocks address.
- The actual alignment may be higher. */
- #define sHT_BLOCK_ALIGN 4096
- /** Try to allocate a memory block
- @var{size}: a positive number, a minimum on the number of bytes of the block
- If the function call is cancelled (e.g. by pthread_cancel(3)) or jumped over
- and not restored (e.g. by longjmp(3) from a signal handler), a block of
- memory of @var{size} bytes or a bit more may be leaked within the process.
- On an out-of-memory condition, the despeculated return value is
- @var{sHT_BLOCK_ALLOC_FAILED}. Else, it is a fresh block that can be freed
- by @var{sHT_block_free}. */
- void *
- sHT_block_alloc(size_t size);
- /** Free a single memory block
- @var{block}: the block to free
- @var{size}: the size of the block
- On a speculative execution, the block might actually not be freed.
- If cancelled (e.g. by pthread_cancel(3)) or jumped over (e.g. by longjmp(3)
- from a signal handler), the block may or may not be freed, resulting in a
- memory leak within the process of at most @var{size} plus delta. */
- void
- sHT_block_free(void *block, size_t size);
- /** Try to allocate @var{n} memory blocks of particular sizes
- @var{n}: the length of @var{dest} and @var{sizes}
- @var{dest}: a list of block pointers to write. May not be accessed
- concurrently.
- @var{sizes}: a list of the positive sizes of each block to allocate, in the
- same order as @var{dest}. May not be modified.
- On a speculative execution, more or less blocks may actually be allocated
- and the return value may be incorrect. On a non-speculative execution,
- a return value of 1 indicates that the blocks could not be allocated as
- requested. Then there is no net change is memory consumption except for
- some change. 0 indicates all blocks were allocated.
- If cancelled (e.g. by pthread_cancel(3)) or jumped over (e.g. by longjmp(3)
- from a signal handler), there may be a memory leak within the process of at
- most the sum of @var{sizes} plus delta. */
- _Bool
- sHT_block_alloc_batch(size_t n, void *dest[], const size_t sizes[]);
- /** Free the memory blocks in @var{dest}
- @var{n}: the number of elements in @var{dest} and @var{sizes}
- @var{dest}: a readable list of distinct, allocated blocks to free.
- May not be accessed concurrently.
- @var{sizes}: a readable list of the size of each block of @var{dest},
- in the same order. May not be modified concurrently.
- Some elements of @var{dest} are freed. On a non-speculative execution,
- all are freed.
- If cancelled (e.g. by pthread_cancel(3)) or jumped over (e.g. by longjmp(3)
- from a signal handler), there may be a memory leak within the process of at
- most the sum of @var{sizes} plus delta.
- On a non-speculative execution, all are freed. Otherwise, it might only be
- a subset. */
- void
- sHT_block_free_batch(size_t n, void *const dest[], const size_t sizes[]);
- #endif
|