pepper: Better ID allocation algorithm 88/56988/2
authorTaekyun Kim <tkq.kim@samsung.com>
Thu, 14 Jan 2016 06:19:10 +0000 (15:19 +0900)
committerTaekyun Kim <tkq.kim@samsung.com>
Thu, 14 Jan 2016 06:38:18 +0000 (22:38 -0800)
Avoid allocating an ID having same value with recently released IDs.
To do this, we use some upper bits of the ID as an age. When an ID
is reused, the age is increased. This can help detect error cases
where users incorrectly access IDs that has been already destroyed.

But, this does not mean that we are completely safe from the problem.
Some kind of locking mechanism or reference counting is required to
prevent from accessing invalid (most likely dead) IDs.

Change-Id: I218f94566c0f2e63d23df4e8fa1a2890184ca583

src/lib/pepper/pepper-utils.h
src/lib/pepper/utils.c

index 88bc5b6d4191bba93b501ee3f1df6b0a7c38c40c..6889c65a1fb85510b4396065ec4d2798009e754b 100644 (file)
@@ -321,9 +321,11 @@ typedef struct pepper_id_allocator  pepper_id_allocator_t;
 struct pepper_id_allocator
 {
     uint32_t        next_id;
+    uint32_t       *free_ids;
     int             free_id_count;
     int             free_id_size;
-    uint32_t       *free_ids;
+    int             free_id_head;
+    int             free_id_tail;
 };
 
 PEPPER_API void
index 17e279406651c59cb2ec31cc93461dfa41d23807..fe978b0acb213d6882cff1662c7f90ca91f60489 100644 (file)
 
 #include "pepper-utils.h"
 
+#define PEPPER_ID_BITS  24
+#define PEPPER_ID_AGE   (1 << (PEPPER_ID_BITS))
+#define PEPPER_ID_MAX   (0xffffffff >> (32 - PEPPER_ID_BITS))
+
 PEPPER_API void
 pepper_id_allocator_init(pepper_id_allocator_t *allocator)
 {
@@ -45,21 +49,54 @@ pepper_id_allocator_fini(pepper_id_allocator_t *allocator)
 PEPPER_API uint32_t
 pepper_id_allocator_alloc(pepper_id_allocator_t *allocator)
 {
+    uint32_t id;
+
     if (allocator->free_id_count)
-        return allocator->free_ids[--allocator->free_id_count];
+    {
+        /* Increase age of the ID (upper N bits) when reusing it. */
+        id =  allocator->free_ids[allocator->free_id_head++] + PEPPER_ID_AGE;
+        allocator->free_id_count--;
+
+        if (allocator->free_id_head == allocator->free_id_size)
+            allocator->free_id_head = 0;
+    }
+    else
+    {
+        id = allocator->next_id++;
+        PEPPER_CHECK(id <= PEPPER_ID_MAX, return 0, "No available IDs left.\n");
+    }
 
-    return allocator->next_id++;
+    return id;
 }
 
 PEPPER_API void
 pepper_id_allocator_free(pepper_id_allocator_t *allocator, uint32_t id)
 {
-    if (allocator->free_id_size <= allocator->free_id_count)
+    if (allocator->free_id_count == allocator->free_id_size)
     {
+        int i;
+        uint32_t *ids = malloc((allocator->free_id_size + 64) * sizeof(uint32_t));
+
+        for (i = 0; i < allocator->free_id_size; i++)
+        {
+            ids[i] = allocator->free_ids[allocator->free_id_head++];
+
+            if (allocator->free_id_head == allocator->free_id_size)
+                allocator->free_id_head = 0;
+        }
+
+        if (allocator->free_ids)
+            free(allocator->free_ids);
+
+        allocator->free_id_head = 0;
+        allocator->free_id_tail = allocator->free_id_size;
         allocator->free_id_size += 64;
-        allocator->free_ids = realloc(allocator->free_ids,
-                                      allocator->free_id_size * sizeof(uint32_t));
+        allocator->free_ids = ids;
     }
 
-    allocator->free_ids[allocator->free_id_count++] = id;
+    allocator->free_ids[allocator->free_id_tail++] = id;
+    allocator->free_id_count++;
+
+    if (allocator->free_id_tail == allocator->free_id_size)
+        allocator->free_id_tail = 0;
 }