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..4907f01f04f56 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,28 @@ static void nxsig_alloc_actionblock(void) irqstate_t flags; int i; + /* Use pre-allocated sigactions only once */ + +#if CONFIG_SIG_PREALLOC_ACTIONS > 0 + 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; + } +#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 +133,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 +442,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..86d7aee60ffce 100644 --- a/sched/signal/sig_initialize.c +++ b/sched/signal/sig_initialize.c @@ -155,6 +155,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(); 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