parent
29af1d7fa5
commit
a6689c4823
@ -0,0 +1,109 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <errno.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#include "debuglog.h"
|
||||
#include "types.h" /* PAGE_SIZE */
|
||||
|
||||
struct buffer {
|
||||
uint32_t size;
|
||||
uint64_t max;
|
||||
uint8_t data[];
|
||||
};
|
||||
|
||||
static inline struct buffer *
|
||||
buffer_allocate(size_t initial, size_t max)
|
||||
{
|
||||
char * error_message = NULL;
|
||||
int rc = 0;
|
||||
struct buffer *self = NULL;
|
||||
assert(initial > 0);
|
||||
assert(max > 0);
|
||||
|
||||
size_t size_to_alloc = sizeof(struct buffer) + max + /* guard page */ PAGE_SIZE;
|
||||
// assert(round_up_to_page(size_to_alloc) == size_to_alloc);
|
||||
|
||||
void *addr = mmap(NULL, size_to_alloc, PROT_NONE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
if (addr == MAP_FAILED) {
|
||||
debuglog("buffer_allocate - allocation failed, (size: %lu) %s\n", size_to_alloc, strerror(errno));
|
||||
return self;
|
||||
}
|
||||
|
||||
/* Set as read / write */
|
||||
size_t size_to_read_write = sizeof(struct buffer) + initial;
|
||||
|
||||
void *addr_rw = mmap(addr, size_to_read_write, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
|
||||
-1, 0);
|
||||
if (addr_rw == MAP_FAILED) {
|
||||
perror("buffer_allocate - prot r/w failed");
|
||||
munmap(addr, size_to_alloc);
|
||||
return self;
|
||||
}
|
||||
|
||||
|
||||
self = (struct buffer *)addr_rw;
|
||||
self->max = max;
|
||||
self->size = initial;
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void
|
||||
buffer_free(struct buffer *self)
|
||||
{
|
||||
size_t size_to_free = sizeof(struct buffer) + self->max + /* guard page */ PAGE_SIZE;
|
||||
munmap(self, size_to_free);
|
||||
}
|
||||
|
||||
|
||||
static inline int
|
||||
buffer_expand(struct buffer *self, size_t size_to_expand)
|
||||
{
|
||||
if (unlikely(self->size + size_to_expand >= self->max)) {
|
||||
debuglog("buffer_expand - Out of Memory!. %u out of %lu\n", self->size, self->max);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *temp = mmap(self, sizeof(struct buffer) + self->size + size_to_expand, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
|
||||
if (temp == NULL) {
|
||||
perror("buffer_expand mmap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Assumption: We are not actually resizing our buffer capacity. We are just adjusting the R/W rules within a
|
||||
* preallocated buffer of size max */
|
||||
assert(self == temp);
|
||||
|
||||
self->size += size_to_expand;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
buffer_resize(struct buffer *self, size_t target_size)
|
||||
{
|
||||
if (unlikely(target_size >= self->max)) {
|
||||
debuglog("buffer_expand - Out of Memory!. %u out of %lu\n", self->size, self->max);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *temp = mmap(self, sizeof(struct buffer) + target_size, PROT_READ | PROT_WRITE,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
|
||||
|
||||
if (temp == NULL) {
|
||||
perror("buffer_resize mmap");
|
||||
return -1;
|
||||
}
|
||||
|
||||
assert(self == temp);
|
||||
|
||||
/* Assumption: We are not actually resizing our buffer capacity. We are just adjusting the R/W rules within a
|
||||
* preallocated buffer of size max */
|
||||
self->size = target_size;
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,118 @@
|
||||
#pragma once
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "generic_thread.h"
|
||||
#include "lock.h"
|
||||
|
||||
struct pool {
|
||||
bool use_lock;
|
||||
lock_t lock;
|
||||
ssize_t top;
|
||||
size_t capacity;
|
||||
void * buffer[];
|
||||
};
|
||||
|
||||
static inline bool
|
||||
pool_is_empty(struct pool *self)
|
||||
{
|
||||
return self->top == -1;
|
||||
}
|
||||
|
||||
static inline bool
|
||||
pool_is_full(struct pool *self)
|
||||
{
|
||||
return self->top + 1 == self->capacity;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
pool_allocate_object_nolock(struct pool *self)
|
||||
{
|
||||
assert(self != NULL);
|
||||
assert(!self->use_lock || LOCK_IS_LOCKED(&self->lock));
|
||||
|
||||
void *result = NULL;
|
||||
|
||||
if (pool_is_empty(self)) return result;
|
||||
|
||||
result = self->buffer[self->top--];
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline void *
|
||||
pool_allocate_object(struct pool *self)
|
||||
{
|
||||
assert(self != NULL);
|
||||
assert(self->use_lock);
|
||||
|
||||
void *result = NULL;
|
||||
|
||||
if (pool_is_empty(self)) return result;
|
||||
|
||||
LOCK_LOCK(&self->lock);
|
||||
if (pool_is_empty(self)) {
|
||||
LOCK_UNLOCK(&self->lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
result = self->buffer[self->top--];
|
||||
assert(result != NULL);
|
||||
LOCK_UNLOCK(&self->lock);
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int
|
||||
pool_free_object_nolock(struct pool *self, void *obj)
|
||||
{
|
||||
assert(self != NULL);
|
||||
assert(obj != NULL);
|
||||
assert(!self->use_lock || LOCK_IS_LOCKED(&self->lock));
|
||||
|
||||
if (pool_is_full(self)) return -1;
|
||||
|
||||
self->buffer[++self->top] = obj;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int
|
||||
pool_free_object(struct pool *self, void *obj)
|
||||
{
|
||||
assert(self != NULL);
|
||||
assert(obj != NULL);
|
||||
assert(self->use_lock);
|
||||
|
||||
if (pool_is_full(self)) return -1;
|
||||
|
||||
LOCK_LOCK(&self->lock);
|
||||
if (pool_is_full(self)) {
|
||||
LOCK_UNLOCK(&self->lock);
|
||||
return -1;
|
||||
}
|
||||
|
||||
self->buffer[++self->top] = obj;
|
||||
LOCK_UNLOCK(&self->lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline struct pool *
|
||||
pool_init(size_t capacity, bool use_lock)
|
||||
{
|
||||
struct pool *self = (struct pool *)calloc(1, sizeof(struct pool) + capacity * sizeof(void *));
|
||||
self->top = -1;
|
||||
self->capacity = capacity;
|
||||
self->use_lock = use_lock;
|
||||
|
||||
if (use_lock) LOCK_INIT(&self->lock);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
static inline void
|
||||
pool_free(struct pool *self)
|
||||
{
|
||||
while (!pool_is_empty(self)) free(pool_allocate_object(self));
|
||||
|
||||
free(self);
|
||||
}
|
@ -0,0 +1,3 @@
|
||||
#include "pool.h"
|
||||
|
||||
struct pool **runtime_linear_memory_pools;
|
Loading…
Reference in new issue