mirror of
https://github.com/apache/nuttx.git
synced 2026-05-22 05:42:05 +08:00
Performance improvement: Idle loop should not take MM semaphore if there is not garbage to be collected. This can cause loss of performance and thrashing in tasking
This commit is contained in:
+15
-3
@@ -1,7 +1,7 @@
|
||||
/****************************************************************************
|
||||
* include/nuttx/kmalloc.h
|
||||
*
|
||||
* Copyright (C) 2007-2008, 2011, 2013 Gregory Nutt. All rights reserved.
|
||||
* Copyright (C) 2007-2008, 2011, 2013, 2016 Gregory Nutt. All rights reserved.
|
||||
* Author: Gregory Nutt <gnutt@nuttx.org>
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@@ -177,7 +177,7 @@ void group_free(FAR struct task_group_s *group, FAR void *mem);
|
||||
/* Handles memory freed from an interrupt handler. In that context, kmm_free()
|
||||
* (or kumm_free()) cannot be called. Instead, the allocations are saved in a
|
||||
* list of delayed allocations that will be periodically cleaned up by
|
||||
* sched_garbagecollection().
|
||||
* sched_garbage_collection().
|
||||
*/
|
||||
|
||||
void sched_ufree(FAR void *address);
|
||||
@@ -196,7 +196,19 @@ void sched_kfree(FAR void *address);
|
||||
* the system for memory in some context.
|
||||
*/
|
||||
|
||||
void sched_garbagecollection(void);
|
||||
void sched_garbage_collection(void);
|
||||
|
||||
/* Is is not a good idea for the IDLE threads to take the KMM semaphore.
|
||||
* That can cause the IDLE thread to take processing time from higher
|
||||
* priority tasks. The IDLE threads will only take the KMM semaphore if
|
||||
* there is garbage to be collected.
|
||||
*
|
||||
* Certainly there is a race condition involved in sampling the garbage
|
||||
* state. The looping nature of the IDLE loops should catch any missed
|
||||
* garbage from the test on the next time arround.
|
||||
*/
|
||||
|
||||
bool sched_have_garbage(void);
|
||||
|
||||
#undef KMALLOC_EXTERN
|
||||
#if defined(__cplusplus)
|
||||
|
||||
@@ -97,6 +97,7 @@ int os_idletask(int argc, FAR char *argv[])
|
||||
/* Enter the IDLE loop */
|
||||
|
||||
sdbg("CPU%d: Beginning Idle Loop\n", this_cpu());
|
||||
|
||||
for (; ; )
|
||||
{
|
||||
/* Perform garbage collection (if it is not being done by the worker
|
||||
@@ -118,9 +119,9 @@ int os_idletask(int argc, FAR char *argv[])
|
||||
* queue so that is done in a safer context.
|
||||
*/
|
||||
|
||||
if (kmm_trysemaphore() == 0)
|
||||
if (sched_have_garbage() && kmm_trysemaphore() == 0)
|
||||
{
|
||||
sched_garbagecollection();
|
||||
sched_garbage_collection();
|
||||
kmm_givesemaphore();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -415,11 +415,13 @@ void os_start(void)
|
||||
#endif
|
||||
{
|
||||
FAR dq_queue_t *tasklist;
|
||||
int hashndx;
|
||||
|
||||
/* Assign the process ID(s) of ZERO to the idle task(s) */
|
||||
|
||||
g_pidhash[PIDHASH(g_lastpid)].tcb = &g_idletcb[cpu].cmn;
|
||||
g_pidhash[PIDHASH(g_lastpid)].pid = g_lastpid;
|
||||
hashndx = PIDHASH(g_lastpid);
|
||||
g_pidhash[hashndx].tcb = &g_idletcb[cpu].cmn;
|
||||
g_pidhash[hashndx].pid = g_lastpid;
|
||||
|
||||
/* Initialize a TCB for this thread of execution. NOTE: The default
|
||||
* value for most components of the g_idletcb are zero. The entire
|
||||
@@ -783,9 +785,9 @@ void os_start(void)
|
||||
* queue so that is done in a safer context.
|
||||
*/
|
||||
|
||||
if (kmm_trysemaphore() == 0)
|
||||
if (sched_have_garbage() && kmm_trysemaphore() == 0)
|
||||
{
|
||||
sched_garbagecollection();
|
||||
sched_garbage_collection();
|
||||
kmm_givesemaphore();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -104,6 +104,29 @@ static inline void sched_kucleanup(void)
|
||||
#endif
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_have_kugarbage
|
||||
*
|
||||
* Description:
|
||||
* Return TRUE if there is user heap garbage to be collected.
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* TRUE if there is kernel heap garbage to be collected.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
|
||||
defined(CONFIG_MM_KERNEL_HEAP)
|
||||
static inline bool sched_have_kugarbage(void)
|
||||
{
|
||||
return (g_delayed_kufree.head != NULL);
|
||||
#else
|
||||
# define sched_have_kugarbage() false
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_kcleanup
|
||||
*
|
||||
@@ -155,11 +178,35 @@ static inline void sched_kcleanup(void)
|
||||
# define sched_kcleanup()
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_have_kgarbage
|
||||
*
|
||||
* Description:
|
||||
* Return TRUE if there is kernal heap garbage to be collected.
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* TRUE if there is kernel heap garbage to be collected.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#if (defined(CONFIG_BUILD_PROTECTED) || defined(CONFIG_BUILD_KERNEL)) && \
|
||||
defined(CONFIG_MM_KERNEL_HEAP)
|
||||
static inline bool sched_have_kgarbage(void)
|
||||
{
|
||||
return (g_delayed_kfree.head != NULL);
|
||||
#else
|
||||
# define sched_have_kgarbage() false
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
* Public Functions
|
||||
****************************************************************************/
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_garbagecollection
|
||||
* Name: sched_garbage_collection
|
||||
*
|
||||
* Description:
|
||||
* Clean-up memory de-allocations that we queued because they could not
|
||||
@@ -180,7 +227,7 @@ static inline void sched_kcleanup(void)
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
void sched_garbagecollection(void)
|
||||
void sched_garbage_collection(void)
|
||||
{
|
||||
/* Handle deferred deallocations for the kernel heap */
|
||||
|
||||
@@ -190,3 +237,31 @@ void sched_garbagecollection(void)
|
||||
|
||||
sched_kucleanup();
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
* Name: sched_have_garbage
|
||||
*
|
||||
* Description:
|
||||
* Return TRUE if there is garbage to be collected.
|
||||
*
|
||||
* Is is not a good idea for the IDLE threads to take the KMM semaphore.
|
||||
* That can cause the IDLE thread to take processing time from higher
|
||||
* priority tasks. The IDLE threads will only take the KMM semaphore if
|
||||
* there is garbage to be collected.
|
||||
*
|
||||
* Certainly there is a race condition involved in sampling the garbage
|
||||
* state. The looping nature of the IDLE loops should catch any missed
|
||||
* garbage from the test on the next time arround.
|
||||
*
|
||||
* Input parameters:
|
||||
* None
|
||||
*
|
||||
* Returned Value:
|
||||
* TRUE if there is garbage to be collected.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
bool sched_have_garbage(void)
|
||||
{
|
||||
return (sched_have_kgarbage() || sched_have_kugarbage());
|
||||
}
|
||||
|
||||
@@ -120,7 +120,7 @@ static int work_hpthread(int argc, char *argv[])
|
||||
* thread instead.
|
||||
*/
|
||||
|
||||
sched_garbagecollection();
|
||||
sched_garbage_collection();
|
||||
#endif
|
||||
|
||||
/* Then process queued work. work_process will not return until: (1)
|
||||
|
||||
@@ -156,7 +156,7 @@ static int work_lpthread(int argc, char *argv[])
|
||||
* the garbage collection.
|
||||
*/
|
||||
|
||||
sched_garbagecollection();
|
||||
sched_garbage_collection();
|
||||
|
||||
/* Then process queued work. work_process will not return until:
|
||||
* (1) there is no further work in the work queue, and (2) the polling
|
||||
|
||||
Reference in New Issue
Block a user