diff --git a/lib/memory_pool.c b/lib/memory_pool.c index 4e0d3afa..d67f695a 100644 --- a/lib/memory_pool.c +++ b/lib/memory_pool.c @@ -5,6 +5,17 @@ #include "memory_pool.h" #include "mem.h" +static size_t g_total_free = 0; +static size_t g_total_allocated = 0; + +size_t memory_pool_get_total_free_blocks(void) { + return g_total_free; +} + +size_t memory_pool_get_total_allocated(void) { + return g_total_allocated; +} + // Инициализировать пул памяти struct memory_pool* memory_pool_init(size_t object_size) { struct memory_pool* pool = u_calloc(1, sizeof(struct memory_pool)); @@ -29,6 +40,7 @@ void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) { void* obj = pool->free_head; pool->free_head = *(void**)obj; // Извлекаем next из начала блока pool->free_count--; + g_total_free--; pool->reuse_count++; memset(obj, 0, pool->object_size); // Опционально: очищаем память для безопасности DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_alloc reused: %s, remaining=%zu", location, pool->free_count); @@ -36,6 +48,7 @@ void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location) { } pool->allocations++; + g_total_allocated++; DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_alloc: %s, total_allocs=%zu", location, pool->allocations); return u_calloc_impl(1, pool->object_size, location); // Используем calloc для инициализации нулями } @@ -51,6 +64,7 @@ void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* loca *(void**)obj = pool->free_head; // Сохраняем next в начало блока pool->free_head = obj; pool->free_count++; + g_total_free++; DEBUG_INFO(DEBUG_CATEGORY_MEMORY, "pool_free returned: %s, free_count=%zu", location, pool->free_count); return; } @@ -84,6 +98,8 @@ void memory_pool_destroy(struct memory_pool* pool) { void* obj = pool->free_head; while (obj) { void* next = *(void**)obj; + g_total_free--; + g_total_allocated--; u_free(obj); cnt++; obj = next; diff --git a/lib/memory_pool.h b/lib/memory_pool.h index 8a2bfe76..374a2873 100644 --- a/lib/memory_pool.h +++ b/lib/memory_pool.h @@ -28,6 +28,8 @@ void memory_pool_destroy(struct memory_pool* pool); void* memory_pool_alloc_impl(struct memory_pool* pool, const char* location); void memory_pool_free_impl(struct memory_pool* pool, void* obj, const char* location); void memory_pool_get_stats(struct memory_pool* pool, size_t* allocations, size_t* reuse_count); +size_t memory_pool_get_total_free_blocks(void); +size_t memory_pool_get_total_allocated(void); #define memory_pool_alloc(pool) memory_pool_alloc_impl(pool, PLOCATION) #define memory_pool_free(pool, obj) memory_pool_free_impl(pool, obj, PLOCATION) diff --git a/lib/timeout_heap.c b/lib/timeout_heap.c index b46b2db3..cc82ee87 100644 --- a/lib/timeout_heap.c +++ b/lib/timeout_heap.c @@ -159,8 +159,13 @@ int timeout_heap_cancel(TimeoutHeap *h, TimeoutTime expiration, void *data) { return -1; // Not found } -void timeout_heap_set_free_callback(TimeoutHeap *h, void* user_data, void (*callback)(void* user_data, void* data)) { - if (!h) return; - h->user_data = user_data; - h->free_callback = callback; +void timeout_heap_set_free_callback(TimeoutHeap *h, void* user_data, void (*callback)(void* user_data, void* data)) { + if (!h) return; + h->user_data = user_data; + h->free_callback = callback; } + +size_t timeout_heap_get_size(TimeoutHeap *h) { + if (!h) return 0; + return h->size; +} diff --git a/lib/timeout_heap.h b/lib/timeout_heap.h index 5609df7a..8cf979f6 100644 --- a/lib/timeout_heap.h +++ b/lib/timeout_heap.h @@ -89,4 +89,6 @@ int timeout_heap_cancel(TimeoutHeap *h, TimeoutTime expiration, void *data); */ size_t timeout_heap_get_freed_count(TimeoutHeap *h); +size_t timeout_heap_get_size(TimeoutHeap *h); + #endif // TIMEOUT_HEAP_H diff --git a/src/control_server.c b/src/control_server.c index 6708acc3..433f8877 100644 --- a/src/control_server.c +++ b/src/control_server.c @@ -14,6 +14,8 @@ #include "pkt_normalizer.h" #include "../tools/etcpmon/etcpmon_protocol.h" #include "../lib/u_async.h" +#include "../lib/timeout_heap.h" +#include "../lib/memory_pool.h" #include "../lib/debug_config.h" #include "../lib/mem.h" #include "../lib/ll_queue.h" @@ -971,6 +973,15 @@ static void send_metrics(struct control_server* server, struct control_client* c for (int i = 0; i < 8; i++) { rsp->etcp.debug[i] = conn->debug[i]; } + + /* System resources */ + if (instance->ua && instance->ua->timeout_heap) { + rsp->etcp.active_timeouts = (uint32_t)timeout_heap_get_size(instance->ua->timeout_heap); + } else { + rsp->etcp.active_timeouts = 0; + } + + rsp->etcp.busy_memory_blocks = (uint32_t)(memory_pool_get_total_allocated() - memory_pool_get_total_free_blocks()); /* Fill TUN metrics */ if (instance->tun) { diff --git a/tools/etcpmon/etcpmon_gui.c b/tools/etcpmon/etcpmon_gui.c index b445f227..8d18aa05 100644 --- a/tools/etcpmon/etcpmon_gui.c +++ b/tools/etcpmon/etcpmon_gui.c @@ -548,6 +548,20 @@ static void CreateControls(struct etcpmon_app* app) { app->hEditTimerAckResp = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER, q_col2 + 110, qy - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_TIMER_ACK_RESP, hInst, NULL); + + /* System resources - below timer flags */ + qy += 28; + CreateWindowExA(0, "STATIC", "Timeouts:", + WS_CHILD | WS_VISIBLE, q_col1, qy, 60, 16, hWnd, (HMENU)IDC_STATIC, hInst, NULL); + app->hEditActiveTimeouts = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER, + q_col1 + 65, qy - 2, 50, 18, hWnd, (HMENU)IDC_EDIT_ACTIVE_TIMEOUTS, hInst, NULL); + + CreateWindowExA(0, "STATIC", "Memory:", + WS_CHILD | WS_VISIBLE, q_col2, qy, 50, 16, hWnd, (HMENU)IDC_STATIC, hInst, NULL); + app->hEditBusyMemory = CreateWindowExA(WS_EX_CLIENTEDGE, "EDIT", "", + WS_CHILD | WS_VISIBLE | ES_READONLY | ES_CENTER, + q_col2 + 60, qy - 2, 60, 18, hWnd, (HMENU)IDC_EDIT_BUSY_MEMORY, hInst, NULL); /* WaitAck queue state */ qy += 30; @@ -1088,6 +1102,10 @@ void etcpmon_gui_update_metrics(struct etcpmon_app* app, for (int i = 0; i < 8; i++) { UpdateEditIfChanged(hMain, IDC_EDIT_DEBUG_0 + i, "%u", metrics->etcp.debug[i]); } + + /* System resources */ + UpdateEditIfChanged(hMain, IDC_EDIT_ACTIVE_TIMEOUTS, "%u", metrics->etcp.active_timeouts); + UpdateEditIfChanged(hMain, IDC_EDIT_BUSY_MEMORY, "%u", metrics->etcp.busy_memory_blocks); /* Links list */ if (app->hListLinks) { diff --git a/tools/etcpmon/etcpmon_gui.h b/tools/etcpmon/etcpmon_gui.h index 880bda1c..0eb3d679 100644 --- a/tools/etcpmon/etcpmon_gui.h +++ b/tools/etcpmon/etcpmon_gui.h @@ -146,6 +146,10 @@ extern "C" { #define IDC_EDIT_DEBUG_6 692 #define IDC_EDIT_DEBUG_7 693 +/* System resources IDs */ +#define IDC_EDIT_ACTIVE_TIMEOUTS 700 +#define IDC_EDIT_BUSY_MEMORY 701 + /* Graph control ID */ #define IDC_GRAPH 500 @@ -284,6 +288,10 @@ struct etcpmon_app { HWND hEditCntLinkWait; HWND hEditTxState; HWND hEditDebug[8]; + + /* System resources */ + HWND hEditActiveTimeouts; + HWND hEditBusyMemory; /* Graph controls */ HWND hGraphWnd; diff --git a/tools/etcpmon/etcpmon_protocol.h b/tools/etcpmon/etcpmon_protocol.h index 52be4b38..d7504364 100644 --- a/tools/etcpmon/etcpmon_protocol.h +++ b/tools/etcpmon/etcpmon_protocol.h @@ -192,6 +192,10 @@ struct etcpmon_etcp_metrics { uint32_t cnt_link_wait; uint32_t tx_state; uint32_t debug[8]; + + /* System resources */ + uint32_t active_timeouts; + uint32_t busy_memory_blocks; }; /* Link metrics */