1 /* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2006-03-28 Bernard first version 9 * 2006-04-29 Bernard implement thread timer 10 * 2006-04-30 Bernard added THREAD_DEBUG 11 * 2006-05-27 Bernard fixed the rt_thread_yield bug 12 * 2006-06-03 Bernard fixed the thread timer init bug 13 * 2006-08-10 Bernard fixed the timer bug in thread_sleep 14 * 2006-09-03 Bernard changed rt_timer_delete to rt_timer_detach 15 * 2006-09-03 Bernard implement rt_thread_detach 16 * 2008-02-16 Bernard fixed the rt_thread_timeout bug 17 * 2010-03-21 Bernard change the errno of rt_thread_delay/sleep to 18 * RT_EOK. 19 * 2010-11-10 Bernard add cleanup callback function in thread exit. 20 * 2011-09-01 Bernard fixed rt_thread_exit issue when the current 21 * thread preempted, which reported by Jiaxing Lee. 22 * 2011-09-08 Bernard fixed the scheduling issue in rt_thread_startup. 23 * 2012-12-29 Bernard fixed compiling warning. 24 * 2016-08-09 ArdaFu add thread suspend and resume hook. 25 * 2017-04-10 armink fixed the rt_thread_delete and rt_thread_detach 26 * bug when thread has not startup. 27 * 2018-11-22 Jesven yield is same to rt_schedule 28 * add support for tasks bound to cpu 29 */ 30 31 #include <rthw.h> 32 #include <rtthread.h> 33 34 extern rt_list_t rt_thread_defunct; 35 36 #ifdef RT_USING_HOOK 37 static void (*rt_thread_suspend_hook)(rt_thread_t thread); 38 static void (*rt_thread_resume_hook) (rt_thread_t thread); 39 static void (*rt_thread_inited_hook) (rt_thread_t thread); 40 41 /** 42 * @ingroup Hook 43 * This function sets a hook function when the system suspend a thread. 44 * 45 * @param hook the specified hook function 46 * 47 * @note the hook function must be simple and never be blocked or suspend. 48 */ 49 void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread)) 50 { 51 rt_thread_suspend_hook = hook; 52 } 53 54 /** 55 * @ingroup Hook 56 * This function sets a hook function when the system resume a thread. 57 * 58 * @param hook the specified hook function 59 * 60 * @note the hook function must be simple and never be blocked or suspend. 61 */ 62 void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread)) 63 { 64 rt_thread_resume_hook = hook; 65 } 66 67 /** 68 * @ingroup Hook 69 * This function sets a hook function when a thread is initialized. 70 * 71 * @param hook the specified hook function 72 */ 73 void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread)) 74 { 75 rt_thread_inited_hook = hook; 76 } 77 78 #endif 79 80 void rt_thread_exit(void) 81 { 82 struct rt_thread *thread; 83 register rt_base_t level; 84 85 /* get current thread */ 86 thread = rt_thread_self(); 87 88 /* disable interrupt */ 89 level = rt_hw_interrupt_disable(); 90 91 /* remove from schedule */ 92 rt_schedule_remove_thread(thread); 93 /* change stat */ 94 thread->stat = RT_THREAD_CLOSE; 95 96 /* remove it from timer list */ 97 rt_timer_detach(&thread->thread_timer); 98 99 if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) && 100 thread->cleanup == RT_NULL) 101 { 102 rt_object_detach((rt_object_t)thread); 103 } 104 else 105 { 106 /* insert to defunct thread list */ 107 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); 108 } 109 110 /* enable interrupt */ 111 rt_hw_interrupt_enable(level); 112 113 /* switch to next task */ 114 rt_schedule(); 115 } 116 117 static rt_err_t _rt_thread_init(struct rt_thread *thread, 118 const char *name, 119 void (*entry)(void *parameter), 120 void *parameter, 121 void *stack_start, 122 rt_uint32_t stack_size, 123 rt_uint8_t priority, 124 rt_uint32_t tick) 125 { 126 /* init thread list */ 127 rt_list_init(&(thread->tlist)); 128 129 thread->entry = (void *)entry; 130 thread->parameter = parameter; 131 132 /* stack init */ 133 thread->stack_addr = stack_start; 134 thread->stack_size = stack_size; 135 136 /* init thread stack */ 137 rt_memset(thread->stack_addr, '#', thread->stack_size); 138 #ifdef ARCH_CPU_STACK_GROWS_UPWARD 139 thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, 140 (void *)((char *)thread->stack_addr), 141 (void *)rt_thread_exit); 142 #else 143 thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter, 144 (void *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)), 145 (void *)rt_thread_exit); 146 #endif 147 148 /* priority init */ 149 RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX); 150 thread->init_priority = priority; 151 thread->current_priority = priority; 152 153 thread->number_mask = 0; 154 #if RT_THREAD_PRIORITY_MAX > 32 155 thread->number = 0; 156 thread->high_mask = 0; 157 #endif 158 159 /* tick init */ 160 thread->init_tick = tick; 161 thread->remaining_tick = tick; 162 163 /* error and flags */ 164 thread->error = RT_EOK; 165 thread->stat = RT_THREAD_INIT; 166 167 #ifdef RT_USING_SMP 168 /* not bind on any cpu */ 169 thread->bind_cpu = RT_CPUS_NR; 170 thread->oncpu = RT_CPU_DETACHED; 171 172 /* lock init */ 173 thread->scheduler_lock_nest = 0; 174 thread->cpus_lock_nest = 0; 175 #endif /*RT_USING_SMP*/ 176 177 /* initialize cleanup function and user data */ 178 thread->cleanup = 0; 179 thread->user_data = 0; 180 181 /* init thread timer */ 182 rt_timer_init(&(thread->thread_timer), 183 thread->name, 184 rt_thread_timeout, 185 thread, 186 0, 187 RT_TIMER_FLAG_ONE_SHOT); 188 189 /* initialize signal */ 190 #ifdef RT_USING_SIGNALS 191 thread->sig_mask = 0x00; 192 thread->sig_pending = 0x00; 193 194 thread->sig_ret = RT_NULL; 195 thread->sig_vectors = RT_NULL; 196 thread->si_list = RT_NULL; 197 #endif 198 199 #ifdef RT_USING_LWP 200 thread->lwp = RT_NULL; 201 #endif 202 203 RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread)); 204 205 return RT_EOK; 206 } 207 208 /** 209 * @addtogroup Thread 210 */ 211 212 /**@{*/ 213 214 /** 215 * This function will initialize a thread, normally it's used to initialize a 216 * static thread object. 217 * 218 * @param thread the static thread object 219 * @param name the name of thread, which shall be unique 220 * @param entry the entry function of thread 221 * @param parameter the parameter of thread enter function 222 * @param stack_start the start address of thread stack 223 * @param stack_size the size of thread stack 224 * @param priority the priority of thread 225 * @param tick the time slice if there are same priority thread 226 * 227 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 228 */ 229 rt_err_t rt_thread_init(struct rt_thread *thread, 230 const char *name, 231 void (*entry)(void *parameter), 232 void *parameter, 233 void *stack_start, 234 rt_uint32_t stack_size, 235 rt_uint8_t priority, 236 rt_uint32_t tick) 237 { 238 /* thread check */ 239 RT_ASSERT(thread != RT_NULL); 240 RT_ASSERT(stack_start != RT_NULL); 241 242 /* init thread object */ 243 rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name); 244 245 return _rt_thread_init(thread, 246 name, 247 entry, 248 parameter, 249 stack_start, 250 stack_size, 251 priority, 252 tick); 253 } 254 RTM_EXPORT(rt_thread_init); 255 256 /** 257 * This function will return self thread object 258 * 259 * @return the self thread object 260 */ 261 rt_thread_t rt_thread_self(void) 262 { 263 #ifdef RT_USING_SMP 264 rt_base_t lock; 265 rt_thread_t self; 266 267 lock = rt_hw_local_irq_disable(); 268 self = rt_cpu_self()->current_thread; 269 rt_hw_local_irq_enable(lock); 270 return self; 271 #else 272 extern rt_thread_t rt_current_thread; 273 274 return rt_current_thread; 275 #endif 276 } 277 RTM_EXPORT(rt_thread_self); 278 279 /** 280 * This function will start a thread and put it to system ready queue 281 * 282 * @param thread the thread to be started 283 * 284 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 285 */ 286 rt_err_t rt_thread_startup(rt_thread_t thread) 287 { 288 /* thread check */ 289 RT_ASSERT(thread != RT_NULL); 290 RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT); 291 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 292 293 /* set current priority to init priority */ 294 thread->current_priority = thread->init_priority; 295 296 /* calculate priority attribute */ 297 #if RT_THREAD_PRIORITY_MAX > 32 298 thread->number = thread->current_priority >> 3; /* 5bit */ 299 thread->number_mask = 1L << thread->number; 300 thread->high_mask = 1L << (thread->current_priority & 0x07); /* 3bit */ 301 #else 302 thread->number_mask = 1L << thread->current_priority; 303 #endif 304 305 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n", 306 thread->name, thread->init_priority)); 307 /* change thread stat */ 308 thread->stat = RT_THREAD_SUSPEND; 309 /* then resume it */ 310 rt_thread_resume(thread); 311 if (rt_thread_self() != RT_NULL) 312 { 313 /* do a scheduling */ 314 rt_schedule(); 315 } 316 317 return RT_EOK; 318 } 319 RTM_EXPORT(rt_thread_startup); 320 321 /** 322 * This function will detach a thread. The thread object will be removed from 323 * thread queue and detached/deleted from system object management. 324 * 325 * @param thread the thread to be deleted 326 * 327 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 328 */ 329 rt_err_t rt_thread_detach(rt_thread_t thread) 330 { 331 rt_base_t lock; 332 333 /* thread check */ 334 RT_ASSERT(thread != RT_NULL); 335 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 336 RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread)); 337 338 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) 339 { 340 /* remove from schedule */ 341 rt_schedule_remove_thread(thread); 342 } 343 344 /* release thread timer */ 345 rt_timer_detach(&(thread->thread_timer)); 346 347 /* change stat */ 348 thread->stat = RT_THREAD_CLOSE; 349 350 /* detach object */ 351 rt_object_detach((rt_object_t)thread); 352 353 if (thread->cleanup != RT_NULL) 354 { 355 /* disable interrupt */ 356 lock = rt_hw_interrupt_disable(); 357 358 /* insert to defunct thread list */ 359 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); 360 361 /* enable interrupt */ 362 rt_hw_interrupt_enable(lock); 363 } 364 365 return RT_EOK; 366 } 367 RTM_EXPORT(rt_thread_detach); 368 369 370 #ifdef RT_USING_HEAP 371 /** 372 * This function will create a thread object and allocate thread object memory 373 * and stack. 374 * 375 * @param name the name of thread, which shall be unique 376 * @param entry the entry function of thread 377 * @param parameter the parameter of thread enter function 378 * @param stack_size the size of thread stack 379 * @param priority the priority of thread 380 * @param tick the time slice if there are same priority thread 381 * 382 * @return the created thread object 383 */ 384 rt_thread_t rt_thread_create(const char *name, 385 void (*entry)(void *parameter), 386 void *parameter, 387 rt_uint32_t stack_size, 388 rt_uint8_t priority, 389 rt_uint32_t tick) 390 { 391 struct rt_thread *thread; 392 void *stack_start; 393 394 thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread, 395 name); 396 if (thread == RT_NULL) 397 return RT_NULL; 398 399 stack_start = (void *)RT_KERNEL_MALLOC(stack_size); 400 if (stack_start == RT_NULL) 401 { 402 /* allocate stack failure */ 403 rt_object_delete((rt_object_t)thread); 404 405 return RT_NULL; 406 } 407 408 _rt_thread_init(thread, 409 name, 410 entry, 411 parameter, 412 stack_start, 413 stack_size, 414 priority, 415 tick); 416 417 return thread; 418 } 419 RTM_EXPORT(rt_thread_create); 420 421 /** 422 * This function will delete a thread. The thread object will be removed from 423 * thread queue and deleted from system object management in the idle thread. 424 * 425 * @param thread the thread to be deleted 426 * 427 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 428 */ 429 rt_err_t rt_thread_delete(rt_thread_t thread) 430 { 431 rt_base_t lock; 432 433 /* thread check */ 434 RT_ASSERT(thread != RT_NULL); 435 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 436 RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE); 437 438 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) 439 { 440 /* remove from schedule */ 441 rt_schedule_remove_thread(thread); 442 } 443 444 /* release thread timer */ 445 rt_timer_detach(&(thread->thread_timer)); 446 447 /* change stat */ 448 thread->stat = RT_THREAD_CLOSE; 449 450 /* disable interrupt */ 451 lock = rt_hw_interrupt_disable(); 452 453 /* insert to defunct thread list */ 454 rt_list_insert_after(&rt_thread_defunct, &(thread->tlist)); 455 456 /* enable interrupt */ 457 rt_hw_interrupt_enable(lock); 458 459 return RT_EOK; 460 } 461 RTM_EXPORT(rt_thread_delete); 462 #endif 463 464 /** 465 * This function will let current thread yield processor, and scheduler will 466 * choose a highest thread to run. After yield processor, the current thread 467 * is still in READY state. 468 * 469 * @return RT_EOK 470 */ 471 rt_err_t rt_thread_yield(void) 472 { 473 rt_schedule(); 474 475 return RT_EOK; 476 } 477 RTM_EXPORT(rt_thread_yield); 478 479 /** 480 * This function will let current thread sleep for some ticks. 481 * 482 * @param tick the sleep ticks 483 * 484 * @return RT_EOK 485 */ 486 rt_err_t rt_thread_sleep(rt_tick_t tick) 487 { 488 register rt_base_t temp; 489 struct rt_thread *thread; 490 491 /* set to current thread */ 492 thread = rt_thread_self(); 493 RT_ASSERT(thread != RT_NULL); 494 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 495 496 /* disable interrupt */ 497 temp = rt_hw_interrupt_disable(); 498 499 /* suspend thread */ 500 rt_thread_suspend(thread); 501 502 /* reset the timeout of thread timer and start it */ 503 rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick); 504 rt_timer_start(&(thread->thread_timer)); 505 506 /* enable interrupt */ 507 rt_hw_interrupt_enable(temp); 508 509 rt_schedule(); 510 511 /* clear error number of this thread to RT_EOK */ 512 if (thread->error == -RT_ETIMEOUT) 513 thread->error = RT_EOK; 514 515 return RT_EOK; 516 } 517 518 /** 519 * This function will let current thread delay for some ticks. 520 * 521 * @param tick the delay ticks 522 * 523 * @return RT_EOK 524 */ 525 rt_err_t rt_thread_delay(rt_tick_t tick) 526 { 527 return rt_thread_sleep(tick); 528 } 529 RTM_EXPORT(rt_thread_delay); 530 531 /** 532 * This function will let current thread delay for some milliseconds. 533 * 534 * @param tick the delay time 535 * 536 * @return RT_EOK 537 */ 538 rt_err_t rt_thread_mdelay(rt_int32_t ms) 539 { 540 rt_tick_t tick; 541 542 tick = rt_tick_from_millisecond(ms); 543 544 return rt_thread_sleep(tick); 545 } 546 RTM_EXPORT(rt_thread_mdelay); 547 548 /** 549 * This function will control thread behaviors according to control command. 550 * 551 * @param thread the specified thread to be controlled 552 * @param cmd the control command, which includes 553 * RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread; 554 * RT_THREAD_CTRL_STARTUP for starting a thread; 555 * RT_THREAD_CTRL_CLOSE for delete a thread; 556 * RT_THREAD_CTRL_BIND_CPU for bind the thread to a CPU. 557 * @param arg the argument of control command 558 * 559 * @return RT_EOK 560 */ 561 rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg) 562 { 563 register rt_base_t temp; 564 565 /* thread check */ 566 RT_ASSERT(thread != RT_NULL); 567 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 568 569 switch (cmd) 570 { 571 case RT_THREAD_CTRL_CHANGE_PRIORITY: 572 /* disable interrupt */ 573 temp = rt_hw_interrupt_disable(); 574 575 /* for ready thread, change queue */ 576 if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY) 577 { 578 /* remove thread from schedule queue first */ 579 rt_schedule_remove_thread(thread); 580 581 /* change thread priority */ 582 thread->current_priority = *(rt_uint8_t *)arg; 583 584 /* recalculate priority attribute */ 585 #if RT_THREAD_PRIORITY_MAX > 32 586 thread->number = thread->current_priority >> 3; /* 5bit */ 587 thread->number_mask = 1 << thread->number; 588 thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ 589 #else 590 thread->number_mask = 1 << thread->current_priority; 591 #endif 592 593 /* insert thread to schedule queue again */ 594 rt_schedule_insert_thread(thread); 595 } 596 else 597 { 598 thread->current_priority = *(rt_uint8_t *)arg; 599 600 /* recalculate priority attribute */ 601 #if RT_THREAD_PRIORITY_MAX > 32 602 thread->number = thread->current_priority >> 3; /* 5bit */ 603 thread->number_mask = 1 << thread->number; 604 thread->high_mask = 1 << (thread->current_priority & 0x07); /* 3bit */ 605 #else 606 thread->number_mask = 1 << thread->current_priority; 607 #endif 608 } 609 610 /* enable interrupt */ 611 rt_hw_interrupt_enable(temp); 612 break; 613 614 case RT_THREAD_CTRL_STARTUP: 615 return rt_thread_startup(thread); 616 617 #ifdef RT_USING_HEAP 618 case RT_THREAD_CTRL_CLOSE: 619 return rt_thread_delete(thread); 620 #endif 621 622 #ifdef RT_USING_SMP 623 case RT_THREAD_CTRL_BIND_CPU: 624 { 625 rt_uint8_t cpu; 626 627 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT) 628 { 629 /* we only support bind cpu before started phase. */ 630 return RT_ERROR; 631 } 632 633 cpu = (rt_uint8_t)(size_t)arg; 634 thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu; 635 break; 636 } 637 #endif /*RT_USING_SMP*/ 638 default: 639 break; 640 } 641 642 return RT_EOK; 643 } 644 RTM_EXPORT(rt_thread_control); 645 646 /** 647 * This function will suspend the specified thread. 648 * 649 * @param thread the thread to be suspended 650 * 651 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 652 * 653 * @note if suspend self thread, after this function call, the 654 * rt_schedule() must be invoked. 655 */ 656 rt_err_t rt_thread_suspend(rt_thread_t thread) 657 { 658 register rt_base_t stat; 659 register rt_base_t temp; 660 661 /* thread check */ 662 RT_ASSERT(thread != RT_NULL); 663 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 664 665 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: %s\n", thread->name)); 666 667 stat = thread->stat & RT_THREAD_STAT_MASK; 668 if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING)) 669 { 670 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n", 671 thread->stat)); 672 return -RT_ERROR; 673 } 674 675 /* disable interrupt */ 676 temp = rt_hw_interrupt_disable(); 677 if (stat == RT_THREAD_RUNNING) 678 { 679 /* not suspend running status thread on other core */ 680 RT_ASSERT(thread == rt_thread_self()); 681 } 682 683 /* change thread stat */ 684 rt_schedule_remove_thread(thread); 685 thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK); 686 687 /* stop thread timer anyway */ 688 rt_timer_stop(&(thread->thread_timer)); 689 690 /* enable interrupt */ 691 rt_hw_interrupt_enable(temp); 692 693 RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread)); 694 return RT_EOK; 695 } 696 RTM_EXPORT(rt_thread_suspend); 697 698 /** 699 * This function will resume a thread and put it to system ready queue. 700 * 701 * @param thread the thread to be resumed 702 * 703 * @return the operation status, RT_EOK on OK, -RT_ERROR on error 704 */ 705 rt_err_t rt_thread_resume(rt_thread_t thread) 706 { 707 register rt_base_t temp; 708 709 /* thread check */ 710 RT_ASSERT(thread != RT_NULL); 711 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 712 713 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: %s\n", thread->name)); 714 715 if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND) 716 { 717 RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n", 718 thread->stat)); 719 720 return -RT_ERROR; 721 } 722 723 /* disable interrupt */ 724 temp = rt_hw_interrupt_disable(); 725 726 /* remove from suspend list */ 727 rt_list_remove(&(thread->tlist)); 728 729 rt_timer_stop(&thread->thread_timer); 730 731 /* enable interrupt */ 732 rt_hw_interrupt_enable(temp); 733 734 /* insert to schedule ready list */ 735 rt_schedule_insert_thread(thread); 736 737 RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread)); 738 return RT_EOK; 739 } 740 RTM_EXPORT(rt_thread_resume); 741 742 /** 743 * This function is the timeout function for thread, normally which is invoked 744 * when thread is timeout to wait some resource. 745 * 746 * @param parameter the parameter of thread timeout function 747 */ 748 void rt_thread_timeout(void *parameter) 749 { 750 struct rt_thread *thread; 751 752 thread = (struct rt_thread *)parameter; 753 754 /* thread check */ 755 RT_ASSERT(thread != RT_NULL); 756 RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND); 757 RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread); 758 759 /* set error number */ 760 thread->error = -RT_ETIMEOUT; 761 762 /* remove from suspend list */ 763 rt_list_remove(&(thread->tlist)); 764 765 /* insert to schedule ready list */ 766 rt_schedule_insert_thread(thread); 767 768 /* do schedule */ 769 rt_schedule(); 770 } 771 RTM_EXPORT(rt_thread_timeout); 772 773 /** 774 * This function will find the specified thread. 775 * 776 * @param name the name of thread finding 777 * 778 * @return the found thread 779 * 780 * @note please don't invoke this function in interrupt status. 781 */ 782 rt_thread_t rt_thread_find(char *name) 783 { 784 struct rt_object_information *information; 785 struct rt_object *object; 786 struct rt_list_node *node; 787 788 /* enter critical */ 789 if (rt_thread_self() != RT_NULL) 790 rt_enter_critical(); 791 792 /* try to find device object */ 793 information = rt_object_get_information(RT_Object_Class_Thread); 794 RT_ASSERT(information != RT_NULL); 795 for (node = information->object_list.next; 796 node != &(information->object_list); 797 node = node->next) 798 { 799 object = rt_list_entry(node, struct rt_object, list); 800 if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0) 801 { 802 /* leave critical */ 803 if (rt_thread_self() != RT_NULL) 804 rt_exit_critical(); 805 806 return (rt_thread_t)object; 807 } 808 } 809 810 /* leave critical */ 811 if (rt_thread_self() != RT_NULL) 812 rt_exit_critical(); 813 814 /* not found */ 815 return RT_NULL; 816 } 817 RTM_EXPORT(rt_thread_find); 818 819 /**@}*/ 820