From 562bc50d090bf62b1936c4d9936dc58453fb508a Mon Sep 17 00:00:00 2001 From: zhouli <1932489836@qq.com> Date: Sat, 18 Apr 2026 23:46:17 +0800 Subject: [PATCH] fix(claw_cap): Use buffered growth for claw_cap capacit --- .../claw_modules/claw_cap/include/claw_cap.h | 7 +- .../claw_modules/claw_cap/src/claw_cap.c | 202 ++++++++++++++---- .../event_router_cli_test/main/main.c | 7 +- 3 files changed, 163 insertions(+), 53 deletions(-) diff --git a/components/claw_modules/claw_cap/include/claw_cap.h b/components/claw_modules/claw_cap/include/claw_cap.h index 70050d9..2d60850 100644 --- a/components/claw_modules/claw_cap/include/claw_cap.h +++ b/components/claw_modules/claw_cap/include/claw_cap.h @@ -116,12 +116,7 @@ typedef struct { uint32_t active_calls; } claw_cap_descriptor_info_t; -typedef struct { - size_t max_capabilities; - size_t max_groups; -} claw_cap_config_t; - -esp_err_t claw_cap_init(const claw_cap_config_t *config); +esp_err_t claw_cap_init(void); esp_err_t claw_cap_register(const claw_cap_descriptor_t *descriptor); esp_err_t claw_cap_register_group(const claw_cap_group_t *group); esp_err_t claw_cap_start_all(void); diff --git a/components/claw_modules/claw_cap/src/claw_cap.c b/components/claw_modules/claw_cap/src/claw_cap.c index ca65507..99a7cc8 100644 --- a/components/claw_modules/claw_cap/src/claw_cap.c +++ b/components/claw_modules/claw_cap/src/claw_cap.c @@ -18,8 +18,8 @@ static const char *TAG = "claw_cap"; -#define CLAW_CAP_DEFAULT_MAX_CAPABILITIES 16 -#define CLAW_CAP_DEFAULT_MAX_GROUPS 8 +#define CLAW_CAP_DEFAULT_MAX_CAPABILITIES 4 +#define CLAW_CAP_DEFAULT_MAX_GROUPS 4 #define CLAW_CAP_UNLOAD_POLL_MS 20 typedef struct { @@ -75,6 +75,10 @@ static void claw_cap_free_session_visibility(claw_cap_session_visibility_t *visi static ssize_t claw_cap_find_session_visibility_locked(const char *session_id); static const claw_cap_session_visibility_t *claw_cap_get_session_visibility_locked( const char *session_id); +static size_t claw_cap_count_used_descriptor_slots_locked(void); +static size_t claw_cap_count_used_group_slots_locked(void); +static esp_err_t claw_cap_ensure_descriptor_capacity_locked(size_t additional_free_slots); +static esp_err_t claw_cap_ensure_group_capacity_locked(size_t additional_free_slots); static char *claw_cap_strdup(const char *src) { @@ -637,6 +641,149 @@ static size_t claw_cap_count_free_descriptor_slots_locked(void) return count; } +static size_t claw_cap_count_used_descriptor_slots_locked(void) +{ + size_t i; + size_t count = 0; + + for (i = 0; i < s_runtime.descriptor_capacity; i++) { + if (s_runtime.descriptor_slots[i].occupied) { + count++; + } + } + + return count; +} + +static size_t claw_cap_count_used_group_slots_locked(void) +{ + size_t i; + size_t count = 0; + + for (i = 0; i < s_runtime.group_capacity; i++) { + if (s_runtime.group_slots[i].occupied) { + count++; + } + } + + return count; +} + +static esp_err_t claw_cap_ensure_descriptor_capacity_locked(size_t additional_free_slots) +{ + claw_cap_descriptor_slot_t *original_slots = s_runtime.descriptor_slots; + claw_cap_descriptor_t *original_snapshot = s_runtime.descriptor_list_snapshot; + claw_cap_descriptor_slot_t *new_slots = NULL; + claw_cap_descriptor_t *new_snapshot = NULL; + size_t required_capacity; + size_t old_capacity; + size_t new_capacity; + + if (additional_free_slots == 0 || claw_cap_count_free_descriptor_slots_locked() >= additional_free_slots) { + return ESP_OK; + } + + old_capacity = s_runtime.descriptor_capacity; + required_capacity = claw_cap_count_used_descriptor_slots_locked() + additional_free_slots; + new_capacity = s_runtime.descriptor_capacity ? s_runtime.descriptor_capacity : CLAW_CAP_DEFAULT_MAX_CAPABILITIES; + // Descriptors grow with a small buffer instead of geometric jumps. + if (new_capacity < required_capacity) { + size_t growth_margin = required_capacity / 4; + + if (growth_margin < CLAW_CAP_DEFAULT_MAX_CAPABILITIES) { + growth_margin = CLAW_CAP_DEFAULT_MAX_CAPABILITIES; + } + new_capacity = required_capacity + growth_margin; + } + + new_slots = realloc(original_slots, new_capacity * sizeof(*new_slots)); + if (!new_slots) { + return ESP_ERR_NO_MEM; + } + new_snapshot = realloc(original_snapshot, new_capacity * sizeof(*new_snapshot)); + if (!new_snapshot) { + if (new_slots != original_slots) { + void *restored = realloc(new_slots, old_capacity * sizeof(*new_slots)); + + if (restored) { + new_slots = restored; + } + } + return ESP_ERR_NO_MEM; + } + + if (new_capacity > old_capacity) { + memset(&new_slots[old_capacity], 0, (new_capacity - old_capacity) * sizeof(*new_slots)); + memset(&new_snapshot[old_capacity], 0, (new_capacity - old_capacity) * sizeof(*new_snapshot)); + } + s_runtime.descriptor_slots = new_slots; + s_runtime.descriptor_list_snapshot = new_snapshot; + s_runtime.descriptor_capacity = new_capacity; + ESP_LOGI(TAG, "Expanded descriptor capacity to %u", (unsigned)new_capacity); + return ESP_OK; +} + +static esp_err_t claw_cap_ensure_group_capacity_locked(size_t additional_free_slots) +{ + claw_cap_group_slot_t *original_slots = s_runtime.group_slots; + claw_cap_group_info_t *original_snapshot = s_runtime.group_list_snapshot; + claw_cap_group_slot_t *new_slots = NULL; + claw_cap_group_info_t *new_snapshot = NULL; + size_t required_capacity; + size_t old_capacity; + size_t new_capacity; + + if (additional_free_slots == 0) { + return ESP_OK; + } + if (s_runtime.group_capacity > 0) { + size_t free_slots = s_runtime.group_capacity - claw_cap_count_used_group_slots_locked(); + + if (free_slots >= additional_free_slots) { + return ESP_OK; + } + } + + old_capacity = s_runtime.group_capacity; + required_capacity = claw_cap_count_used_group_slots_locked() + additional_free_slots; + new_capacity = s_runtime.group_capacity ? s_runtime.group_capacity : CLAW_CAP_DEFAULT_MAX_GROUPS; + // Groups stay relatively few, so reserve only a small buffer above the exact need. + if (new_capacity < required_capacity) { + size_t growth_margin = required_capacity / 4; + + if (growth_margin < CLAW_CAP_DEFAULT_MAX_GROUPS) { + growth_margin = CLAW_CAP_DEFAULT_MAX_GROUPS; + } + new_capacity = required_capacity + growth_margin; + } + + new_slots = realloc(original_slots, new_capacity * sizeof(*new_slots)); + if (!new_slots) { + return ESP_ERR_NO_MEM; + } + new_snapshot = realloc(original_snapshot, new_capacity * sizeof(*new_snapshot)); + if (!new_snapshot) { + if (new_slots != original_slots) { + void *restored = realloc(new_slots, old_capacity * sizeof(*new_slots)); + + if (restored) { + new_slots = restored; + } + } + return ESP_ERR_NO_MEM; + } + + if (new_capacity > old_capacity) { + memset(&new_slots[old_capacity], 0, (new_capacity - old_capacity) * sizeof(*new_slots)); + memset(&new_snapshot[old_capacity], 0, (new_capacity - old_capacity) * sizeof(*new_snapshot)); + } + s_runtime.group_slots = new_slots; + s_runtime.group_list_snapshot = new_snapshot; + s_runtime.group_capacity = new_capacity; + ESP_LOGI(TAG, "Expanded group capacity to %u", (unsigned)new_capacity); + return ESP_OK; +} + static esp_err_t claw_cap_validate_group_locked(const claw_cap_group_t *group) { size_t i; @@ -649,12 +796,6 @@ static esp_err_t claw_cap_validate_group_locked(const claw_cap_group_t *group) if (claw_cap_find_group_slot_index_locked(group->group_id) >= 0) { return ESP_ERR_INVALID_STATE; } - if (claw_cap_find_free_group_slot_locked() < 0) { - return ESP_ERR_NO_MEM; - } - if (claw_cap_count_free_descriptor_slots_locked() < group->descriptor_count) { - return ESP_ERR_NO_MEM; - } for (i = 0; i < group->descriptor_count; i++) { esp_err_t err = claw_cap_validate_descriptor(&group->descriptors[i]); @@ -870,6 +1011,16 @@ static esp_err_t claw_cap_register_group_locked(const claw_cap_group_t *group, ssize_t group_slot_index; claw_cap_group_slot_t *group_slot; size_t i; + esp_err_t err; + + err = claw_cap_ensure_group_capacity_locked(1); + if (err != ESP_OK) { + return err; + } + err = claw_cap_ensure_descriptor_capacity_locked(group->descriptor_count); + if (err != ESP_OK) { + return err; + } group_slot_index = claw_cap_find_free_group_slot_locked(); if (group_slot_index < 0) { @@ -921,43 +1072,14 @@ static esp_err_t claw_cap_register_group_locked(const claw_cap_group_t *group, return ESP_OK; } -esp_err_t claw_cap_init(const claw_cap_config_t *config) +esp_err_t claw_cap_init(void) { - size_t descriptor_capacity; - size_t group_capacity; - if (s_runtime.initialized) { return ESP_ERR_INVALID_STATE; } - descriptor_capacity = config && config->max_capabilities ? - config->max_capabilities : CLAW_CAP_DEFAULT_MAX_CAPABILITIES; - group_capacity = config && config->max_groups ? - config->max_groups : CLAW_CAP_DEFAULT_MAX_GROUPS; - - s_runtime.descriptor_slots = calloc(descriptor_capacity, - sizeof(claw_cap_descriptor_slot_t)); - s_runtime.group_slots = calloc(group_capacity, sizeof(claw_cap_group_slot_t)); - s_runtime.descriptor_list_snapshot = calloc(descriptor_capacity, - sizeof(claw_cap_descriptor_t)); - s_runtime.group_list_snapshot = calloc(group_capacity, - sizeof(claw_cap_group_info_t)); - if (!s_runtime.descriptor_slots || !s_runtime.group_slots || - !s_runtime.descriptor_list_snapshot || !s_runtime.group_list_snapshot) { - free(s_runtime.descriptor_slots); - free(s_runtime.group_slots); - free(s_runtime.descriptor_list_snapshot); - free(s_runtime.group_list_snapshot); - memset(&s_runtime, 0, sizeof(s_runtime)); - return ESP_ERR_NO_MEM; - } - s_runtime.mutex = xSemaphoreCreateMutex(); if (!s_runtime.mutex) { - free(s_runtime.descriptor_slots); - free(s_runtime.group_slots); - free(s_runtime.descriptor_list_snapshot); - free(s_runtime.group_list_snapshot); if (s_runtime.mutex) { vSemaphoreDelete(s_runtime.mutex); } @@ -965,10 +1087,8 @@ esp_err_t claw_cap_init(const claw_cap_config_t *config) return ESP_ERR_NO_MEM; } - s_runtime.descriptor_capacity = descriptor_capacity; - s_runtime.group_capacity = group_capacity; s_runtime.initialized = true; - ESP_LOGI(TAG, "Initialized runtime"); + ESP_LOGI(TAG, "Initialized runtime with dynamic capacity growth"); return ESP_OK; } diff --git a/components/claw_modules/claw_event_router/test_apps/event_router_cli_test/main/main.c b/components/claw_modules/claw_event_router/test_apps/event_router_cli_test/main/main.c index da0c89d..a870fd1 100644 --- a/components/claw_modules/claw_event_router/test_apps/event_router_cli_test/main/main.c +++ b/components/claw_modules/claw_event_router/test_apps/event_router_cli_test/main/main.c @@ -125,12 +125,7 @@ static esp_err_t init_console(void) ESP_RETURN_ON_ERROR(esp_console_init(&console_config), TAG, "Failed to init console"); esp_console_register_help_command(); - ESP_RETURN_ON_ERROR(claw_cap_init(&(claw_cap_config_t) { - .max_capabilities = 8, - .max_groups = 2, - }), - TAG, - "Failed to init claw_cap"); + ESP_RETURN_ON_ERROR(claw_cap_init(), TAG, "Failed to init claw_cap"); ESP_RETURN_ON_ERROR(cap_router_mgr_register_group(), TAG, "Failed to register router manager cap"); ESP_RETURN_ON_ERROR(claw_cap_start_all(), TAG, "Failed to start capabilities"); register_cap_router_mgr();