1 /*
2  * Copyright (C) 2015-2017 Alibaba Group Holding Limited
3  */
4 
5 #ifndef K_INTERNAL_H
6 #define K_INTERNAL_H
7 
8 #ifdef __cplusplus
9 extern "C" {
10 #endif
11 
12 /** @addtogroup aos_rhino internal
13  *  OS internal funtions
14  *
15  *  @{
16  */
17 
18 extern kstat_t g_sys_stat;
19 extern uint8_t g_idle_task_spawned[RHINO_CONFIG_CPU_NUM];
20 
21 extern runqueue_t g_ready_queue;
22 
23 /* System lock */
24 extern uint8_t g_sched_lock[RHINO_CONFIG_CPU_NUM];
25 extern uint8_t g_intrpt_nested_level[RHINO_CONFIG_CPU_NUM];
26 
27 /* highest pri ready task object */
28 extern ktask_t *g_preferred_ready_task[RHINO_CONFIG_CPU_NUM];
29 
30 /* current active task */
31 extern ktask_t *g_active_task[RHINO_CONFIG_CPU_NUM];
32 
33 /* global task ID */
34 extern uint32_t g_task_id;
35 
36 /* idle attribute */
37 extern ktask_t      g_idle_task[RHINO_CONFIG_CPU_NUM];
38 extern idle_count_t g_idle_count[RHINO_CONFIG_CPU_NUM];
39 extern cpu_stack_t  g_idle_task_stack[RHINO_CONFIG_CPU_NUM][RHINO_CONFIG_IDLE_TASK_STACK_SIZE];
40 extern per_cpu_t    g_per_cpu[RHINO_CONFIG_CPU_NUM];
41 
42 
43 /* tick attribute */
44 extern tick_t  g_tick_count;
45 extern klist_t g_tick_head;
46 
47 #if (RHINO_CONFIG_KOBJ_LIST > 0)
48 extern kobj_list_t g_kobj_list;
49 #endif
50 
51 #if (RHINO_CONFIG_TIMER > 0)
52 extern klist_t          g_timer_head;
53 extern tick_t           g_timer_count;
54 extern ktask_t          g_timer_task;
55 extern cpu_stack_t      g_timer_task_stack[RHINO_CONFIG_TIMER_TASK_STACK_SIZE];
56 extern kbuf_queue_t     g_timer_queue;
57 extern k_timer_queue_cb timer_queue_cb[RHINO_CONFIG_TIMER_MSG_NUM];
58 #endif
59 
60 #if (RHINO_CONFIG_SYS_STATS > 0)
61 extern hr_timer_t g_sched_disable_time_start;
62 extern hr_timer_t g_sched_disable_max_time;
63 extern hr_timer_t g_cur_sched_disable_max_time;
64 extern uint16_t   g_intrpt_disable_times;
65 extern hr_timer_t g_intrpt_disable_time_start;
66 extern hr_timer_t g_intrpt_disable_max_time;
67 extern hr_timer_t g_cur_intrpt_disable_max_time;
68 extern ctx_switch_t g_sys_ctx_switch_times;
69 #endif
70 
71 #if (RHINO_CONFIG_HW_COUNT > 0)
72 extern hr_timer_t g_sys_measure_waste;
73 #endif
74 
75 #if (RHINO_CONFIG_CPU_USAGE_STATS > 0)
76 extern ktask_t      g_cpu_usage_task;
77 extern cpu_stack_t  g_cpu_task_stack[RHINO_CONFIG_CPU_USAGE_TASK_STACK];
78 extern idle_count_t g_idle_count_max;
79 extern uint32_t     g_cpu_usage;
80 #endif
81 
82 #if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0)
83 extern ksem_t      g_res_sem;
84 extern klist_t     g_res_list;
85 extern ktask_t     g_dyn_task;
86 extern cpu_stack_t g_dyn_task_stack[RHINO_CONFIG_K_DYN_TASK_STACK];
87 #endif
88 
89 #if (RHINO_CONFIG_WORKQUEUE > 0)
90 extern klist_t      g_workqueue_list_head;
91 extern kmutex_t     g_workqueue_mutex;
92 extern kworkqueue_t g_workqueue_default;
93 extern cpu_stack_t  g_workqueue_stack[RHINO_CONFIG_WORKQUEUE_STACK_SIZE];
94 #endif
95 
96 #if (RHINO_CONFIG_MM_TLF > 0)
97 extern k_mm_head *g_kmm_head;
98 #endif
99 
100 #if (RHINO_CONFIG_CPU_NUM > 1)
101 extern kspinlock_t g_sys_lock;
102 extern klist_t     g_task_del_head;
103 #endif
104 
105 #define K_OBJ_STATIC_ALLOC 1u
106 #define K_OBJ_DYN_ALLOC 2u
107 
108 #define NULL_PARA_CHK(para)        \
109     do {                           \
110         if (para == NULL) {        \
111             return RHINO_NULL_PTR; \
112         }                          \
113     } while (0)
114 
115 #define INTRPT_NESTED_LEVEL_CHK()                        \
116     do {                                                 \
117         if (g_intrpt_nested_level[cpu_cur_get()] > 0u) { \
118             RHINO_CRITICAL_EXIT();                       \
119             return RHINO_NOT_CALLED_BY_INTRPT;           \
120         }                                                \
121     } while (0)
122 
123 
is_task_exec(ktask_t * task)124 RHINO_INLINE uint8_t is_task_exec(ktask_t *task)
125 {
126 #if (RHINO_CONFIG_CPU_NUM > 1)
127      if (task->cur_exc > 0u) {
128         return RHINO_TRUE;
129      }
130      else {
131         return RHINO_FALSE;
132      }
133 #else
134     if (g_active_task[0] == task) {
135         return RHINO_TRUE;
136     }
137     else {
138         return RHINO_FALSE;
139     }
140 #endif
141 }
142 
143 #define RT_MAX_PRI 99u
144 #define RT_MIN_PRI 0u
145 
146 #if (RHINO_CONFIG_TASK_DEL > 0)
147 #define TASK_CANCEL_CHK(obj)                                      \
148             do {                                               \
149                 if ((g_active_task[cur_cpu_num]->cancel == 1u) && (obj->blk_obj.cancel == 1u)) {\
150                     RHINO_CRITICAL_EXIT();                     \
151                     return RHINO_TASK_CANCELED;                \
152                 }                                              \
153             } while (0)
154 #else
155 #define TASK_CANCEL_CHK(obj)
156 #endif
157 
158 #define RES_FREE_NUM 4
159 
160 typedef struct
161 {
162     size_t   cnt;
163     void    *res[RES_FREE_NUM];
164     klist_t  res_list;
165 } res_free_t;
166 
167 ktask_t *preferred_cpu_ready_task_get(runqueue_t *rq, uint8_t cpu_num);
168 ktask_t *cfs_preferred_task_get(void);
169 
170 void core_sched(void);
171 void runqueue_init(runqueue_t *rq);
172 
173 void ready_list_add(runqueue_t *rq, ktask_t *task);
174 void ready_list_add_head(runqueue_t *rq, ktask_t *task);
175 void ready_list_add_tail(runqueue_t *rq, ktask_t *task);
176 void ready_list_rm(runqueue_t *rq, ktask_t *task);
177 void ready_list_head_to_tail(runqueue_t *rq, ktask_t *task);
178 
179 void time_slice_update(void);
180 void timer_task_sched(void);
181 
182 void pend_list_reorder(ktask_t *task);
183 void pend_task_wakeup(ktask_t *task);
184 void pend_to_blk_obj(blk_obj_t *blk_obj, ktask_t *task, tick_t timeout);
185 void pend_task_rm(ktask_t *task);
186 
187 kstat_t pend_state_end_proc(ktask_t *task, blk_obj_t *blk_obj);
188 
189 void idle_task(void *p_arg);
190 void         idle_count_set(idle_count_t value);
191 idle_count_t idle_count_get(void);
192 
193 void tick_list_init(void);
194 void tick_task_start(void);
195 void tick_list_rm(ktask_t *task);
196 void tick_list_insert(ktask_t *task, tick_t time);
197 void tick_list_update(tick_i_t ticks);
198 
199 uint8_t mutex_pri_limit(ktask_t *tcb, uint8_t pri);
200 void    mutex_task_pri_reset(ktask_t *tcb);
201 uint8_t mutex_pri_look(ktask_t *tcb, kmutex_t *mutex_rel);
202 
203 kstat_t task_pri_change(ktask_t *task, uint8_t new_pri);
204 
205 void ktimer_init(void);
206 
207 void intrpt_disable_measure_start(void);
208 void intrpt_disable_measure_stop(void);
209 __attribute__((weak)) void dyn_mem_proc_task_start(void);
210 void cpu_usage_stats_start(void);
211 
212 kstat_t ringbuf_init(k_ringbuf_t *p_ringbuf, void *buf, size_t len, size_t type,size_t block_size);
213 kstat_t ringbuf_reset(k_ringbuf_t *p_ringbuf);
214 kstat_t ringbuf_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
215 kstat_t ringbuf_head_push(k_ringbuf_t *p_ringbuf, void *data, size_t len);
216 kstat_t ringbuf_pop(k_ringbuf_t *p_ringbuf, void *pdata, size_t *plen);
217 uint8_t ringbuf_is_full(k_ringbuf_t *p_ringbuf);
218 uint8_t ringbuf_is_empty(k_ringbuf_t *p_ringbuf);
219 void    workqueue_init(void);
220 void    k_mm_init(void);
221 
222 #if (RHINO_CONFIG_PWRMGMT > 0)
223 void cpu_pwr_down(void);
224 void cpu_pwr_up(void);
225 #endif
226 
227 /** @} */
228 #ifdef __cplusplus
229 }
230 #endif
231 
232 #endif /* K_INTERNAL_H */
233 
234