aboutsummaryrefslogtreecommitdiff
path: root/src/modules/dataman
diff options
context:
space:
mode:
authorJean Cyr <jcyr@dillobits.com>2014-05-13 19:59:44 -0400
committerJean Cyr <jcyr@dillobits.com>2014-05-13 19:59:44 -0400
commit8d3fed09443faa6a3c79b68b7800ed3472877a1c (patch)
tree68df28fda657261eb21215941fcfbca2965284a6 /src/modules/dataman
parent178a3e8567b3e721771fffcb8f32df140ad1038b (diff)
downloadpx4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.tar.gz
px4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.tar.bz2
px4-firmware-8d3fed09443faa6a3c79b68b7800ed3472877a1c.zip
Reduce potential dataman memory fragmentation
The data manager dynamically allocates relatively small work item blocks on an as needed basis. It never frees these, instead maintaining then in a list of available block for reuse when needed. Even if these blocks are small, the are required at non-deterministic times and can end up scattered in memory thus causing memory fragmentation. In order to mitigate this problems work item blocks are allocated in groups of 8 in contiguous memory to reduce the number of scattered memory allocations. In reality, based on current usage, rarely will more than one group of 8 be allocated.
Diffstat (limited to 'src/modules/dataman')
-rw-r--r--src/modules/dataman/dataman.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/src/modules/dataman/dataman.c b/src/modules/dataman/dataman.c
index 7505ba358..cbd9b2d7c 100644
--- a/src/modules/dataman/dataman.c
+++ b/src/modules/dataman/dataman.c
@@ -100,6 +100,8 @@ typedef struct {
};
} work_q_item_t;
+const size_t k_work_item_allocation_chunk_size = 8;
+
/* Usage statistics */
static unsigned g_func_counts[dm_number_of_funcs];
@@ -177,9 +179,20 @@ create_work_item(void)
unlock_queue(&g_free_q);
- /* If we there weren't any free items then obtain memory for a new one */
- if (item == NULL)
- item = (work_q_item_t *)malloc(sizeof(work_q_item_t));
+ /* If we there weren't any free items then obtain memory for a new ones */
+ if (item == NULL) {
+ item = (work_q_item_t *)malloc(k_work_item_allocation_chunk_size * sizeof(work_q_item_t));
+ if (item) {
+ lock_queue(&g_free_q);
+ for (int i = 1; i < k_work_item_allocation_chunk_size; i++)
+ sq_addfirst(&(item + i)->link, &(g_free_q.q));
+ /* Update the queue size and potentially the maximum queue size */
+ g_free_q.size += k_work_item_allocation_chunk_size - 1;
+ if (g_free_q.size > g_free_q.max_size)
+ g_free_q.max_size = g_free_q.size;
+ unlock_queue(&g_free_q);
+ }
+ }
/* If we got one then lock the item*/
if (item)