diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile | 2 | ||||
-rw-r--r-- | src/libwapcaplet.c | 91 | ||||
-rwxr-xr-x | src/mempool.c | 147 | ||||
-rwxr-xr-x | src/mempool.h | 22 |
4 files changed, 212 insertions, 50 deletions
diff --git a/src/Makefile b/src/Makefile index 4e03048..870989c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,3 +1,3 @@ -DIR_SOURCES := libwapcaplet.c +DIR_SOURCES := libwapcaplet.c mempool.c include $(NSBUILD)/Makefile.subdir diff --git a/src/libwapcaplet.c b/src/libwapcaplet.c index ecc1fb9..4cbb555 100644 --- a/src/libwapcaplet.c +++ b/src/libwapcaplet.c @@ -10,13 +10,9 @@ #include <string.h> #include <assert.h> +#include "mempool.h" #include "libwapcaplet/libwapcaplet.h" -#ifdef __amigaos4__ -#include <proto/exec.h> -#include <proto/onchipmem.h> -#endif - #ifndef UNUSED #define UNUSED(x) ((x) = (x)) #endif @@ -36,10 +32,12 @@ lwc__calculate_hash(const char *str, size_t len) return z; } -#define STR_OF(str) ((char *)(str + 1)) -#define CSTR_OF(str) ((const char *)(str + 1)) +#define STR_OF(str) ((char *)(str->string)) +#define CSTR_OF(str) ((const char *)(str->string)) #define NR_BUCKETS_DEFAULT (4091) +#define MAX_MEM_POOLS 2 +#define MEM_POOL_BLOCKS (65536) / (sizeof(lwc_string) + sizeof(void *)) typedef struct lwc_context_s { lwc_string ** buckets; @@ -50,55 +48,45 @@ static lwc_context *ctx = NULL; #define LWC_ALLOC(s) malloc(s) #define LWC_FREE(p) free(p) +#define LWC_ALLOC_STR() str_alloc() +#define LWC_FREE_STR(p) str_free(p) -#ifndef __amigaos4__ -#define LWC_ALLOC_BUCKET(s) malloc(s) -#define LWC_FREE_BUCKET(p) free(p) -#else -#define LWC_ALLOC_BUCKET(s) onchipmem_malloc(s) -#define LWC_FREE_BUCKET(p) onchipmem_free(p) +memory_pool_t *mp[MAX_MEM_POOLS] = { NULL, NULL }; -struct Library *ocmb; -struct OCMIFace *IOCM = NULL; -bool using_onchipmem; +typedef lwc_hash (*lwc_hasher)(const char *, size_t); +typedef int (*lwc_strncmp)(const char *, const char *, size_t); +typedef void (*lwc_memcpy)(char *, const char *, size_t); -void *onchipmem_malloc(int s); -void onchipmem_free(void *p); +static void *str_alloc(void); +static void str_free(void *p); -void *onchipmem_malloc(int s) +static void *str_alloc(void) { - /* NB: If using OCM this always allocates 64K, ie. a bucket size of 16384 */ - uint8 *ocm = NULL; - - if((ocmb = IExec->OpenResource("onchipmem.resource"))) { - if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) { - ocm = (uint8 *)IOCM->ObtainOnChipMem(); + void *p; + int i; + + for(i = 0; i < MAX_MEM_POOLS; i++) { + if(mp[i] == NULL) { + mp[i] = memory_pool_create(sizeof(lwc_string), MEM_POOL_BLOCKS); + if(mp[i] == NULL) return NULL; /* out of memory */ } - } - if(ocm == NULL) { - ocm = malloc(s); - using_onchipmem = false; - } else { - using_onchipmem = true; + if((p = memory_pool_alloc(mp[i]))) { + return p; + } } - return ocm; + return NULL; /* out of memory pools */ } -void onchipmem_free(void *p) +static void str_free(void *p) { - if(using_onchipmem == true) { - IOCM->ReleaseOnChipMem(); - IExec->DropInterface((struct Interface *)IOCM); - } else { - free(p); + int i; + + for(i = 0; i < MAX_MEM_POOLS; i++) { + if(memory_pool_free(mp[i], p)) + return; } } -#endif - -typedef lwc_hash (*lwc_hasher)(const char *, size_t); -typedef int (*lwc_strncmp)(const char *, const char *, size_t); -typedef void (*lwc_memcpy)(char *, const char *, size_t); static lwc_error lwc__initialise(void) @@ -114,10 +102,10 @@ lwc__initialise(void) memset(ctx, 0, sizeof(lwc_context)); ctx->bucketcount = NR_BUCKETS_DEFAULT; - ctx->buckets = LWC_ALLOC_BUCKET(sizeof(lwc_string *) * ctx->bucketcount); + ctx->buckets = LWC_ALLOC(sizeof(lwc_string *) * ctx->bucketcount); if (ctx->buckets == NULL) { - LWC_FREE_BUCKET(ctx); + LWC_FREE(ctx); ctx = NULL; return lwc_error_oom; } @@ -163,12 +151,16 @@ lwc__intern(const char *s, size_t slen, str = str->next; } - /* Add one for the additional NUL. */ - *ret = str = LWC_ALLOC(sizeof(lwc_string) + slen + 1); + *ret = str = LWC_ALLOC_STR(); if (str == NULL) return lwc_error_oom; - + + /* Add one for the additional NUL. */ + str->string = LWC_ALLOC(slen + 1); + if (str->string == NULL) + return lwc_error_oom; + str->prevptr = &(ctx->buckets[bucket]); str->next = ctx->buckets[bucket]; if (str->next != NULL) @@ -230,7 +222,8 @@ lwc_string_destroy(lwc_string *str) memset(str, 0xA5, sizeof(*str) + str->len); #endif - LWC_FREE(str); + LWC_FREE_STR(str); + LWC_FREE(STR_OF(str)); } /**** Shonky caseless bits ****/ diff --git a/src/mempool.c b/src/mempool.c new file mode 100755 index 0000000..5dc5498 --- /dev/null +++ b/src/mempool.c @@ -0,0 +1,147 @@ +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <stdint.h> +#include "mempool.h" + +#ifdef __amigaos4__ +#include <proto/exec.h> +#include <proto/onchipmem.h> + +struct Library *ocmb; +struct OCMIFace *IOCM = NULL; +#endif + +#define MEMORY_POOL_ALLOCED_CONST ((void *) 0xFFFFFFFFu) + +memory_pool_t * memory_pool_create(size_t bs, size_t c) +{ + memory_pool_t *mp = malloc(sizeof(memory_pool_t)); + if (!mp) + return NULL; + + mp->block_size = bs; + mp->count = c; + mp->pool = NULL; + + if((ocmb = IExec->OpenResource("onchipmem.resource"))) { + if((IOCM = (struct OCMIFace *)IExec->GetInterface((struct Library *)ocmb, "main", 1, NULL))) { + mp->pool = IOCM->ObtainOnChipMem(); + } + } + + if(mp->pool == NULL) { + mp->pool = malloc((mp->block_size + sizeof(void *)) * mp->count); + } + + memory_pool_clear(mp); + + mp->empty_blocks = mp->pool; + + return mp; +} + +void memory_pool_destroy(memory_pool_t *mp) +{ + if (!mp) + return; + + memory_pool_clear(mp); + +/**TODO: Track if this is an OCM or standard memory pool. + * At the moment we have no way of freeing on exit so it doesn't matter. + + IOCM->ReleaseOnChipMem(); + IExec->DropInterface((struct Interface *)IOCM); + free(mp->pool); +*/ + free(mp); +} + +void memory_pool_clear(memory_pool_t *mp) +{ + if (!mp) + return; + + size_t i; + void **p; + + for (i = 0; i < mp->count - 1; i++) + { + p = (void **) ((uint8_t *) mp->pool + (mp->block_size * (i + 1) + + sizeof(void *) * i)); + *p = (uint8_t *) mp->pool + (mp->block_size + sizeof(void *)) * (i + 1); + } + + p = (void **) ((uint8_t *) mp->pool + (mp->block_size * mp->count + + sizeof(void *) * (mp->count - 1))); + *p = NULL; + + mp->empty_blocks = mp->pool; +} + +void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value)) +{ + printf("start: %p, size: %d, count: %d\n", mp->pool, + (mp->block_size + sizeof(void *)) * mp->count, mp->count); + + void *block; + void **next; + size_t i; + + for (i = 0; i < mp->count; i++) + { + block = (void *) ((uint8_t *) mp->pool + (mp->block_size * i) + + sizeof(void *) * i); + next = (void **) ((uint8_t *) block + sizeof(void *)); + + printf("block #%i(%p):", i, block); + + if (*next == MEMORY_POOL_ALLOCED_CONST) + { + printf(" allocated"); + + if (print_func) + { + printf(", value: "); + print_func(block); + } + + printf("\n"); + } else + { + printf(" free, next address %p\n", *next); + } + } +} + +void * memory_pool_alloc(memory_pool_t *mp) +{ + void *p; + + if (mp->empty_blocks) + { + p = mp->empty_blocks; + mp->empty_blocks = * (void **) ((uint8_t *) mp->empty_blocks + + mp->block_size); + *(void **) ((uint8_t *) p + mp->block_size) = MEMORY_POOL_ALLOCED_CONST; + return p; + } else + { + return NULL; + } +} + +bool memory_pool_free(memory_pool_t *mp, void *p) +{ + if (p && (p >= mp->pool) && (p <= (void *) ((uint8_t *) mp->pool + + (mp->block_size + sizeof(void *)) * mp->count))) + { + *(void **) ((uint8_t *) p + mp->block_size) = mp->empty_blocks; + mp->empty_blocks = p; + return true; + } else { + return false; + } +} + diff --git a/src/mempool.h b/src/mempool.h new file mode 100755 index 0000000..c99f239 --- /dev/null +++ b/src/mempool.h @@ -0,0 +1,22 @@ +#ifndef MEMPOOL_H
+#define MEMPOOL_H 1
+
+#include <stdlib.h>
+#include <stdint.h>
+#include <stdbool.h>
+
+typedef struct memory_pool_s
+{
+ void *pool;
+ void *empty_blocks;
+ size_t block_size;
+ size_t count;
+} __attribute__ ((__aligned__)) memory_pool_t;
+
+memory_pool_t * memory_pool_create(size_t bs, size_t c);
+void memory_pool_destroy(memory_pool_t *mp);
+void memory_pool_clear(memory_pool_t *mp);
+void memory_pool_dump(memory_pool_t *mp, void (* print_func) (void *value));
+void *memory_pool_alloc(memory_pool_t *mp);
+bool memory_pool_free(memory_pool_t *mp, void *p);
+#endif /* MEMPOOL_H */
|