diff --git a/libs/libks/src/include/ks_pool.h b/libs/libks/src/include/ks_pool.h index 9d0ff0fadf..a8981bf1fc 100644 --- a/libs/libks/src/include/ks_pool.h +++ b/libs/libks/src/include/ks_pool.h @@ -67,6 +67,8 @@ typedef enum { #define KS_POOL_FUNC_CALLOC 4 /* ks_pool_calloc function called */ #define KS_POOL_FUNC_FREE 5 /* ks_pool_free function called */ #define KS_POOL_FUNC_RESIZE 6 /* ks_pool_resize function called */ +#define KS_POOL_FUNC_INCREF 7 /* reference count incremented */ +#define KS_POOL_FUNC_DECREF 8 /* reference count decremented */ /* * void ks_pool_log_func_t @@ -293,6 +295,34 @@ KS_DECLARE(void *) ks_pool_calloc_ex(ks_pool_t *mp_p, const unsigned long ele_n, KS_DECLARE(ks_status_t) ks_pool_free_ex(ks_pool_t *mp_p, void **addrP); + +/* + * void *ks_pool_ref_ex + * + * DESCRIPTION: + * + * Ref count increment an address in a memoory pool. + * + * RETURNS: + * + * Success - The same pointer + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * addr -> The addr to ref + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a ks_pool error code. + */ + +KS_DECLARE(void *) ks_pool_ref_ex(ks_pool_t *mp_p, void *addr, ks_status_t *error_p); + +#define ks_pool_ref(_p, _x) ks_pool_ref_ex(_p, _x, NULL) + /* * void *ks_pool_resize * diff --git a/libs/libks/src/include/ks_types.h b/libs/libks/src/include/ks_types.h index 9e1cba61c0..74d59c03a0 100644 --- a/libs/libks/src/include/ks_types.h +++ b/libs/libks/src/include/ks_types.h @@ -85,6 +85,7 @@ KS_BEGIN_EXTERN_C KS_STATUS_INACTIVE, KS_STATUS_TIMEOUT, /* Memory pool errors */ + KS_STATUS_REFS_EXIST, /* references exist */ KS_STATUS_ARG_NULL, /* function argument is null */ KS_STATUS_ARG_INVALID, /* function argument is invalid */ KS_STATUS_PNT, /* invalid ks_pool pointer */ @@ -105,6 +106,7 @@ KS_BEGIN_EXTERN_C KS_STATUS_ALLOC, /* calloc,malloc,free,realloc failed */ KS_STATUS_PNT_OVER, /* pointer structure was overwritten */ KS_STATUS_INVALID_POINTER, /* address is not valid */ + KS_STATUS_NOT_ALLOWED, /* operation is not allowed */ /* Always insert new entries above this line*/ KS_STATUS_COUNT } ks_status_t; diff --git a/libs/libks/src/ks_pool.c b/libs/libks/src/ks_pool.c index b79a95b18b..49f18d16c3 100644 --- a/libs/libks/src/ks_pool.c +++ b/libs/libks/src/ks_pool.c @@ -52,6 +52,7 @@ typedef struct alloc_prefix_s { unsigned char m1; unsigned long size; unsigned char m2; + unsigned int refs; } alloc_prefix_t; #define PREFIX_SIZE sizeof(struct alloc_prefix_s) @@ -949,6 +950,12 @@ static void *alloc_mem(ks_pool_t *mp_p, const unsigned long byte_size, ks_status prefix->m1 = PRE_MAGIC1; prefix->m2 = PRE_MAGIC2; prefix->size = size; + prefix->refs++; + + if (mp_p->mp_log_func != NULL) { + alloc_prefix_t *prefix = (alloc_prefix_t *) ((char *) addr - PREFIX_SIZE); + mp_p->mp_log_func(mp_p, KS_POOL_FUNC_INCREF, prefix->size, prefix->refs, NULL, addr, 0); + } /* maintain our stats */ mp_p->mp_alloc_c++; @@ -995,6 +1002,14 @@ static int free_mem(ks_pool_t *mp_p, void *addr) return KS_STATUS_INVALID_POINTER; } + if (prefix->refs > 0) { + prefix->refs--; + } + + if (prefix->refs > 0) { + return KS_STATUS_REFS_EXIST; + } + size = prefix->size; /* @@ -1645,7 +1660,11 @@ KS_DECLARE(ks_status_t) ks_pool_free_ex(ks_pool_t *mp_p, void **addrP) if (mp_p->mp_log_func != NULL) { alloc_prefix_t *prefix = (alloc_prefix_t *) ((char *) addr - PREFIX_SIZE); - mp_p->mp_log_func(mp_p, KS_POOL_FUNC_FREE, prefix->size, 0, NULL, addr, 0); + if (prefix->refs == 1) { + mp_p->mp_log_func(mp_p, KS_POOL_FUNC_FREE, prefix->size, prefix->refs - 1, NULL, addr, 0); + } else { + mp_p->mp_log_func(mp_p, KS_POOL_FUNC_DECREF, prefix->size, prefix->refs - 1, NULL, addr, 0); + } } r = free_mem(mp_p, addr); @@ -1662,13 +1681,68 @@ KS_DECLARE(ks_status_t) ks_pool_free_ex(ks_pool_t *mp_p, void **addrP) } +/* + * void *ks_pool_ref_ex + * + * DESCRIPTION: + * + * Ref count increment an address in a memoory pool. + * + * RETURNS: + * + * Success - The same pointer + * + * Failure - NULL + * + * ARGUMENTS: + * + * mp_p <-> Pointer to the memory pool. + * + * addr -> The addr to ref + * + * error_p <- Pointer to integer which, if not NULL, will be set with + * a ks_pool error code. + */ +KS_DECLARE(void *) ks_pool_ref_ex(ks_pool_t *mp_p, void *addr, ks_status_t *error_p) +{ + alloc_prefix_t *prefix; + + if (mp_p->mp_magic != KS_POOL_MAGIC) { + SET_POINTER(error_p, KS_STATUS_PNT); + return NULL; + } + + if (mp_p->mp_magic2 != KS_POOL_MAGIC) { + SET_POINTER(error_p, KS_STATUS_POOL_OVER); + return NULL; + } + + ks_mutex_lock(mp_p->mutex); + prefix = (alloc_prefix_t *) ((char *) addr - PREFIX_SIZE); + + if (!(prefix->m1 == PRE_MAGIC1 && prefix->m2 == PRE_MAGIC2)) { + SET_POINTER(error_p, KS_STATUS_INVALID_POINTER); + return NULL; + } + + prefix->refs++; + + if (mp_p->mp_log_func != NULL) { + alloc_prefix_t *prefix = (alloc_prefix_t *) ((char *) addr - PREFIX_SIZE); + mp_p->mp_log_func(mp_p, KS_POOL_FUNC_INCREF, prefix->size, prefix->refs, NULL, addr, 0); + } + + ks_mutex_unlock(mp_p->mutex); + + return addr; +} + /* * void *ks_pool_resize_ex * * DESCRIPTION: * - * Reallocate an address in a mmeory pool to a new size. This is - * different from realloc in that it needs the old address' size. + * Reallocate an address in a memory pool to a new size. This is * * RETURNS: * @@ -1722,6 +1796,12 @@ KS_DECLARE(void *) ks_pool_resize_ex(ks_pool_t *mp_p, void *old_addr, const unsi ks_mutex_lock(mp_p->mutex); + + if (prefix->refs > 1) { + SET_POINTER(error_p,KS_STATUS_NOT_ALLOWED); + return NULL; + } + old_byte_size = prefix->size; /* diff --git a/libs/libks/test/testpools.c b/libs/libks/test/testpools.c index 7edf716308..170e7f97db 100644 --- a/libs/libks/test/testpools.c +++ b/libs/libks/test/testpools.c @@ -4,6 +4,7 @@ #include #include #include "tap.h" +#define STR "ABCDEFGHIJKLMNOPQRSTUVWXYZ" static void fill(char *str, int bytes, char c) { @@ -48,7 +49,7 @@ int main(int argc, char **argv) ks_init(); - plan(11); + plan(14); if (argc > 1) { int tmp = atoi(argv[1]); @@ -100,10 +101,38 @@ int main(int argc, char **argv) exit(255); } - fill(str, bytes, '-'); + + ks_snprintf(str, bytes, "%s", STR); printf("%s\n", str); + printf("ALLOC3 (refs):\n"); + + str = ks_pool_ref(pool, str); + + printf("STR [%s]\n", str); + + ks_pool_free(pool, &str); + + ok(str != NULL && !strcmp(str, STR)); + + printf("STR [%s]\n", str); + + ks_pool_free(pool, &str); + + ok(str == NULL); + + str = ks_pool_alloc(pool, bytes); + + ok(str != NULL); + if (!str) { + fprintf(stderr, "ALLOC2 ERR: [FAILED]\n"); + exit(255); + } + + fill(str, bytes, '-'); + printf("%s\n", str); + printf("ALLOC OBJ:\n"); foo = ks_pool_alloc(pool, sizeof(struct foo)); @@ -168,13 +197,13 @@ int main(int argc, char **argv) printf("RESIZE:\n"); - ks_snprintf(str, bytes, "%s", "ABCDEFGHIJKLM"); + ks_snprintf(str, bytes, "%s", STR); printf("1 STR [%s]\n", str); bytes *= 2; str = ks_pool_resize(pool, str, bytes); printf("2 STR [%s]\n", str); - ok(!strcmp(str, "ABCDEFGHIJKLM")); + ok(!strcmp(str, STR)); if (!str) { fprintf(stderr, "RESIZE ERR: [FAILED]\n");