From 92c6a1667d6745ca51f4d2955e89397d5b3a5693 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Mon, 27 May 2024 12:06:47 +0800 Subject: [PATCH] sched/signal: reclaim unused sigaction blocks This adds logic to reclaim unused sigaction blocks to reduce footprint after running ostest. Signed-off-by: Yanfeng Liu --- sched/signal/sig_action.c | 111 +++++++++++++++++++++++++++++++++++--- sched/signal/signal.h | 3 +- 2 files changed, 105 insertions(+), 9 deletions(-) diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 934a668224527..e1c1451b52301 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -50,12 +51,53 @@ 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 sigactq_t *prev; + FAR sigactq_t *next; + irqstate_t flags; + + flags = spin_lock_irqsave(&g_sigaction_spin); + + if (g_sigfreeaction.head == NULL || + (uintptr_t)sigact > (uintptr_t)g_sigfreeaction.tail) + { + sq_addlast((FAR sq_entry_t *)sigact, &g_sigfreeaction); + } + else if ((uintptr_t)sigact < (uintptr_t)g_sigfreeaction.head) + { + sq_addfirst((FAR sq_entry_t *)sigact, &g_sigfreeaction); + } + else + { + prev = (FAR sigactq_t *)g_sigfreeaction.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, + &g_sigfreeaction); + } + + 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 +109,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 +451,62 @@ int sigaction(int signo, FAR const struct sigaction *act, void nxsig_release_action(FAR sigactq_t *sigact) { + FAR sigactq_t *prev; + FAR sigactq_t *next; irqstate_t flags; + int i; - /* Just put it back on the free list */ + /* Put back to the free list */ + + nxsig_add_free(sigact); + + /* 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 *)g_sigfreeaction.head; + +next_sob: + + while (sigact && !sigact->sob) /* Seek for SOB entry */ + { + prev = sigact; + sigact = sigact->flink; + } + + if (sigact && sigact->flink) + { + /* Check following entries */ + + for ( + next = sigact->flink, i = 1; + 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(&g_sigfreeaction); + } + else + { + sq_remafter((FAR sq_entry_t *)prev, &g_sigfreeaction); + } + } + + kmm_free(sigact); /* Free the block */ + } + + if (g_sigfreeaction.head && next) + { + sigact = next; + 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;