extmod/nimble: Make nimble_malloc work with allocated size.
This commit is contained in:
parent
5b08676d6a
commit
f3f31ac959
@ -58,44 +58,58 @@ void *ble_npl_get_current_task_id(void) {
|
|||||||
// Maintain a linked list of heap memory that we've passed to Nimble,
|
// Maintain a linked list of heap memory that we've passed to Nimble,
|
||||||
// discoverable via the bluetooth_nimble_memory root pointer.
|
// discoverable via the bluetooth_nimble_memory root pointer.
|
||||||
|
|
||||||
// MP_STATE_PORT(bluetooth_nimble_memory) is a pointer to [next, prev, data...].
|
typedef struct _mp_bluetooth_nimble_malloc_t {
|
||||||
|
struct _mp_bluetooth_nimble_malloc_t *prev;
|
||||||
|
struct _mp_bluetooth_nimble_malloc_t *next;
|
||||||
|
size_t size;
|
||||||
|
uint8_t data[];
|
||||||
|
} mp_bluetooth_nimble_malloc_t;
|
||||||
|
|
||||||
// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature?
|
// TODO: This is duplicated from mbedtls. Perhaps make this a generic feature?
|
||||||
void *m_malloc_bluetooth(size_t size) {
|
STATIC void *m_malloc_bluetooth(size_t size) {
|
||||||
void **ptr = m_malloc0(size + 2 * sizeof(uintptr_t));
|
size += sizeof(mp_bluetooth_nimble_malloc_t);
|
||||||
if (MP_STATE_PORT(bluetooth_nimble_memory) != NULL) {
|
mp_bluetooth_nimble_malloc_t *alloc = m_malloc0(size);
|
||||||
MP_STATE_PORT(bluetooth_nimble_memory)[0] = ptr;
|
alloc->size = size;
|
||||||
|
alloc->next = MP_STATE_PORT(bluetooth_nimble_memory);
|
||||||
|
if (alloc->next) {
|
||||||
|
alloc->next->prev = alloc;
|
||||||
}
|
}
|
||||||
ptr[0] = NULL;
|
MP_STATE_PORT(bluetooth_nimble_memory) = alloc;
|
||||||
ptr[1] = MP_STATE_PORT(bluetooth_nimble_memory);
|
return alloc->data;
|
||||||
MP_STATE_PORT(bluetooth_nimble_memory) = ptr;
|
|
||||||
return &ptr[2];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void m_free_bluetooth(void *ptr_in) {
|
STATIC mp_bluetooth_nimble_malloc_t* get_nimble_malloc(void *ptr) {
|
||||||
void **ptr = &((void**)ptr_in)[-2];
|
return (mp_bluetooth_nimble_malloc_t*)((uintptr_t)ptr - sizeof(mp_bluetooth_nimble_malloc_t));
|
||||||
if (ptr[1] != NULL) {
|
|
||||||
((void**)ptr[1])[0] = ptr[0];
|
|
||||||
}
|
}
|
||||||
if (ptr[0] != NULL) {
|
|
||||||
((void**)ptr[0])[1] = ptr[1];
|
STATIC void m_free_bluetooth(void *ptr) {
|
||||||
|
mp_bluetooth_nimble_malloc_t *alloc = get_nimble_malloc(ptr);
|
||||||
|
if (alloc->next) {
|
||||||
|
alloc->next->prev = alloc->prev;
|
||||||
|
}
|
||||||
|
if (alloc->prev) {
|
||||||
|
alloc->prev->next = alloc->next;
|
||||||
} else {
|
} else {
|
||||||
MP_STATE_PORT(bluetooth_nimble_memory) = ptr[1];
|
MP_STATE_PORT(bluetooth_nimble_memory) = NULL;
|
||||||
}
|
}
|
||||||
m_free(ptr);
|
m_free(alloc
|
||||||
|
#if MICROPY_MALLOC_USES_ALLOCATED_SIZE
|
||||||
|
, alloc->size
|
||||||
|
#endif
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check if a nimble ptr is tracked.
|
// Check if a nimble ptr is tracked.
|
||||||
// If it isn't, that means that it's from a previous soft-reset cycle.
|
// If it isn't, that means that it's from a previous soft-reset cycle.
|
||||||
STATIC bool is_valid_nimble_malloc(void *ptr) {
|
STATIC bool is_valid_nimble_malloc(void *ptr) {
|
||||||
DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr);
|
DEBUG_MALLOC_printf("NIMBLE is_valid_nimble_malloc(%p)\n", ptr);
|
||||||
void** search = MP_STATE_PORT(bluetooth_nimble_memory);
|
mp_bluetooth_nimble_malloc_t *alloc = MP_STATE_PORT(bluetooth_nimble_memory);
|
||||||
while (search) {
|
while (alloc) {
|
||||||
if (&search[2] == ptr) {
|
DEBUG_MALLOC_printf("NIMBLE checking: %p\n", alloc->data);
|
||||||
|
if (alloc->data == ptr) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
alloc = alloc->next;
|
||||||
search = (void**)search[1];
|
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -110,22 +124,46 @@ void *nimble_malloc(size_t size) {
|
|||||||
// Only free if it's still a valid pointer.
|
// Only free if it's still a valid pointer.
|
||||||
void nimble_free(void *ptr) {
|
void nimble_free(void *ptr) {
|
||||||
DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr);
|
DEBUG_MALLOC_printf("NIMBLE free(%p)\n", ptr);
|
||||||
if (ptr && is_valid_nimble_malloc(ptr)) {
|
|
||||||
|
if (ptr) {
|
||||||
|
// After a stack re-init, NimBLE has variables in BSS that might be
|
||||||
|
// still pointing to old allocations from a previous init. We can't do
|
||||||
|
// anything about this (e.g. ble_gatts_free_mem is private). But we
|
||||||
|
// can identify that this is a non-null, invalid alloc because it
|
||||||
|
// won't be in our list, so ignore it because it is effectively free'd
|
||||||
|
// anyway (it's not referenced by anything the GC can find).
|
||||||
|
if (is_valid_nimble_malloc(ptr)) {
|
||||||
m_free_bluetooth(ptr);
|
m_free_bluetooth(ptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Only realloc if it's still a valid pointer. Otherwise just malloc.
|
// Only realloc if it's still a valid pointer. Otherwise just malloc.
|
||||||
void *nimble_realloc(void *ptr, size_t size) {
|
void *nimble_realloc(void *ptr, size_t new_size) {
|
||||||
// This is only used by ble_gatts.c to grow the queue of pending services to be registered.
|
DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)new_size);
|
||||||
DEBUG_MALLOC_printf("NIMBLE realloc(%p, %u)\n", ptr, (uint)size);
|
|
||||||
void *ptr2 = nimble_malloc(size);
|
if (!ptr) {
|
||||||
if (ptr && is_valid_nimble_malloc(ptr)) {
|
return nimble_malloc(new_size);
|
||||||
// If it's a realloc and we still have the old data, then copy it.
|
|
||||||
// This will happen as we add services.
|
|
||||||
memcpy(ptr2, ptr, size);
|
|
||||||
m_free_bluetooth(ptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
assert(is_valid_nimble_malloc(ptr));
|
||||||
|
|
||||||
|
// Existing alloc is big enough.
|
||||||
|
mp_bluetooth_nimble_malloc_t *alloc = get_nimble_malloc(ptr);
|
||||||
|
size_t old_size = alloc->size - sizeof(mp_bluetooth_nimble_malloc_t);
|
||||||
|
if (old_size >= new_size) {
|
||||||
|
return ptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Allocate a new, larger region.
|
||||||
|
void *ptr2 = m_malloc_bluetooth(new_size);
|
||||||
|
|
||||||
|
// Copy old, smaller region into new region.
|
||||||
|
memcpy(ptr2, ptr, old_size);
|
||||||
|
m_free_bluetooth(ptr);
|
||||||
|
|
||||||
|
DEBUG_MALLOC_printf(" --> %p\n", ptr2);
|
||||||
|
|
||||||
return ptr2;
|
return ptr2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -299,7 +299,7 @@ extern const struct _mp_obj_module_t mp_module_onewire;
|
|||||||
#if MICROPY_BLUETOOTH_NIMBLE
|
#if MICROPY_BLUETOOTH_NIMBLE
|
||||||
struct _mp_bluetooth_nimble_root_pointers_t;
|
struct _mp_bluetooth_nimble_root_pointers_t;
|
||||||
struct _mp_bluetooth_nimble_malloc_t;
|
struct _mp_bluetooth_nimble_malloc_t;
|
||||||
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE void **bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
|
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE struct _mp_bluetooth_nimble_malloc_t *bluetooth_nimble_memory; struct _mp_bluetooth_nimble_root_pointers_t *bluetooth_nimble_root_pointers;
|
||||||
#else
|
#else
|
||||||
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
|
#define MICROPY_PORT_ROOT_POINTER_BLUETOOTH_NIMBLE
|
||||||
#endif
|
#endif
|
||||||
|
Loading…
Reference in New Issue
Block a user