Add allocation-free queue discard for terminal stream resets

This commit is contained in:
evgeny committed 2026-10-23 12:20:34 +02:00
1 parent 0989eff73d
commit 466a56b499
2 files changed
+32 -14

No files matched your search

+26 -14
View File
@@ -129,15 +129,7 @@ struct ll_entry* ll_alloc_lldgram(uint16_t len) {
return entry;
}
void queue_free(struct ll_queue* q) {
if (!q) return;
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "queue_free: freeing queue %p, head=%p, tail=%p, count=%d",
q, q->head, q->tail, q->count);
// ВАЖНО: Не освобождаем элементы в очереди - они должны быть извлечены отдельно
// Это упрощает архитектуру и предотвращает double-u_free
static void queue_cancel_notifications(struct ll_queue* q) {
while (q->deferred_waiters) queue_waiter_cancel(q, q->deferred_waiters);
// Освободить список waiters (сбросить handle->internal, отменить отложенные вызовы)
struct queue_waiter* w = q->waiter_head;
@@ -150,11 +142,6 @@ void queue_free(struct ll_queue* q) {
q->waiter_head = NULL;
q->waiter_tail = NULL;
// Освободить хеш-таблицу
if (q->hash_table) {
u_free(q->hash_table);
}
// Отменить отложенное возобновление
if (q->resume_timeout_id) {
uasync_call_soon_cancel(q->ua, q->resume_timeout_id);
@@ -170,6 +157,31 @@ void queue_free(struct ll_queue* q) {
q->on_get_arg = NULL;
if (q->on_get_call_soon_id) uasync_call_soon_cancel(q->ua, q->on_get_call_soon_id);
q->on_get_call_soon_id = NULL; q->on_get_pending = 0;
q->callback_suspended = 1;
}
void queue_clear(struct ll_queue* q) {
if (!q) return;
#ifdef QUEUE_THREAD_CHECK
queue_check_thread(q);
#endif
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "[%s] discard queue: packets=%d bytes=%zu", q->name, q->count, q->total_bytes);
queue_cancel_notifications(q);
struct ll_entry* entry = q->head;
q->head = q->tail = NULL; q->count = 0; q->total_bytes = 0;
if (q->hash_table) memset(q->hash_table, 0, q->hash_size * sizeof(*q->hash_table));
while (entry) {
struct ll_entry* next = entry->next;
entry->owner = NULL; entry->next = entry->prev = entry->hash_next = NULL;
queue_dgram_free(entry); queue_entry_free(entry); entry = next;
}
}
void queue_free(struct ll_queue* q) {
if (!q) return;
DEBUG_DEBUG(DEBUG_CATEGORY_SYS, "queue_free: freeing queue %p, head=%p, count=%d", (void*)q, (void*)q->head, q->count);
queue_cancel_notifications(q);
if (q->hash_table) u_free(q->hash_table);
if (q->head) DEBUG_WARN(DEBUG_CATEGORY_SYS, "[%s] freeing nonempty queue: count=%d; entries remain caller-owned", q->name, q->count);
for (struct ll_entry* e = q->head; e; e = e->next) e->owner = NULL;
+6
View File
@@ -205,6 +205,12 @@ struct ll_queue* queue_new(struct UASYNC* ua, size_t hash_size, uint16_t index_o
*/
void queue_free(struct ll_queue* q);
/* Аварийный сброс: освободить все entry/dgram, отменить waiters и отложенные уведомления без их вызова.
* Не выделяет память (кроме действий пользовательского dgram_free_fn). Очередь/индекс/обычный callback/пороги сохраняются.
* empty/on_get обработчики снимаются, callback приостановлен; владельцы заново ставят ожидания после восстановления.
* Вызывать в потоке ua; NULL допустим. Для продолжения автозабора нужен queue_resume_callback(). */
void queue_clear(struct ll_queue* q);
// ==================== Конфигурация ====================
/**