Skip to content

Commit

Permalink
Merge pull request #2 from discosat/memory-management
Browse files Browse the repository at this point in the history
Add portable memory management functions
  • Loading branch information
NValsted authored Apr 16, 2024
2 parents ef14513 + 811a1f1 commit 6e75379
Show file tree
Hide file tree
Showing 17 changed files with 232 additions and 89 deletions.
24 changes: 24 additions & 0 deletions include/csp_proc/proc_memory.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
#ifndef CSP_PROC_MEMORY_H
#define CSP_PROC_MEMORY_H

#include <stddef.h>

#ifdef __cplusplus
extern "C" {
#endif

void * proc_malloc(size_t size);

void * proc_calloc(size_t num, size_t size);

void * proc_realloc(void * ptr, size_t size);

void proc_free(void * ptr);

char * proc_strdup(const char * str);

#ifdef __cplusplus
}
#endif

#endif // CSP_PROC_MEMORY_H
6 changes: 4 additions & 2 deletions meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -42,13 +42,15 @@ endif

if get_option('posix') == true
csp_proc_src += files([
'src/sync/proc_mutex_POSIX.c',
'src/platform/proc_memory_POSIX.c',
'src/platform/proc_mutex_POSIX.c',
])
endif

if get_option('freertos') == true
csp_proc_src += files([
'src/sync/proc_mutex_FreeRTOS.c',
'src/platform/proc_memory_FreeRTOS.c',
'src/platform/proc_mutex_FreeRTOS.c',
])
endif

Expand Down
83 changes: 83 additions & 0 deletions src/platform/proc_memory_FreeRTOS.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
#include <csp_proc/proc_memory.h>
#include <FreeRTOS.h>

/**
* Allocates a block of memory of the specified size.
* An extra sizeof(size_t) bytes are allocated at the beginning of the block to store the size of the block.
* This is used by proc_realloc to know how much data to copy to the new block.
*/
void * proc_malloc(size_t size) {
size_t * actual_ptr = pvPortMalloc(size + sizeof(size_t));
if (actual_ptr == NULL) {
return NULL;
}
*actual_ptr = size;
return actual_ptr + 1;
}

/**
* Allocates a block of memory for an array of num elements, each of them size bytes long, and initializes all its bits to zero.
* An extra sizeof(size_t) bytes are allocated at the beginning of the block to store the size of the block.
* This is used by proc_realloc to know how much data to copy to the new block.
*/
void * proc_calloc(size_t num, size_t size) {
size_t total_size = num * size;
size_t * actual_ptr = pvPortMalloc(total_size + sizeof(size_t));
if (actual_ptr == NULL) {
return NULL;
}
*actual_ptr = total_size;
memset(actual_ptr + 1, 0, total_size);
return actual_ptr + 1;
}

/**
* Changes the size of the memory block pointed to by ptr to size bytes.
* The function may move the memory block to a new location, in which case the new location is returned.
* The content of the memory block is preserved up to the lesser of the new and old sizes, even if the block is moved.
* If the new size is larger, the value of the newly allocated portion is indeterminate.
* If ptr is NULL, the function behaves like malloc for the specified size.
* If size is zero, the memory previously allocated at ptr is deallocated as if a call to free was made, and a NULL pointer is returned.
*/
void * proc_realloc(void * ptr, size_t size) {
if (size == 0) {
proc_free(ptr);
return NULL;
} else if (ptr == NULL) {
return proc_malloc(size);
} else {
size_t * actual_ptr = (size_t *)ptr - 1;
size_t old_size = *actual_ptr;
size_t * new_ptr = pvPortMalloc(size + sizeof(size_t));
if (new_ptr) {
*new_ptr = size;
memcpy(new_ptr + 1, ptr, old_size < size ? old_size : size);
vPortFree(actual_ptr);
}
return new_ptr ? new_ptr + 1 : NULL;
}
}

/**
* Deallocates the memory previously allocated by proc_malloc, proc_calloc or proc_realloc.
* If ptr is a NULL pointer, no operation is performed.
*/
void proc_free(void * ptr) {
if (ptr) {
size_t * actual_ptr = (size_t *)ptr - 1;
vPortFree(actual_ptr);
}
}

/**
* Allocates a new string which is a duplicate of the string str (strdup).
* The memory for the new string is obtained using proc_malloc.
*/
char * proc_strdup(const char * s) {
size_t len = strlen(s) + 1;
char * new = proc_malloc(len);
if (new == NULL) {
return NULL;
}
return memcpy(new, s, len);
}
22 changes: 22 additions & 0 deletions src/platform/proc_memory_POSIX.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include <csp_proc/proc_memory.h>
#include <stdlib.h>

void * proc_malloc(size_t size) {
return malloc(size);
}

void * proc_calloc(size_t num, size_t size) {
return calloc(num, size);
}

void * proc_realloc(void * ptr, size_t size) {
return realloc(ptr, size);
}

void proc_free(void * ptr) {
free(ptr);
}

char * proc_strdup(const char * str) {
return strdup(str);
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include <csp_proc/proc_mutex.h>
#include <csp_proc/proc_memory.h>
#include <FreeRTOS.h>
#include <semphr.h>

Expand All @@ -7,10 +8,10 @@ struct proc_mutex_t {
};

proc_mutex_t * proc_mutex_create() {
proc_mutex_t * mutex = pvPortMalloc(sizeof(proc_mutex_t));
proc_mutex_t * mutex = proc_malloc(sizeof(proc_mutex_t));
mutex->handle = xSemaphoreCreateMutex();
if (mutex->handle == NULL) {
vPortFree(mutex);
proc_free(mutex);
return NULL;
}
return mutex;
Expand All @@ -32,5 +33,5 @@ int proc_mutex_give(proc_mutex_t * mutex) {

void proc_mutex_destroy(proc_mutex_t * mutex) {
vSemaphoreDelete(mutex->handle);
vPortFree(mutex);
proc_free(mutex);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#include <csp_proc/proc_mutex.h>
#include <csp_proc/proc_memory.h>
#include <pthread.h>

struct proc_mutex_t {
pthread_mutex_t handle;
};

proc_mutex_t * proc_mutex_create() {
proc_mutex_t * mutex = malloc(sizeof(proc_mutex_t));
proc_mutex_t * mutex = proc_malloc(sizeof(proc_mutex_t));
if (pthread_mutex_init(&mutex->handle, NULL) != 0) {
free(mutex);
proc_free(mutex);
return NULL;
}
return mutex;
Expand All @@ -30,5 +31,5 @@ int proc_mutex_give(proc_mutex_t * mutex) {

void proc_mutex_destroy(proc_mutex_t * mutex) {
pthread_mutex_destroy(&mutex->handle);
free(mutex);
proc_free(mutex);
}
19 changes: 10 additions & 9 deletions src/proc_analyze.c
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include <csp_proc/proc_analyze.h>
#include <csp_proc/proc_store.h>
#include <csp_proc/proc_memory.h>

/**
* Free all memory associated with a proc_analysis_t.
Expand All @@ -14,10 +15,10 @@ void free_proc_analysis(proc_analysis_t * analysis) {
}
}

free(analysis->sub_analyses);
free(analysis->procedure_slots);
free(analysis->instruction_analyses);
free(analysis);
proc_free(analysis->sub_analyses);
proc_free(analysis->procedure_slots);
proc_free(analysis->instruction_analyses);
proc_free(analysis);
}

int analyze_tail_call(proc_t * proc, uint8_t i, proc_instruction_analysis_t * instruction_analysis) {
Expand Down Expand Up @@ -90,7 +91,7 @@ int proc_analyze(proc_t * proc, proc_analysis_t * analysis, proc_analysis_config
analysis->procedure_slots = NULL;
analysis->procedure_slot_count = 0;

analysis->instruction_analyses = calloc(proc->instruction_count, sizeof(proc_instruction_analysis_t));
analysis->instruction_analyses = proc_calloc(proc->instruction_count, sizeof(proc_instruction_analysis_t));
if (analysis->instruction_analyses == NULL) {
printf("Error allocating memory for instruction_analyses\n");
return -1;
Expand All @@ -109,7 +110,7 @@ int proc_analyze(proc_t * proc, proc_analysis_t * analysis, proc_analysis_config
if (instruction->type == PROC_CALL) {
// Special handling for call instructions which require recursive analysis

analysis->procedure_slots = realloc(analysis->procedure_slots, (analysis->procedure_slot_count + 1) * sizeof(uint8_t));
analysis->procedure_slots = proc_realloc(analysis->procedure_slots, (analysis->procedure_slot_count + 1) * sizeof(uint8_t));
if (analysis->procedure_slots == NULL) {
printf("Error reallocating memory for procedure_slots\n");
return -1;
Expand All @@ -118,7 +119,7 @@ int proc_analyze(proc_t * proc, proc_analysis_t * analysis, proc_analysis_config
analysis->procedure_slots[analysis->procedure_slot_count] = instruction->instruction.call.procedure_slot;
analysis->procedure_slot_count++;

analysis->sub_analyses = realloc(analysis->sub_analyses, (analysis->sub_analysis_count + 1) * sizeof(proc_analysis_t *));
analysis->sub_analyses = proc_realloc(analysis->sub_analyses, (analysis->sub_analysis_count + 1) * sizeof(proc_analysis_t *));
if (analysis->sub_analyses == NULL) {
printf("Error reallocating memory for sub_analyses\n");
return -1;
Expand All @@ -136,7 +137,7 @@ int proc_analyze(proc_t * proc, proc_analysis_t * analysis, proc_analysis_config
// Procedure is already in the call stack
sub_analysis = config->analyses[instruction->instruction.call.procedure_slot];
} else {
sub_analysis = malloc(sizeof(proc_analysis_t));
sub_analysis = proc_malloc(sizeof(proc_analysis_t));
if (sub_analysis == NULL) {
printf("Error allocating memory for sub_analysis\n");
return -1;
Expand Down Expand Up @@ -164,7 +165,7 @@ int proc_analyze(proc_t * proc, proc_analysis_t * analysis, proc_analysis_config
* @param slot_count The number of procedure slots in the array
*/
void collect_proc_slots(proc_analysis_t * analysis, uint8_t ** slots, size_t * slot_count) {
*slots = realloc(*slots, (*slot_count + analysis->procedure_slot_count) * sizeof(uint8_t));
*slots = proc_realloc(*slots, (*slot_count + analysis->procedure_slot_count) * sizeof(uint8_t));
memcpy(*slots + *slot_count, analysis->procedure_slots, analysis->procedure_slot_count * sizeof(uint8_t));
*slot_count += analysis->procedure_slot_count;

Expand Down
58 changes: 30 additions & 28 deletions src/proc_pack.c
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#include <csp_proc/proc_pack.h>
#include <csp_proc/proc_memory.h>

#include <stdlib.h>
#include <string.h>
#include <stdint.h>
Expand Down Expand Up @@ -152,35 +154,35 @@ int unpack_proc_from_csp_packet(proc_t * procedure, csp_packet_t * packet) {
switch (procedure->instructions[i].type) {
case PROC_BLOCK:
case PROC_IFELSE:
procedure->instructions[i].instruction.block.param_a = strdup(packet->data + offset);
procedure->instructions[i].instruction.block.param_a = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
memcpy(&procedure->instructions[i].instruction.block.op, packet->data + offset, sizeof(comparison_op_t));
offset += sizeof(comparison_op_t);
procedure->instructions[i].instruction.block.param_b = strdup(packet->data + offset);
procedure->instructions[i].instruction.block.param_b = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
break;
case PROC_SET:
procedure->instructions[i].instruction.set.param = strdup(packet->data + offset);
procedure->instructions[i].instruction.set.param = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
procedure->instructions[i].instruction.set.value = strdup(packet->data + offset);
procedure->instructions[i].instruction.set.value = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
break;
case PROC_UNOP:
procedure->instructions[i].instruction.unop.param = strdup(packet->data + offset);
procedure->instructions[i].instruction.unop.param = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
memcpy(&procedure->instructions[i].instruction.unop.op, packet->data + offset, sizeof(unary_op_t));
offset += sizeof(unary_op_t);
procedure->instructions[i].instruction.unop.result = strdup(packet->data + offset);
procedure->instructions[i].instruction.unop.result = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
break;
case PROC_BINOP:
procedure->instructions[i].instruction.binop.param_a = strdup(packet->data + offset);
procedure->instructions[i].instruction.binop.param_a = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
memcpy(&procedure->instructions[i].instruction.binop.op, packet->data + offset, sizeof(binary_op_t));
offset += sizeof(binary_op_t);
procedure->instructions[i].instruction.binop.param_b = strdup(packet->data + offset);
procedure->instructions[i].instruction.binop.param_b = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
procedure->instructions[i].instruction.binop.result = strdup(packet->data + offset);
procedure->instructions[i].instruction.binop.result = proc_strdup(packet->data + offset);
offset += strlen(packet->data + offset) + 1;
break;
case PROC_CALL:
Expand All @@ -202,21 +204,21 @@ void proc_free_instruction(proc_instruction_t * instruction) {
switch (instruction->type) {
case PROC_BLOCK:
case PROC_IFELSE:
free(instruction->instruction.block.param_a);
free(instruction->instruction.block.param_b);
proc_free(instruction->instruction.block.param_a);
proc_free(instruction->instruction.block.param_b);
break;
case PROC_SET:
free(instruction->instruction.set.param);
free(instruction->instruction.set.value);
proc_free(instruction->instruction.set.param);
proc_free(instruction->instruction.set.value);
break;
case PROC_UNOP:
free(instruction->instruction.unop.param);
free(instruction->instruction.unop.result);
proc_free(instruction->instruction.unop.param);
proc_free(instruction->instruction.unop.result);
break;
case PROC_BINOP:
free(instruction->instruction.binop.param_a);
free(instruction->instruction.binop.param_b);
free(instruction->instruction.binop.result);
proc_free(instruction->instruction.binop.param_a);
proc_free(instruction->instruction.binop.param_b);
proc_free(instruction->instruction.binop.result);
break;
case PROC_CALL:
case PROC_NOOP:
Expand All @@ -231,7 +233,7 @@ void free_proc(proc_t * procedure) {
for (int i = 0; i < procedure->instruction_count; i++) {
proc_free_instruction(&procedure->instructions[i]);
}
free(procedure);
proc_free(procedure);
}

int proc_copy_instruction(proc_instruction_t * instruction, proc_instruction_t * copy) {
Expand All @@ -246,23 +248,23 @@ int proc_copy_instruction(proc_instruction_t * instruction, proc_instruction_t *
switch (instruction->type) {
case PROC_BLOCK:
case PROC_IFELSE:
copy->instruction.block.param_a = strdup(instruction->instruction.block.param_a);
copy->instruction.block.param_b = strdup(instruction->instruction.block.param_b);
copy->instruction.block.param_a = proc_strdup(instruction->instruction.block.param_a);
copy->instruction.block.param_b = proc_strdup(instruction->instruction.block.param_b);
copy->instruction.block.op = instruction->instruction.block.op;
break;
case PROC_SET:
copy->instruction.set.param = strdup(instruction->instruction.set.param);
copy->instruction.set.value = strdup(instruction->instruction.set.value);
copy->instruction.set.param = proc_strdup(instruction->instruction.set.param);
copy->instruction.set.value = proc_strdup(instruction->instruction.set.value);
break;
case PROC_UNOP:
copy->instruction.unop.param = strdup(instruction->instruction.unop.param);
copy->instruction.unop.result = strdup(instruction->instruction.unop.result);
copy->instruction.unop.param = proc_strdup(instruction->instruction.unop.param);
copy->instruction.unop.result = proc_strdup(instruction->instruction.unop.result);
copy->instruction.unop.op = instruction->instruction.unop.op;
break;
case PROC_BINOP:
copy->instruction.binop.param_a = strdup(instruction->instruction.binop.param_a);
copy->instruction.binop.param_b = strdup(instruction->instruction.binop.param_b);
copy->instruction.binop.result = strdup(instruction->instruction.binop.result);
copy->instruction.binop.param_a = proc_strdup(instruction->instruction.binop.param_a);
copy->instruction.binop.param_b = proc_strdup(instruction->instruction.binop.param_b);
copy->instruction.binop.result = proc_strdup(instruction->instruction.binop.result);
copy->instruction.binop.op = instruction->instruction.binop.op;
break;
case PROC_CALL:
Expand Down
Loading

0 comments on commit 6e75379

Please sign in to comment.