From 5f7bf3e2e0d28e987c255a3a5c12cb8511cfedf2 Mon Sep 17 00:00:00 2001 From: Yanfeng Liu Date: Wed, 29 May 2024 14:55:19 +0800 Subject: [PATCH] sched/signal: reclaim dynamic sigactions This adds pre-allocation and dynamic allocations for sigactions. Current behavior can be acheived by setting SIG_ALLOC_ACTIONS to a number larger than 1. Signed-off-by: Yanfeng Liu --- sched/Kconfig | 14 ++++++++++ sched/signal/sig_action.c | 57 ++++++++++++++++++++++++++++++++++----- sched/signal/signal.h | 1 - 3 files changed, 64 insertions(+), 8 deletions(-) diff --git a/sched/Kconfig b/sched/Kconfig index 232c009f8c46d..0e3dfa9e465cc 100644 --- a/sched/Kconfig +++ b/sched/Kconfig @@ -1548,6 +1548,20 @@ endmenu # RTOS hooks menu "Signal Configuration" +config SIG_PREALLOC_ACTIONS + int "Number of pre-allocated sigactions" + default 4 + ---help--- + The number of pre-allocated sigaction structures. + +config SIG_ALLOC_ACTIONS + int "Num of sigactions to allocate per time" + default 1 + ---help--- + The number of sigactions to allocate per time. Note that + if this number is larger than 1, the allocation won't be + returned to the heap but kept in a free list for reuse. + config SIG_PREALLOC_IRQ_ACTIONS int "Number of pre-allocated irq actions" default 4 if DEFAULT_SMALL diff --git a/sched/signal/sig_action.c b/sched/signal/sig_action.c index 934a668224527..3467279bab98c 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -40,12 +40,31 @@ #include "group/group.h" #include "signal/signal.h" +/**************************************************************************** + * Preprocessor definitions + ****************************************************************************/ + +/* judges if a sigaction instance is a preallocated one */ + +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 +# define IS_PREALLOC_ACTION(x) ( \ + (uintptr_t)(x) >= (uintptr_t)g_sigactions && \ + (uintptr_t)(x) < ((uintptr_t)g_sigactions) + sizeof(g_sigactions)) +#else +# define IS_PREALLOC_ACTION(x) false +#endif + /**************************************************************************** * Private Data ****************************************************************************/ static spinlock_t g_sigaction_spin; +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 +static sigactq_t g_sigactions[CONFIG_SIG_PREALLOC_ACTIONS]; +static bool g_sigactions_used = false; +#endif + /**************************************************************************** * Private Functions ****************************************************************************/ @@ -65,14 +84,31 @@ static void nxsig_alloc_actionblock(void) irqstate_t flags; int i; + /* Use pre-allocated instances only once */ + +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 + flags = spin_lock_irqsave(&g_sigaction_spin); + if (!g_sigactions_used) + { + for (i = 0; i < CONFIG_SIG_PREALLOC_ACTIONS; i++) + { + sq_addlast((FAR sq_entry_t *)(g_sigactions + i), &g_sigfreeaction); + } + + g_sigactions_used = true; + } + + spin_unlock_irqrestore(&g_sigaction_spin, flags); +#endif + /* Allocate a block of signal actions */ - sigact = kmm_malloc((sizeof(sigactq_t)) * NUM_SIGNAL_ACTIONS); + sigact = kmm_malloc((sizeof(sigactq_t)) * CONFIG_SIG_ALLOC_ACTIONS); if (sigact != NULL) { flags = spin_lock_irqsave(&g_sigaction_spin); - for (i = 0; i < NUM_SIGNAL_ACTIONS; i++) + for (i = 0; i < CONFIG_SIG_ALLOC_ACTIONS; i++) { sq_addlast((FAR sq_entry_t *)sigact++, &g_sigfreeaction); } @@ -100,7 +136,7 @@ static FAR sigactq_t *nxsig_alloc_action(void) sigact = (FAR sigactq_t *)sq_remfirst(&g_sigfreeaction); spin_unlock_irqrestore(&g_sigaction_spin, flags); - /* Check if we got one. */ + /* Check if we got one via loop as not in critical section now */ while (!sigact) { @@ -409,9 +445,16 @@ void nxsig_release_action(FAR sigactq_t *sigact) { irqstate_t flags; - /* Just put it back on the free list */ + if (CONFIG_SIG_ALLOC_ACTIONS > 1 || IS_PREALLOC_ACTION(sigact)) + { + /* Non-preallocated instances will never return to heap! */ - flags = spin_lock_irqsave(&g_sigaction_spin); - sq_addlast((FAR sq_entry_t *)sigact, &g_sigfreeaction); - spin_unlock_irqrestore(&g_sigaction_spin, flags); + flags = spin_lock_irqsave(&g_sigaction_spin); + sq_addlast((FAR sq_entry_t *)sigact, &g_sigfreeaction); + spin_unlock_irqrestore(&g_sigaction_spin, flags); + } + else + { + kmm_free(sigact); + } } diff --git a/sched/signal/signal.h b/sched/signal/signal.h index 0553b8e3b0f5e..5165d6804f069 100644 --- a/sched/signal/signal.h +++ b/sched/signal/signal.h @@ -42,7 +42,6 @@ * allocate in a block */ -#define NUM_SIGNAL_ACTIONS 4 #define NUM_PENDING_ACTIONS 4 #define NUM_SIGNALS_PENDING 4