]> git.ipfire.org Git - thirdparty/freeswitch.git/commitdiff
FS-10052: [libks] Add experimental ref counting to ks_pool #resolve
authorAnthony Minessale <anthm@freeswitch.org>
Fri, 17 Feb 2017 02:34:43 +0000 (20:34 -0600)
committerAnthony Minessale <anthm@freeswitch.org>
Fri, 17 Feb 2017 02:34:43 +0000 (20:34 -0600)
libs/libks/src/include/ks_pool.h
libs/libks/src/include/ks_types.h
libs/libks/src/ks_pool.c
libs/libks/test/testpools.c

index 9d0ff0fadf9e5c70f613004d466193cdfe64e86f..a8981bf1fcb83f6f35eeb97495b2d013d0f0368c 100644 (file)
@@ -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
  *
index 9e1cba61c07ab73840a40ed881cc2c71c0bdb0c6..74d59c03a0a1ee159bdb1eefeab0e00bdb0e3256 100644 (file)
@@ -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;
index b79a95b18bcba530534eecf04c1054bec37b97c6..49f18d16c3137c33a1cadfe9d2fe28f4eada1ea9 100644 (file)
@@ -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;
 
        /*
index 7edf716308ecdd1ee3e1e29c551041a378f8e26d..170e7f97db7c8a79ea9c1744fa0a0cb73bcecf44 100644 (file)
@@ -4,6 +4,7 @@
 #include <stdio.h>
 #include <string.h>
 #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");