resource.h 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* shttpd - allocating memory of various types
  2. Copyright (C) 2018 Ariadne Devos
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  13. #ifndef _sHT_RESOURCE_H
  14. #define _sHT_RESOURCE_H
  15. #include <stddef.h>
  16. /** Object caches
  17. s2's object caches allocate pre-allocated objects of fixed size. They
  18. are akin to slabs and object pools, but subtly different.
  19. A slab's memory is allocated on-demand[SLAB], whereas in a cache, it
  20. is done in advance, when s2 boots or loads a module. That seems to
  21. be the only conceptual difference, although this causes many
  22. repercussions in the implementation.
  23. Why this inflexibility? If s2 is the only application, it can allocate
  24. as it pleases. If there are other applications that allocate memory
  25. on-demand, s2 services could be unpredictably unavailable, which is not
  26. reliable -- but s2 must be, up to a configurable value of load.
  27. (This could be less rigid. E.g., the object cache may be grown
  28. opportunistically for non-critical tasks. But s2 allows for spawning
  29. new, independent but cooperating processes, so this is not a problem.
  30. In fact, this forms automatic tests.)
  31. [SLAB]: The Slab Allocator: An Object-Caching Kernel Memory Allocator
  32. by Jeff Bonwick, Sun Microsystems.
  33. It is assumed that there is no shortage of virtual memory.
  34. * Usage
  35. Caches are initialised with @var{sHT_objcache_bless_batch}. It does not
  36. allocate memory itself, rather, it takes a block of memory to use.
  37. @var{sHT_objcache_size_batch} calculates how large the blocks must be.
  38. @var{sHT_alloc} tries to allocates an object from a cache.
  39. @var{sHT_free} frees the object, making it available for later operations.
  40. Caches do not have to be freed. While in use, however, they require the
  41. block to remain available. In particular, the objects are allocated from
  42. the block. */
  43. struct sHT_objcache;
  44. /** Calculate the size of the memory blocks the object caches need
  45. @var{n}: the number of caches to calculate the size for, positive
  46. @var{size}: an writable array to put the calculated cache size in, in the
  47. same order as @var{capacity} and @var{elem_size}, of length @var{n} and
  48. not accessed concurrently
  49. @var{capacity}: an array of the numbers of distinct objects that can be
  50. allocated from the cache, of length @var{n}, readable and unchanging
  51. @var{elem_size}: an array of the sizes of each object that can be
  52. allocated from the cache, of length @var{n}, readable and unchanging
  53. The return value is non-negative and less than or equal to @var{n}. Name
  54. it @var{i}. At least @var{i} elements of @var{size} are set, although they
  55. may speculatively be incorrect. On a non-speculative execution, @var{i}
  56. being less than @var{n} signifies an overflow condition, implying the
  57. hypothetical memory block isn't allocatable.
  58. Once @var{i} is despeculated, if it is equal to @var{n}, the elements of
  59. @var{size} are correct.
  60. (Strictly speaking, a memory block could span multiple caches. Would that
  61. be a good idea? Less syscalls, less TLB pressure, less padding overhead,
  62. higher portability, but also less bug detection and more predictability
  63. for attackers.) */
  64. size_t
  65. sHT_objcache_size_batch(size_t n, size_t size[], const size_t capacity[], const size_t elem_size[]);
  66. /** Bless some memory blocks into caches
  67. @var{n}: the number of blocks to bless into caches, positive
  68. @var{cache}: a readable, unchanging array of distinct memory blocks
  69. / caches-to-be, in the same order as @var{capacity} and @var{elem_size},
  70. that can be written to, read from after writing, and are not accessed
  71. concurrently, of size returned by @var{sHT_objcache_size_batch}...
  72. @var{capacity}: the capacity of each cache, unchanging and readable
  73. for the duration of this call, disjoint from @var{cache}
  74. @var{elem_size}: the size of an element in each cache, unchanging and
  75. readable for the duration of this call, disjoint from @var{cache}
  76. The return value is non-negative and less than or equal to @var{n}. Name
  77. it @var{i}. At least @var{i} elements of @var{cache} are set, although they
  78. may speculatively be incorrect. On a non-speculative execution, @var{i} is
  79. @var{n}. */
  80. size_t
  81. sHT_objcache_bless_batch(size_t n, void *cache[], const size_t capacity[], const size_t elem_size[]);
  82. /** Try to allocate a fresh object from an object cache.
  83. @var{cache}: the object cache to utilise
  84. The object will have the size specified by @var{sHT_alloc_cache},
  85. and at least standard alignment (i.e. @code{_Alignof(max_align_t)}}.
  86. This procedure does not know about signals or POSIX asynchronuous
  87. cancellation.
  88. This may fail by returning @code{NULL} if the object cache is exhausted.
  89. Else, return a fresh object. On a speculative execution, the object may
  90. not be fresh: it may share memory with an already-allocated object of the
  91. cache. If this is a problem in your use cache, you can use
  92. @var{sHT_despeculate}. */
  93. __attribute__((warn_unused_result))
  94. __attribute__((nonnull (1)))
  95. void *
  96. sHT_alloc(struct sHT_objcache *cache);
  97. /** Free an object that belongs to a certain cache.
  98. @var{cache}: the object cache @var{object} was allocated from
  99. @var{object}: the object to free
  100. The object must have been allocated by @var{sHT_alloc} with the same
  101. cache argument. The object will become dangling.
  102. @var{object} speculatively being NULL is also allowed, although that
  103. speculatively messes up statistics.
  104. This procedure does not know about signals or POSIX asynchronuous
  105. cancellation.
  106. This cannot fail in any way. */
  107. __attribute__((nonnull (1)))
  108. void
  109. sHT_free(struct sHT_objcache *cache, void *object);
  110. /** Test if a cache is exhausted.
  111. @var{cache}: the object cache to test
  112. This does not mutate anything.
  113. This procedure does not know about signals or POSIX asynchronuous
  114. cancellation.
  115. This cannot fail in any way. Return 1 if exhausted, 0 otherwise.
  116. An incorrect boolean may be returned on a speculative execution. */
  117. __attribute__((nonnull (1)))
  118. __attribute__((pure))
  119. _Bool
  120. sHT_cache_exhausted_p(struct sHT_objcache *cache);
  121. #endif