From 6be12065deac51dabac8f38928139e207d98791a Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Mon, 27 May 2024 12:06:47 +0800 Subject: [PATCH] sched/signal: reclaim sigaction block after use This adds logic to reclaim sigaction blocks to reduce memory footprint. Signed-off-by: Yanfeng Liu --- sched/signal/sig_action.c | 112 +++++++++++++++++++++++++++++++++++--- sched/signal/signal.h | 3 +- 2 files changed, 106 insertions(+), 9 deletions(-) diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 934a668224527..c0add08c99f21 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -50,12 +50,52 @@ static spinlock_t g_sigaction_spin; * Private Functions ****************************************************************************/ +/**************************************************************************** + * Name: nxsig_add_freeaction + * + * Description: + * Insert a signal action entry to the address-sorted free list + * + ****************************************************************************/ + +static void nxsig_add_free(FAR sigactq_t *sigact) +{ + FAR sq_queue_t * const list = &g_sigfreeaction; + FAR sigactq_t *prev; + FAR sigactq_t *next; + irqstate_t flags; + + flags = spin_lock_irqsave(&g_sigaction_spin); + + if (list->head == NULL || (uintptr_t)sigact > (uintptr_t)list->tail) + { + sq_addlast((FAR sq_entry_t *)sigact, list); + } + else if ((uintptr_t)sigact < (uintptr_t)list->head) + { + sq_addfirst((FAR sq_entry_t *)sigact, list); + } + else + { + prev = (FAR sigactq_t *)list->head; + next = prev->flink; + while ((uintptr_t)next < (uintptr_t)sigact) + { + prev = next; + next = prev->flink; + } + + sq_addafter((FAR sq_entry_t *)prev, (FAR sq_entry_t *)sigact, list); + } + + spin_unlock_irqrestore(&g_sigaction_spin, flags); +} + /**************************************************************************** * Name: nxsig_alloc_actionblock * * Description: - * Allocate a block of signal actions and place them - * on the free list. + * Allocate a block of signal actions and place them in the free list. * ****************************************************************************/ @@ -67,14 +107,16 @@ static void nxsig_alloc_actionblock(void) /* Allocate a block of signal actions */ - sigact = kmm_malloc((sizeof(sigactq_t)) * NUM_SIGNAL_ACTIONS); + sigact = kmm_zalloc((sizeof(sigactq_t)) * NUM_SIGNAL_ACTIONS); if (sigact != NULL) { + sigact->sob = 1; /* mark the first entry only */ + nxsig_add_free(sigact); flags = spin_lock_irqsave(&g_sigaction_spin); - - for (i = 0; i < NUM_SIGNAL_ACTIONS; i++) + for (i = 1; i < NUM_SIGNAL_ACTIONS; i++) { - sq_addlast((FAR sq_entry_t *)sigact++, &g_sigfreeaction); + sq_addafter((FAR sq_entry_t *)(sigact + i - 1), + (FAR sq_entry_t *)(sigact + i), &g_sigfreeaction); } spin_unlock_irqrestore(&g_sigaction_spin, flags); @@ -407,11 +449,65 @@ int sigaction(int signo, FAR const struct sigaction *act, void nxsig_release_action(FAR sigactq_t *sigact) { + FAR sq_queue_t * const list = &g_sigfreeaction; + FAR sigactq_t *prev; + FAR sigactq_t *next; irqstate_t flags; + int i; + + /* Put back to the free list */ + + nxsig_add_free(sigact); - /* Just put it back on the free list */ + /* Scan the list for complete blocks */ flags = spin_lock_irqsave(&g_sigaction_spin); - sq_addlast((FAR sq_entry_t *)sigact, &g_sigfreeaction); + + prev = NULL; + sigact = (FAR sigactq_t *)list->head; + +next_sob: + + while (sigact && !sigact->sob) /* Seek for SOB entry */ + { + prev = sigact; + sigact = sigact->flink; + } + + if (sigact && sigact->flink) + { + for (next = sigact->flink, i = 1; /* Check following entries */ + next == sigact + i && i < NUM_SIGNAL_ACTIONS; + next = next->flink, i++); + + if (i == NUM_SIGNAL_ACTIONS) /* Got complete block */ + { + for (; i > 0; i--) /* Detach entries from list */ + { + if (!prev) + { + sq_remfirst(list); + } + else + { + sq_remafter((FAR sq_entry_t *)prev, list); + } + } + + kmm_free(sigact); /* Reclaim the block */ + + if (list->head && next) + { + sigact = next; + } + } + else /* Advance i entries */ + { + for (; i > 0; i--, prev = sigact, sigact = sigact->flink); + } + + goto next_sob; + } + spin_unlock_irqrestore(&g_sigaction_spin, flags); } diff --git a/sched/signal/signal.h b/sched/signal/signal.h index 0553b8e3b0f5e..bf1535299a943 100644 --- a/sched/signal/signal.h +++ b/sched/signal/signal.h @@ -65,7 +65,8 @@ struct sigactq { FAR struct sigactq *flink; /* Forward link */ struct sigaction act; /* Sigaction data */ - uint8_t signo; /* Signal associated with action */ + uint8_t signo:7; /* Signal associated with action */ + uint8_t sob:1; /* Flag depicting start entry of a block */ }; typedef struct sigactq sigactq_t;