From 0be97b443ff02c7881a1ea005fed13ed0280eee9 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 support of pre- and dynamic allocations of sigactions. Current never-return 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 | 21 ++++++++++++++------- sched/signal/sig_initialize.c | 14 ++++++++++++++ sched/signal/signal.h | 10 +++++++++- 4 files changed, 51 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..8f380df515300 100644 --- a/sched/signal/sig_action.c +++ b/sched/signal/sig_action.c @@ -67,12 +67,12 @@ static void nxsig_alloc_actionblock(void) /* 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 +100,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 +409,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/sig_initialize.c b/sched/signal/sig_initialize.c index 21b5c8025a284..0be80231da22c 100644 --- a/sched/signal/sig_initialize.c +++ b/sched/signal/sig_initialize.c @@ -55,6 +55,10 @@ struct sigpool_s sq_queue_t g_sigfreeaction; +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 +sigactq_t g_sigactions[CONFIG_SIG_PREALLOC_ACTIONS]; +#endif + /* The g_sigpendingaction data structure is a list of available pending * signal action structures. */ @@ -155,6 +159,9 @@ static void *nxsig_init_pendingsignalblock(FAR sq_queue_t *siglist, void nxsig_initialize(void) { FAR void *sigpool = &g_sigpool; +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 + int i; +#endif sched_trace_begin(); @@ -166,6 +173,13 @@ void nxsig_initialize(void) sq_init(&g_sigpendingsignal); sq_init(&g_sigpendingirqsignal); +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 + for (i = 0; i < CONFIG_SIG_PREALLOC_ACTIONS; i++) + { + sq_addlast((FAR sq_entry_t *)(g_sigactions + i), &g_sigfreeaction); + } +#endif + sigpool = nxsig_init_block(&g_sigpendingaction, sigpool, NUM_PENDING_ACTIONS, SIG_ALLOC_FIXED); sigpool = nxsig_init_block(&g_sigpendingirqaction, sigpool, diff --git a/sched/signal/signal.h b/sched/signal/signal.h index 0553b8e3b0f5e..3e5096696e01e 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 @@ -111,6 +110,15 @@ typedef struct sigq_s sigq_t; extern sq_queue_t g_sigfreeaction; +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 +extern sigactq_t g_sigactions[CONFIG_SIG_PREALLOC_ACTIONS]; +#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 + /* The g_sigpendingaction data structure is a list of available pending * signal action structures. */