1 /* 2 * Copyright (C) 2015-2017 Alibaba Group Holding Limited 3 */ 4 5 #ifndef K_TASK_H 6 #define K_TASK_H 7 8 #ifdef __cplusplus 9 extern "C" { 10 #endif 11 12 /** @addtogroup aos_rhino task 13 * Task management 14 * 15 * @{ 16 */ 17 18 19 /** 20 * Task status 21 */ 22 typedef enum { 23 K_SEED, 24 K_RDY, /**< READY, task in ready list (g_ready_queue) */ 25 K_PEND, /**< PEND, task in tick list (g_tick_head) and block list (sem/mutex/queue/...) */ 26 K_SUSPENDED, 27 K_PEND_SUSPENDED, 28 K_SLEEP, /**< SLEEP, task tick list (g_tick_head) */ 29 K_SLEEP_SUSPENDED, 30 K_DELETED, 31 } task_stat_t; 32 33 typedef void (*task_entry_t)(void *arg); 34 35 /** 36 * Task control information 37 */ 38 typedef struct { 39 /**< 40 * Task SP, update when task switching. 41 * Access by assemble code, so do not change position. 42 */ 43 void *task_stack; 44 /**< access by activation, so do not change position */ 45 const name_t *task_name; 46 #if (RHINO_CONFIG_TASK_INFO > 0) 47 /**< access by assemble code, so do not change position */ 48 void *user_info[RHINO_CONFIG_TASK_INFO_NUM]; 49 #endif 50 51 #if (RHINO_CONFIG_USER_SPACE > 0) 52 void *task_ustack; 53 uint32_t ustack_size; 54 uint32_t pid; 55 uint8_t mode; 56 uint8_t is_proc; 57 cpu_stack_t *task_ustack_base; 58 klist_t task_user; 59 void *task_group; 60 #endif 61 /**< 62 * Task stack info 63 * start 'task_stack_base', len 'stack_size * sizeof(cpu_stack_t)' 64 */ 65 cpu_stack_t *task_stack_base; 66 size_t stack_size; 67 /**< 68 * Put task into different linked lists according to the status: 69 * 1. ready queue. The list hade is g_ready_queue->cur_list_item[prio] 70 * 2. The pending queue. The list hade is blk_obj in the blocking object (sem / mutex / queue, etc.). 71 * The final blocking result is recorded in blk_state 72 */ 73 klist_t task_list; 74 /**< Count of entering the K_SUSPENDED state */ 75 suspend_nested_t suspend_count; 76 /**< Mutex owned by this task */ 77 struct mutex_s *mutex_list; 78 #if (RHINO_CONFIG_KOBJ_LIST > 0) 79 /**< Link all task for statistics */ 80 klist_t task_stats_item; 81 #endif 82 /**< Put task into the timeout list of the tick, list head is 'g_tick_head' */ 83 klist_t tick_list; 84 /**< When 'g_tick_count' reaches tick_match, task's PEND or SLEEP state expires. */ 85 tick_t tick_match; 86 /**< Countdown of the PEND state */ 87 tick_t tick_remain; 88 89 /**< Passing massage, for 'queue' and 'buf_queue' */ 90 void *msg; 91 #if (RHINO_CONFIG_BUF_QUEUE > 0) 92 /**< Record the msg length, for 'buf_queue'. */ 93 size_t bq_msg_size; 94 #endif 95 /**< */ 96 /**< Task status */ 97 task_stat_t task_state; 98 /**< Reasons for the end of the blocking state */ 99 blk_state_t blk_state; 100 101 /* Task block on mutex, queue, semphore, event */ 102 blk_obj_t *blk_obj; 103 104 uint32_t task_id; 105 #if (RHINO_CONFIG_MM_DEBUG > 0) 106 uint32_t task_alloc_size; 107 #endif 108 109 #if (RHINO_CONFIG_TASK_SEM > 0) 110 /**< Task semaphore */ 111 struct sem_s *task_sem_obj; 112 #endif 113 114 #if (RHINO_CONFIG_SYS_STATS > 0) 115 size_t task_free_stack_size; 116 ctx_switch_t task_ctx_switch_times; 117 uint64_t task_time_total_run; 118 uint64_t task_time_total_run_prev; 119 lr_timer_t task_time_this_run; 120 lr_timer_t task_exec_time; 121 lr_timer_t task_time_start; 122 hr_timer_t task_intrpt_disable_time_max; 123 hr_timer_t task_sched_disable_time_max; 124 #endif 125 126 #if (RHINO_CONFIG_SCHED_RR > 0) 127 /**< During this round of scheduling, tasks can execute 'time_slice' ticks */ 128 uint32_t time_slice; 129 /**< Once RR scheduling, tasks can execute a total of 'time_total' ticks */ 130 uint32_t time_total; 131 #endif 132 133 #if (RHINO_CONFIG_EVENT_FLAG > 0) 134 uint32_t pend_flags; 135 void *pend_info; 136 uint8_t pend_option; 137 #endif 138 /**< KSCHED_FIFO / KSCHED_RR / KSCHED_CFS */ 139 uint8_t sched_policy; 140 141 #if (RHINO_CONFIG_SCHED_CFS > 0) 142 cfs_node node; 143 #endif 144 /**< On which CPU the task runs */ 145 uint8_t cpu_num; 146 147 #if (RHINO_CONFIG_CPU_NUM > 1) 148 /**< Whether the task is binded to the cpu, 0 no, 1 yes */ 149 uint8_t cpu_binded; 150 /**< Whether the task is ready to execute, 0 no, 1 yes */ 151 uint8_t cur_exc; 152 klist_t task_del_item; 153 #endif 154 155 #if (RHINO_CONFIG_TASK_DEL > 0) 156 uint8_t cancel; 157 #endif 158 159 /**< current prio */ 160 uint8_t prio; 161 /**< base prio */ 162 uint8_t b_prio; 163 /**< buffer from internal malloc or caller input */ 164 uint8_t mm_alloc_flag; 165 166 void *ptcb; /* pthread control block */ 167 168 #if (RHINO_CONFIG_NEWLIBC_REENT > 0) 169 struct _reent *newlibc_reent; /* newlib libc reentrancy */ 170 #endif 171 } ktask_t; 172 173 /** 174 * Create a task and provide the stack space. 175 * 176 * @param[in] task the task to be created (the space is provided outside, by user) 177 * @param[in] name the name of task, which shall be unique 178 * @param[in] arg the parameter of task enter function 179 * @param[in] pri the priority of task 180 * @param[in] ticks the time slice 181 * @param[in] stack_buf the start address of task stack 182 * @param[in] stack_size task stack size = stack_size * sizeof(cpu_stack_t) 183 * @param[in] entry the entry function of task 184 * @param[in] autorun the autorunning flag of task 185 * 186 * @return the operation status, RHINO_SUCCESS is OK, others is error 187 */ 188 kstat_t krhino_task_create(ktask_t *task, const name_t *name, void *arg, 189 uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf, 190 size_t stack_size, task_entry_t entry, uint8_t autorun); 191 192 kstat_t krhino_cfs_task_create(ktask_t *task, const name_t *name, void *arg, 193 uint8_t prio, cpu_stack_t *stack_buf, size_t stack_size, 194 task_entry_t entry, uint8_t autorun); 195 196 #if (RHINO_CONFIG_CPU_NUM > 1) 197 /** 198 * Create a task and provide the stack space, bind the task to specific cpu. 199 * 200 * @param[in] task the task to be created (the space is provided outside, by user) 201 * @param[in] name the name of task, which shall be unique 202 * @param[in] arg the parameter of task enter function 203 * @param[in] pri the priority of task 204 * @param[in] ticks the time slice 205 * @param[in] stack_buf the start address of task stack 206 * @param[in] stack_size task stack size = stack_size * sizeof(cpu_stack_t) 207 * @param[in] entry the entry function of task 208 * @param[in] cpu_num the cpu that task bind to 209 * @param[in] autorun the autorunning flag of task 210 * 211 * @return the operation status, RHINO_SUCCESS is OK, others is error 212 */ 213 kstat_t krhino_task_cpu_create(ktask_t *task, const name_t *name, void *arg, 214 uint8_t prio, tick_t ticks, cpu_stack_t *stack_buf, 215 size_t stack_size, task_entry_t entry, uint8_t cpu_num, 216 uint8_t autorun); 217 218 kstat_t krhino_cfs_task_cpu_create(ktask_t *task, const name_t *name, void *arg, 219 uint8_t prio, cpu_stack_t *stack_buf, size_t stack_size, 220 task_entry_t entry, uint8_t cpu_num, uint8_t autorun); 221 222 /** 223 * Bind a task to specific cpu. 224 * 225 * @param[in] task the task to be binded 226 * @param[in] cpu_num the cpu that task bind to 227 * 228 * @return the operation status, RHINO_SUCCESS is OK, others is error 229 */ 230 kstat_t krhino_task_cpu_bind(ktask_t *task, uint8_t cpu_num); 231 232 /** 233 * Unbind a task. 234 * 235 * @param[in] task the task to be binded 236 * 237 * @return the operation status, RHINO_SUCCESS is OK, others is error 238 */ 239 kstat_t krhino_task_cpu_unbind(ktask_t *task); 240 #endif 241 242 243 #if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0) 244 /** 245 * Create a task and malloc the stack space. 246 * 247 * @param[out] task the task to be created (the space is provided inside, from heap) 248 * @param[in] name the name of task 249 * @param[in] arg the parameter of task enter function 250 * @param[in] pri the priority of task 251 * @param[in] ticks the time slice 252 * @param[in] stack task stack size = stack * sizeof(cpu_stack_t) 253 * @param[in] entry the entry function of task 254 * @param[in] autorun the autorunning flag of task 255 * 256 * @return the operation status, RHINO_SUCCESS is OK, others is error 257 */ 258 kstat_t krhino_task_dyn_create(ktask_t **task, const name_t *name, void *arg, 259 uint8_t pri, tick_t ticks, size_t stack, 260 task_entry_t entry, uint8_t autorun); 261 262 kstat_t krhino_cfs_task_dyn_create(ktask_t **task, const name_t *name, void *arg, 263 uint8_t pri, size_t stack, task_entry_t entry, 264 uint8_t autorun); 265 266 #if (RHINO_CONFIG_CPU_NUM > 1) 267 /** 268 * Create a task and malloc the stack space, bind the task to specific cpu. 269 * 270 * @param[in] task the task to be created (the space is provided inside, from heap) 271 * @param[in] name the name of task, which shall be unique 272 * @param[in] arg the parameter of task enter function 273 * @param[in] pri the priority of task 274 * @param[in] ticks the time slice 275 * @param[in] stack task stack size = stack * sizeof(cpu_stack_t) 276 * @param[in] entry the entry function of task 277 * @param[in] cpu_num the cpu that task bind to 278 * @param[in] autorun the autorunning flag of task 279 * 280 * @return the operation status, RHINO_SUCCESS is OK, others is error 281 */ 282 kstat_t krhino_task_cpu_dyn_create(ktask_t **task, const name_t *name, void *arg, 283 uint8_t pri, tick_t ticks, size_t stack, 284 task_entry_t entry, uint8_t cpu_num, uint8_t autorun); 285 286 kstat_t krhino_cfs_task_cpu_dyn_create(ktask_t **task, const name_t *name, void *arg, 287 uint8_t pri, size_t stack, task_entry_t entry, 288 uint8_t cpu_num, uint8_t autorun); 289 #endif 290 #endif 291 292 #if (RHINO_CONFIG_TASK_DEL > 0) 293 /** 294 * Delete a task, free the task stack. 295 * 296 * @param[in] task the task to be deleted. 297 * 298 * @return the operation status, RHINO_SUCCESS is OK, others is error 299 */ 300 kstat_t krhino_task_del(ktask_t *task); 301 #if (RHINO_CONFIG_KOBJ_DYN_ALLOC > 0) 302 /** 303 * Delete a task, free the task stack, free ktask_t. 304 * 305 * @param[in] task the task to be deleted. 306 * 307 * @return the operation status, RHINO_SUCCESS is OK, others is error 308 */ 309 kstat_t krhino_task_dyn_del(ktask_t *task); 310 #endif 311 312 /** 313 * Cancel a task. 314 * 315 * @param[in] task the task to be killed. 316 * 317 * @return the operation status, RHINO_SUCCESS is OK, others is error 318 */ 319 kstat_t krhino_task_cancel(ktask_t *task); 320 321 /** 322 * Check the task self whether is canceled or not. 323 * 324 * @param[in] NULL 325 * 326 * @return false or true 327 */ 328 RHINO_BOOL krhino_task_cancel_chk(void); 329 #endif 330 331 /** 332 * Task sleep for some ticks. 333 * 334 * @param[in] ticks the ticks to sleep 335 * 336 * @return the operation status, RHINO_SUCCESS is OK, others is error 337 */ 338 kstat_t krhino_task_sleep(tick_t ticks); 339 340 /** 341 * Yield a task. 342 * 343 * @param[in] NULL 344 * 345 * @return the operation status, RHINO_SUCCESS is OK, others is error 346 */ 347 kstat_t krhino_task_yield(void); 348 349 /** 350 * Get the current task for this cpu. 351 * 352 * @param[in] NULL 353 * 354 * @return the current task 355 */ 356 ktask_t *krhino_cur_task_get(void); 357 358 /** 359 * Suspend a task. 360 * 361 * @param[in] task the task to be suspended 362 * 363 * @return the operation status, RHINO_SUCCESS is OK, others is error 364 */ 365 kstat_t krhino_task_suspend(ktask_t *task); 366 367 /** 368 * Resume a task from SUSPEND. 369 * 370 * @param[in] task the task to be resumed 371 * 372 * @return the operation status, RHINO_SUCCESS is OK, others is error 373 */ 374 kstat_t krhino_task_resume(ktask_t *task); 375 376 /** 377 * Get min free stack size in the total runtime. 378 * 379 * @param[in] task the task where get free stack size. 380 * @param[out] free the free task stack size 381 * 382 * @return the operation status, RHINO_SUCCESS is OK, others is error 383 */ 384 kstat_t krhino_task_stack_min_free(ktask_t *task, size_t *free); 385 386 /** 387 * Change the priority of task. 388 * 389 * @param[in] task the task to be changed priority 390 * @param[in] pri the priority to be changed. 391 * @param[out] old_pri the old priority 392 * 393 * @return the operation status, RHINO_SUCCESS is OK, others is error 394 */ 395 kstat_t krhino_task_pri_change(ktask_t *task, uint8_t pri, uint8_t *old_pri); 396 397 /** 398 * Wakup the task, SUSPENDED/SLEEP/PEND -> READY. 399 * 400 * @param[in] task the task to be Wakup 401 * 402 * @return the operation status, RHINO_SUCCESS is OK, others is error 403 */ 404 kstat_t krhino_task_wait_abort(ktask_t *task); 405 406 #if (RHINO_CONFIG_SCHED_RR > 0) 407 /** 408 * Set task timeslice when KSCHED_RR. 409 * 410 * @param[in] task the task to be set timeslice 411 * @param[in] slice the task time slice 412 * 413 * @return the operation status, RHINO_SUCCESS is OK, others is error 414 */ 415 kstat_t krhino_task_time_slice_set(ktask_t *task, size_t slice); 416 417 /** 418 * Set task sched policy. 419 * 420 * @param[in] task the task to be set 421 * @param[in] policy KSCHED_FIFO / KSCHED_RR / KSCHED_CFS 422 * 423 * @return the operation status, RHINO_SUCCESS is OK, others is error 424 */ 425 kstat_t krhino_sched_policy_set(ktask_t *task, uint8_t policy); 426 427 428 /** 429 * Set task sched policy and priority. 430 * 431 * @param[in] task the task to be set timeslice 432 * @param[in] policy KSCHED_FIFO / KSCHED_RR / KSCHED_CFS 433 * @param[in] pri the prio of task 434 * 435 * @return the operation status, RHINO_SUCCESS is OK, others is error 436 */ 437 kstat_t krhino_sched_param_set(ktask_t *task, uint8_t policy, uint8_t pri); 438 439 /** 440 * Get task sched policy. 441 * 442 * @param[in] task the task to be get timeslice 443 * @param[out] policy KSCHED_FIFO / KSCHED_RR / KSCHED_CFS 444 * 445 * @return the operation status, RHINO_SUCCESS is OK, others is error 446 */ 447 kstat_t krhino_sched_policy_get(ktask_t *task, uint8_t *policy); 448 #endif 449 450 #if (RHINO_CONFIG_TASK_INFO > 0) 451 /** 452 * Set task private infomation. 453 * 454 * @param[in] task the task to be set private infomation 455 * @param[in] idx set the info[idx], < RHINO_CONFIG_TASK_INFO_NUM 456 * @param[in] info the private information 457 * 458 * @return the operation status, RHINO_SUCCESS is OK, others is error 459 */ 460 kstat_t krhino_task_info_set(ktask_t *task, size_t idx, void *info); 461 462 /** 463 * Get task private infomation. 464 * 465 * @param[in] task the task to be get private infomation 466 * @param[in] idx get the info[idx], < RHINO_CONFIG_TASK_INFO_NUM 467 * @param[out] info to save private infomation 468 * 469 * @return the task private information 470 */ 471 kstat_t krhino_task_info_get(ktask_t *task, size_t idx, void **info); 472 #endif 473 474 /** 475 * Task self delete, run when task ends. 476 * 477 * @param[in] NULL 478 * 479 * @return NULL 480 */ 481 void krhino_task_deathbed(void); 482 483 /** 484 * Get the task by name. 485 * 486 * @param[in] name task name 487 * 488 * @return the task 489 */ 490 ktask_t *krhino_task_find(name_t *name); 491 492 /** @} */ 493 494 #ifdef __cplusplus 495 } 496 #endif 497 498 #endif /* K_TASK_H */ 499 500