summaryrefslogtreecommitdiff
path: root/src/idle.c
diff options
context:
space:
mode:
authorsszlbg <[email protected]>2021-07-25 17:00:00 +0800
committersszlbg <[email protected]>2021-07-25 17:00:00 +0800
commitbf88963a3ec85ce6da013e4cd1c59ec5041d29e1 (patch)
treed4cd7d4fa3ff6e7b0c859a7660209787f47d168b /src/idle.c
parent88d4faf68735948d6310e2d2271d576c5de254a0 (diff)
parent2b201cbb00c512def085332d7fb09194656418b9 (diff)
Merge branch 'master' into at_client-rt_realloc_iss
# Conflicts: # components/net/at/src/at_client.c
Diffstat (limited to 'src/idle.c')
-rw-r--r--src/idle.c186
1 files changed, 150 insertions, 36 deletions
diff --git a/src/idle.c b/src/idle.c
index 59868352d8..a571e487cf 100644
--- a/src/idle.c
+++ b/src/idle.c
@@ -22,38 +22,48 @@
#ifdef RT_USING_MODULE
#include <dlmodule.h>
-#endif
+#endif /* RT_USING_MODULE */
-#if defined (RT_USING_HOOK)
+#ifdef RT_USING_HOOK
#ifndef RT_USING_IDLE_HOOK
#define RT_USING_IDLE_HOOK
-#endif
-#endif
+#endif /* RT_USING_IDLE_HOOK */
+#endif /* RT_USING_HOOK */
#ifndef IDLE_THREAD_STACK_SIZE
#if defined (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP)
#define IDLE_THREAD_STACK_SIZE 256
#else
#define IDLE_THREAD_STACK_SIZE 128
-#endif
-#endif
+#endif /* (RT_USING_IDLE_HOOK) || defined(RT_USING_HEAP) */
+#endif /* IDLE_THREAD_STACK_SIZE */
#ifdef RT_USING_SMP
#define _CPUS_NR RT_CPUS_NR
#else
#define _CPUS_NR 1
-#endif
+#endif /* RT_USING_SMP */
-extern rt_list_t rt_thread_defunct;
+static rt_list_t _rt_thread_defunct = RT_LIST_OBJECT_INIT(_rt_thread_defunct);;
static struct rt_thread idle[_CPUS_NR];
ALIGN(RT_ALIGN_SIZE)
static rt_uint8_t rt_thread_stack[_CPUS_NR][IDLE_THREAD_STACK_SIZE];
+#ifdef RT_USING_SMP
+#ifndef SYSTEM_THREAD_STACK_SIZE
+#define SYSTEM_THREAD_STACK_SIZE IDLE_THREAD_STACK_SIZE
+#endif
+static struct rt_thread rt_system_thread;
+ALIGN(RT_ALIGN_SIZE)
+static rt_uint8_t rt_system_stack[SYSTEM_THREAD_STACK_SIZE];
+static struct rt_semaphore system_sem;
+#endif
+
#ifdef RT_USING_IDLE_HOOK
#ifndef RT_IDLE_HOOK_LIST_SIZE
#define RT_IDLE_HOOK_LIST_SIZE 4
-#endif
+#endif /* RT_IDLE_HOOK_LIST_SIZE */
static void (*idle_hook_list[RT_IDLE_HOOK_LIST_SIZE])(void);
@@ -125,45 +135,77 @@ rt_err_t rt_thread_idle_delhook(void (*hook)(void))
return ret;
}
-#endif
+#endif /* RT_USING_IDLE_HOOK */
-#ifdef RT_USING_HEAP
+#ifdef RT_USING_MODULE
/* Return whether there is defunctional thread to be deleted. */
rt_inline int _has_defunct_thread(void)
{
/* The rt_list_isempty has prototype of "int rt_list_isempty(const rt_list_t *l)".
- * So the compiler has a good reason that the rt_thread_defunct list does
- * not change within rt_thread_idle_excute thus optimize the "while" loop
+ * So the compiler has a good reason that the _rt_thread_defunct list does
+ * not change within rt_thread_defunct_exceute thus optimize the "while" loop
* into a "if".
*
* So add the volatile qualifier here. */
- const volatile rt_list_t *l = (const volatile rt_list_t *)&rt_thread_defunct;
+ const volatile rt_list_t *l = (const volatile rt_list_t *)&_rt_thread_defunct;
return l->next != l;
}
+#endif /* RT_USING_MODULE */
+
+/* enqueue a thread to defunct queue
+ * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
+ */
+void rt_thread_defunct_enqueue(rt_thread_t thread)
+{
+ rt_list_insert_after(&_rt_thread_defunct, &thread->tlist);
+#ifdef RT_USING_SMP
+ rt_sem_release(&system_sem);
#endif
+}
+
+/* dequeue a thread from defunct queue
+ * it must be called between rt_hw_interrupt_disable and rt_hw_interrupt_enable
+ */
+rt_thread_t rt_thread_defunct_dequeue(void)
+{
+ rt_thread_t thread = RT_NULL;
+ rt_list_t *l = &_rt_thread_defunct;
+
+ if (l->next != l)
+ {
+ thread = rt_list_entry(l->next,
+ struct rt_thread,
+ tlist);
+ rt_list_remove(&(thread->tlist));
+ }
+ return thread;
+}
/**
* @ingroup Thread
*
* This function will perform system background job when system idle.
*/
-void rt_thread_idle_excute(void)
+static void rt_defunct_execute(void)
{
- /* Loop until there is no dead thread. So one call to rt_thread_idle_excute
+ /* Loop until there is no dead thread. So one call to rt_defunct_execute
* will do all the cleanups. */
- /* disable interrupt */
-
- RT_DEBUG_NOT_IN_INTERRUPT;
-
-#ifdef RT_USING_HEAP
while (1)
{
rt_base_t lock;
rt_thread_t thread;
+ void (*cleanup)(struct rt_thread *tid);
+
+#ifdef RT_USING_MODULE
+ struct rt_dlmodule *module = RT_NULL;
+#endif
+ RT_DEBUG_NOT_IN_INTERRUPT;
+ /* disable interrupt */
lock = rt_hw_interrupt_disable();
+#ifdef RT_USING_MODULE
/* check whether list is empty */
if (!_has_defunct_thread())
{
@@ -171,18 +213,56 @@ void rt_thread_idle_excute(void)
break;
}
/* get defunct thread */
- thread = rt_list_entry(rt_thread_defunct.next,
+ thread = rt_list_entry(_rt_thread_defunct.next,
struct rt_thread,
tlist);
+ module = (struct rt_dlmodule*)thread->module_id;
+ if (module)
+ {
+ dlmodule_destroy(module);
+ }
/* remove defunct thread */
rt_list_remove(&(thread->tlist));
- /* release thread's stack */
- RT_KERNEL_FREE(thread->stack_addr);
- /* delete thread object */
- rt_object_delete((rt_object_t)thread);
- rt_hw_interrupt_enable(lock);
- }
+#else
+ thread = rt_thread_defunct_dequeue();
+ if (!thread)
+ {
+ rt_hw_interrupt_enable(lock);
+ break;
+ }
+#endif
+ /* invoke thread cleanup */
+ cleanup = thread->cleanup;
+ if (cleanup != RT_NULL)
+ {
+ rt_hw_interrupt_enable(lock);
+ cleanup(thread);
+ lock = rt_hw_interrupt_disable();
+ }
+
+#ifdef RT_USING_SIGNALS
+ rt_thread_free_sig(thread);
+#endif
+
+ /* if it's a system object, not delete it */
+ if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
+ {
+ /* detach this object */
+ rt_object_detach((rt_object_t)thread);
+ /* enable interrupt */
+ rt_hw_interrupt_enable(lock);
+ }
+ else
+ {
+ rt_hw_interrupt_enable(lock);
+#ifdef RT_USING_HEAP
+ /* release thread's stack */
+ RT_KERNEL_FREE(thread->stack_addr);
+ /* delete thread object */
+ rt_object_delete((rt_object_t)thread);
#endif
+ }
+ }
}
extern void rt_system_power_manager(void);
@@ -196,28 +276,44 @@ static void rt_thread_idle_entry(void *parameter)
rt_hw_secondary_cpu_idle_exec();
}
}
-#endif
+#endif /* RT_USING_SMP */
while (1)
{
#ifdef RT_USING_IDLE_HOOK
rt_size_t i;
+ void (*idle_hook)(void);
for (i = 0; i < RT_IDLE_HOOK_LIST_SIZE; i++)
{
- if (idle_hook_list[i] != RT_NULL)
+ idle_hook = idle_hook_list[i];
+ if (idle_hook != RT_NULL)
{
- idle_hook_list[i]();
+ idle_hook();
}
}
-#endif
+#endif /* RT_USING_IDLE_HOOK */
+
+#ifndef RT_USING_SMP
+ rt_defunct_execute();
+#endif /* RT_USING_SMP */
- rt_thread_idle_excute();
#ifdef RT_USING_PM
rt_system_power_manager();
-#endif
+#endif /* RT_USING_PM */
+ }
+}
+
+#ifdef RT_USING_SMP
+static void rt_thread_system_entry(void *parameter)
+{
+ while (1)
+ {
+ rt_sem_take(&system_sem, RT_WAITING_FOREVER);
+ rt_defunct_execute();
}
}
+#endif
/**
* @ingroup SystemInit
@@ -244,10 +340,28 @@ void rt_thread_idle_init(void)
32);
#ifdef RT_USING_SMP
rt_thread_control(&idle[i], RT_THREAD_CTRL_BIND_CPU, (void*)i);
-#endif
+#endif /* RT_USING_SMP */
/* startup */
rt_thread_startup(&idle[i]);
}
+
+#ifdef RT_USING_SMP
+ RT_ASSERT(RT_THREAD_PRIORITY_MAX > 2);
+
+ rt_sem_init(&system_sem, "defunct", 1, RT_IPC_FLAG_FIFO);
+
+ /* create defunct thread */
+ rt_thread_init(&rt_system_thread,
+ "tsystem",
+ rt_thread_system_entry,
+ RT_NULL,
+ rt_system_stack,
+ sizeof(rt_system_stack),
+ RT_THREAD_PRIORITY_MAX - 2,
+ 32);
+ /* startup */
+ rt_thread_startup(&rt_system_thread);
+#endif
}
/**
@@ -262,7 +376,7 @@ rt_thread_t rt_thread_idle_gethandler(void)
register int id = rt_hw_cpu_id();
#else
register int id = 0;
-#endif
+#endif /* RT_USING_SMP */
return (rt_thread_t)(&idle[id]);
}