Jelajahi Sumber

[kernel][idle] Add idle hook list.

armink 6 tahun lalu
induk
melakukan
e9c165034e
3 mengubah file dengan 86 tambahan dan 6 penghapusan
  1. 2 1
      include/rtthread.h
  2. 9 0
      src/Kconfig
  3. 75 5
      src/idle.c

+ 2 - 1
include/rtthread.h

@@ -173,7 +173,8 @@ void rt_thread_inited_sethook (void (*hook)(rt_thread_t thread));
  */
 void rt_thread_idle_init(void);
 #if defined(RT_USING_HOOK) || defined(RT_USING_IDLE_HOOK)
-void rt_thread_idle_sethook(void (*hook)(void));
+rt_err_t rt_thread_idle_sethook(void (*hook)(void));
+rt_err_t rt_thread_idle_delhook(void (*hook)(void));
 #endif
 void rt_thread_idle_excute(void);
 rt_thread_t rt_thread_idle_gethandler(void);

+ 9 - 0
src/Kconfig

@@ -75,6 +75,15 @@ config RT_USING_HOOK
         Enable the hook function when system running, such as idle thread hook, 
         thread context switch etc.
 
+    if RT_USING_HOOK
+    config RT_IDEL_HOOK_LIST_SIZE
+        int "The max size of idel hook list"
+        default 4
+        range 1 16
+        help
+            The system has a hook list. This is the hook list size.
+    endif
+
 config IDLE_THREAD_STACK_SIZE
     int "The stack size of idle thread"
     default 256

+ 75 - 5
src/idle.c

@@ -52,7 +52,12 @@ static rt_uint8_t rt_thread_stack[IDLE_THREAD_STACK_SIZE];
 extern rt_list_t rt_thread_defunct;
 
 #ifdef RT_USING_IDLE_HOOK
-static void (*rt_thread_idle_hook)();
+
+#ifndef RT_IDEL_HOOK_LIST_SIZE
+#define RT_IDEL_HOOK_LIST_SIZE          4
+#endif
+
+static void (*idle_hook_list[RT_IDEL_HOOK_LIST_SIZE])();
 
 /**
  * @ingroup Hook
@@ -61,12 +66,69 @@ static void (*rt_thread_idle_hook)();
  *
  * @param hook the specified hook function
  *
+ * @return RT_EOK: set OK
+ *         -RT_EFULL: hook list is full
+ *
  * @note the hook function must be simple and never be blocked or suspend.
  */
-void rt_thread_idle_sethook(void (*hook)(void))
+rt_err_t rt_thread_idle_sethook(void (*hook)(void))
 {
-    rt_thread_idle_hook = hook;
+    rt_size_t i;
+    rt_base_t level;
+
+    /* disable interrupt */
+    level = rt_hw_interrupt_disable();
+
+    for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
+    {
+        if (idle_hook_list[i] == RT_NULL)
+        {
+            idle_hook_list[i] = hook;
+            /* enable interrupt */
+            rt_hw_interrupt_enable(level);
+
+            return RT_EOK;
+        }
+    }
+    /* enable interrupt */
+    rt_hw_interrupt_enable(level);
+
+    return -RT_EFULL;
 }
+
+/**
+ * delete the idle hook on hook list
+ *
+ * @param hook the specified hook function
+ *
+ * @return RT_EOK: delete OK
+ *         -RT_ENOSYS: hook was not found
+ */
+rt_err_t rt_thread_idle_delhook(void (*hook)(void))
+{
+    rt_size_t i;
+    rt_base_t level;
+
+    /* disable interrupt */
+    level = rt_hw_interrupt_disable();
+
+    for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
+    {
+        if (idle_hook_list[i] == hook)
+        {
+            idle_hook_list[i] = RT_NULL;
+            /* enable interrupt */
+            rt_hw_interrupt_enable(level);
+
+            return RT_EOK;
+        }
+    }
+    /* enable interrupt */
+    rt_hw_interrupt_enable(level);
+
+    return -RT_ENOSYS;
+}
+
 #endif
 
 /* Return whether there is defunctional thread to be deleted. */
@@ -174,12 +236,20 @@ void rt_thread_idle_excute(void)
 
 static void rt_thread_idle_entry(void *parameter)
 {
+#ifdef RT_USING_IDLE_HOOK
+    rt_size_t i;
+#endif
+
     while (1)
     {
+
 #ifdef RT_USING_IDLE_HOOK
-        if (rt_thread_idle_hook != RT_NULL)
+        for (i = 0; i < RT_IDEL_HOOK_LIST_SIZE; i++)
         {
-            rt_thread_idle_hook();
+            if (idle_hook_list[i] != RT_NULL)
+            {
+                idle_hook_list[i]();
+            }
         }
 #endif