ndppd/src/alloc.c
2019-12-14 01:22:57 +01:00

91 lines
2.2 KiB
C

// This file is part of ndppd.
//
// Copyright (C) 2011-2019 Daniel Adolfsson <daniel@ashen.se>
//
// ndppd is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// ndppd is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with ndppd. If not, see <https://www.gnu.org/licenses/>.
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#ifndef NDPPD_ALLOC_SIZE
# define NDPPD_ALLOC_SIZE 16384
#endif
#include "alloc.h"
#include "ndppd.h"
typedef struct ndL_chunk ndL_chunk_t;
struct ndL_chunk
{
ndL_chunk_t *next;
size_t free;
size_t size;
};
static ndL_chunk_t *ndL_chunks;
static size_t ndL_alloc_size = NDPPD_ALLOC_SIZE;
char *nd_strdup(const char *str)
{
size_t len = strlen(str);
char *buf = (char *)nd_alloc(len + 1);
strcpy(buf, str);
return buf;
}
void *nd_alloc(size_t size)
{
assert(size > 0 && size < 512);
// To keep everything properly aligned, we'll make sure it's multiple of 8.
size = (size + 7U) & ~7U;
for (ndL_chunk_t *chunk = ndL_chunks; chunk; chunk = chunk->next)
{
if (chunk->free >= size)
{
void *ptr = (void *)chunk + chunk->size - chunk->free;
chunk->free -= size;
return ptr;
}
}
ndL_chunk_t *chunk = (ndL_chunk_t *)calloc(1, ndL_alloc_size);
/* Should never happen. */
if (chunk == NULL)
abort();
chunk->next = ndL_chunks;
chunk->size = ndL_alloc_size;
chunk->free = ndL_alloc_size - ((sizeof(ndL_chunk_t) + 7U) & ~7U);
ndL_chunks = chunk;
ndL_alloc_size *= 2;
void *ptr = (void *)chunk + chunk->size - chunk->free;
chunk->free -= size;
return ptr;
}
void nd_alloc_cleanup()
{
ND_LL_FOREACH_S(ndL_chunks, chunk, tmp, next)
{
free(chunk);
}
}