thread.c 20.2 KB
Newer Older
1 2 3
/*
 * File      : thread.c
 * This file is part of RT-Thread RTOS
D
dzzxzz 已提交
4
 * COPYRIGHT (C) 2006 - 2012, RT-Thread Development Team
5
 *
B
Bernard Xiong 已提交
6 7 8 9 10 11 12 13 14 15 16 17 18
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License along
 *  with this program; if not, write to the Free Software Foundation, Inc.,
 *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19 20 21 22 23
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-28     Bernard      first version
 * 2006-04-29     Bernard      implement thread timer
24 25 26 27 28
 * 2006-04-30     Bernard      added THREAD_DEBUG
 * 2006-05-27     Bernard      fixed the rt_thread_yield bug
 * 2006-06-03     Bernard      fixed the thread timer init bug
 * 2006-08-10     Bernard      fixed the timer bug in thread_sleep
 * 2006-09-03     Bernard      changed rt_timer_delete to rt_timer_detach
29
 * 2006-09-03     Bernard      implement rt_thread_detach
30
 * 2008-02-16     Bernard      fixed the rt_thread_timeout bug
31 32
 * 2010-03-21     Bernard      change the errno of rt_thread_delay/sleep to
 *                             RT_EOK.
33
 * 2010-11-10     Bernard      add cleanup callback function in thread exit.
34 35
 * 2011-09-01     Bernard      fixed rt_thread_exit issue when the current
 *                             thread preempted, which reported by Jiaxing Lee.
36
 * 2011-09-08     Bernard      fixed the scheduling issue in rt_thread_startup.
37
 * 2012-12-29     Bernard      fixed compiling warning.
38
 * 2016-08-09     ArdaFu       add thread suspend and resume hook.
39 40 41 42 43 44
 */

#include <rtthread.h>
#include <rthw.h>

extern rt_list_t rt_thread_priority_table[RT_THREAD_PRIORITY_MAX];
D
dzzxzz 已提交
45
extern struct rt_thread *rt_current_thread;
46 47
extern rt_list_t rt_thread_defunct;

48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#ifdef RT_USING_HOOK

static void (*rt_thread_suspend_hook)(rt_thread_t thread);
static void (*rt_thread_resume_hook)(rt_thread_t thread);
/**
 * @ingroup Hook
 * This function sets a hook function when the system suspend a thread. 
 *
 * @param hook the specified hook function
 *
 * @note the hook function must be simple and never be blocked or suspend.
 */
void rt_thread_suspend_sethook(void (*hook)(rt_thread_t thread))
{
    rt_thread_suspend_hook = hook;
}
/**
 * @ingroup Hook
 * This function sets a hook function when the system resume a thread. 
 *
 * @param hook the specified hook function
 *
 * @note the hook function must be simple and never be blocked or suspend.
 */
void rt_thread_resume_sethook(void (*hook)(rt_thread_t thread))
{
    rt_thread_resume_hook = hook;
}
#endif

78
void rt_thread_exit(void)
79
{
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
    struct rt_thread *thread;
    register rt_base_t level;

    /* get current thread */
    thread = rt_current_thread;

    /* disable interrupt */
    level = rt_hw_interrupt_disable();

    /* remove from schedule */
    rt_schedule_remove_thread(thread);
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;

    /* remove it from timer list */
95
    rt_timer_detach(&thread->thread_timer);
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112

    if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
        thread->cleanup == RT_NULL)
    {
        rt_object_detach((rt_object_t)thread);
    }
    else
    {
        /* insert to defunct thread list */
        rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    /* switch to next task */
    rt_schedule();
113
}
114

D
dzzxzz 已提交
115
static rt_err_t _rt_thread_init(struct rt_thread *thread,
116 117 118 119 120 121 122
                                const char       *name,
                                void (*entry)(void *parameter),
                                void             *parameter,
                                void             *stack_start,
                                rt_uint32_t       stack_size,
                                rt_uint8_t        priority,
                                rt_uint32_t       tick)
123
{
124 125 126 127 128 129 130 131
    /* init thread list */
    rt_list_init(&(thread->tlist));

    thread->entry = (void *)entry;
    thread->parameter = parameter;

    /* stack init */
    thread->stack_addr = stack_start;
W
weety 已提交
132
    thread->stack_size = stack_size;
133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165

    /* init thread stack */
    rt_memset(thread->stack_addr, '#', thread->stack_size);
    thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
        (void *)((char *)thread->stack_addr + thread->stack_size - 4),
        (void *)rt_thread_exit);

    /* priority init */
    RT_ASSERT(priority < RT_THREAD_PRIORITY_MAX);
    thread->init_priority    = priority;
    thread->current_priority = priority;

    /* tick init */
    thread->init_tick      = tick;
    thread->remaining_tick = tick;

    /* error and flags */
    thread->error = RT_EOK;
    thread->stat  = RT_THREAD_INIT;

    /* initialize cleanup function and user data */
    thread->cleanup   = 0;
    thread->user_data = 0;

    /* init thread timer */
    rt_timer_init(&(thread->thread_timer),
                  thread->name,
                  rt_thread_timeout,
                  thread,
                  0,
                  RT_TIMER_FLAG_ONE_SHOT);

    return RT_EOK;
166 167 168 169 170 171 172 173 174
}

/**
 * @addtogroup Thread
 */

/*@{*/

/**
B
bernard.xiong@gmail.com 已提交
175 176
 * This function will initialize a thread, normally it's used to initialize a
 * static thread object.
177 178 179 180 181 182 183 184 185 186
 *
 * @param thread the static thread object
 * @param name the name of thread, which shall be unique
 * @param entry the entry function of thread
 * @param parameter the parameter of thread enter function
 * @param stack_start the start address of thread stack
 * @param stack_size the size of thread stack
 * @param priority the priority of thread
 * @param tick the time slice if there are same priority thread
 *
B
bernard.xiong@gmail.com 已提交
187
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
188
 */
D
dzzxzz 已提交
189
rt_err_t rt_thread_init(struct rt_thread *thread,
190 191 192 193 194 195 196
                        const char       *name,
                        void (*entry)(void *parameter),
                        void             *parameter,
                        void             *stack_start,
                        rt_uint32_t       stack_size,
                        rt_uint8_t        priority,
                        rt_uint32_t       tick)
197
{
198 199 200 201 202 203 204 205 206 207 208 209 210 211 212
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(stack_start != RT_NULL);

    /* init thread object */
    rt_object_init((rt_object_t)thread, RT_Object_Class_Thread, name);

    return _rt_thread_init(thread,
                           name,
                           entry,
                           parameter,
                           stack_start,
                           stack_size,
                           priority,
                           tick);
213
}
214
RTM_EXPORT(rt_thread_init);
215 216 217 218 219 220

/**
 * This function will return self thread object
 *
 * @return the self thread object
 */
D
dzzxzz 已提交
221
rt_thread_t rt_thread_self(void)
222
{
223
    return rt_current_thread;
224
}
225
RTM_EXPORT(rt_thread_self);
226 227 228 229 230 231

/**
 * This function will start a thread and put it to system ready queue
 *
 * @param thread the thread to be started
 *
B
bernard.xiong@gmail.com 已提交
232
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
233
 */
D
dzzxzz 已提交
234
rt_err_t rt_thread_startup(rt_thread_t thread)
235
{
236 237 238
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(thread->stat == RT_THREAD_INIT);
239

240 241
    /* set current priority to init priority */
    thread->current_priority = thread->init_priority;
242

243
    /* calculate priority attribute */
244
#if RT_THREAD_PRIORITY_MAX > 32
245 246 247
    thread->number      = thread->current_priority >> 3;            /* 5bit */
    thread->number_mask = 1L << thread->number;
    thread->high_mask   = 1L << (thread->current_priority & 0x07);  /* 3bit */
248
#else
249
    thread->number_mask = 1L << thread->current_priority;
250 251
#endif

252
    RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",
253
                                   thread->name, thread->init_priority));
254 255 256 257 258 259 260 261 262 263 264
    /* change thread stat */
    thread->stat = RT_THREAD_SUSPEND;
    /* then resume it */
    rt_thread_resume(thread);
    if (rt_thread_self() != RT_NULL)
    {
        /* do a scheduling */
        rt_schedule();
    }

    return RT_EOK;
265
}
266
RTM_EXPORT(rt_thread_startup);
267 268

/**
B
bernard.xiong@gmail.com 已提交
269 270
 * This function will detach a thread. The thread object will be removed from
 * thread queue and detached/deleted from system object management.
271 272 273
 *
 * @param thread the thread to be deleted
 *
B
bernard.xiong@gmail.com 已提交
274
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
275
 */
D
dzzxzz 已提交
276
rt_err_t rt_thread_detach(rt_thread_t thread)
277
{
278
    rt_base_t lock;
279

280 281
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
282

283 284
    /* remove from schedule */
    rt_schedule_remove_thread(thread);
285

286 287
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
288

289 290
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;
291

292 293
    /* detach object */
    rt_object_detach((rt_object_t)thread);
294

295 296 297 298
    if (thread->cleanup != RT_NULL)
    {
        /* disable interrupt */
        lock = rt_hw_interrupt_disable();
299

300 301
        /* insert to defunct thread list */
        rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
302

303 304 305
        /* enable interrupt */
        rt_hw_interrupt_enable(lock);
    }
306

307
    return RT_EOK;
308
}
309 310
RTM_EXPORT(rt_thread_detach);

311 312

#ifdef RT_USING_HEAP
313 314 315 316 317 318 319 320 321 322 323 324 325 326
/**
 * This function will create a thread object and allocate thread object memory
 * and stack.
 *
 * @param name the name of thread, which shall be unique
 * @param entry the entry function of thread
 * @param parameter the parameter of thread enter function
 * @param stack_size the size of thread stack
 * @param priority the priority of thread
 * @param tick the time slice if there are same priority thread
 *
 * @return the created thread object
 */
rt_thread_t rt_thread_create(const char *name,
327 328 329 330 331
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick)
332
{
333 334 335 336 337 338 339 340
    struct rt_thread *thread;
    void *stack_start;

    thread = (struct rt_thread *)rt_object_allocate(RT_Object_Class_Thread,
                                                    name);
    if (thread == RT_NULL)
        return RT_NULL;

B
Bernard Xiong 已提交
341
    stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359
    if (stack_start == RT_NULL)
    {
        /* allocate stack failure */
        rt_object_delete((rt_object_t)thread);

        return RT_NULL;
    }

    _rt_thread_init(thread,
                    name,
                    entry,
                    parameter,
                    stack_start,
                    stack_size,
                    priority,
                    tick);

    return thread;
360
}
361
RTM_EXPORT(rt_thread_create);
362

363
/**
B
bernard.xiong@gmail.com 已提交
364
 * This function will delete a thread. The thread object will be removed from
365
 * thread queue and deleted from system object management in the idle thread.
366 367 368
 *
 * @param thread the thread to be deleted
 *
B
bernard.xiong@gmail.com 已提交
369
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
370
 */
D
dzzxzz 已提交
371
rt_err_t rt_thread_delete(rt_thread_t thread)
372
{
373
    rt_base_t lock;
374

375 376
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
377

378 379
    /* remove from schedule */
    rt_schedule_remove_thread(thread);
380

381 382
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
383

384 385
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;
386

387 388
    /* disable interrupt */
    lock = rt_hw_interrupt_disable();
389

390 391
    /* insert to defunct thread list */
    rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
392

393 394
    /* enable interrupt */
    rt_hw_interrupt_enable(lock);
395

396
    return RT_EOK;
397
}
398
RTM_EXPORT(rt_thread_delete);
399 400 401
#endif

/**
B
bernard.xiong@gmail.com 已提交
402 403 404
 * This function will let current thread yield processor, and scheduler will
 * choose a highest thread to run. After yield processor, the current thread
 * is still in READY state.
405
 *
B
bernard.xiong@gmail.com 已提交
406
 * @return RT_EOK
407
 */
D
dzzxzz 已提交
408
rt_err_t rt_thread_yield(void)
409
{
410 411
    register rt_base_t level;
    struct rt_thread *thread;
412

413 414
    /* disable interrupt */
    level = rt_hw_interrupt_disable();
415

416 417
    /* set to current thread */
    thread = rt_current_thread;
418

419 420 421 422 423 424
    /* if the thread stat is READY and on ready queue list */
    if (thread->stat == RT_THREAD_READY &&
        thread->tlist.next != thread->tlist.prev)
    {
        /* remove thread from thread list */
        rt_list_remove(&(thread->tlist));
425

426 427 428
        /* put thread to end of ready queue */
        rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                              &(thread->tlist));
429

430 431
        /* enable interrupt */
        rt_hw_interrupt_enable(level);
432

433
        rt_schedule();
434

435 436
        return RT_EOK;
    }
437

438 439
    /* enable interrupt */
    rt_hw_interrupt_enable(level);
440

441
    return RT_EOK;
442
}
443
RTM_EXPORT(rt_thread_yield);
444 445 446 447 448 449

/**
 * This function will let current thread sleep for some ticks.
 *
 * @param tick the sleep ticks
 *
B
bernard.xiong@gmail.com 已提交
450
 * @return RT_EOK
451
 */
D
dzzxzz 已提交
452
rt_err_t rt_thread_sleep(rt_tick_t tick)
453
{
454 455
    register rt_base_t temp;
    struct rt_thread *thread;
456

457 458 459 460 461
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
    /* set to current thread */
    thread = rt_current_thread;
    RT_ASSERT(thread != RT_NULL);
462

463 464
    /* suspend thread */
    rt_thread_suspend(thread);
465

466 467 468
    /* reset the timeout of thread timer and start it */
    rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &tick);
    rt_timer_start(&(thread->thread_timer));
469

470 471
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
472

473
    rt_schedule();
474

475 476 477
    /* clear error number of this thread to RT_EOK */
    if (thread->error == -RT_ETIMEOUT)
        thread->error = RT_EOK;
478

479
    return RT_EOK;
480 481 482 483 484 485 486
}

/**
 * This function will let current thread delay for some ticks.
 *
 * @param tick the delay ticks
 *
B
bernard.xiong@gmail.com 已提交
487
 * @return RT_EOK
488 489 490
 */
rt_err_t rt_thread_delay(rt_tick_t tick)
{
491
    return rt_thread_sleep(tick);
492
}
493
RTM_EXPORT(rt_thread_delay);
494

B
bernard.xiong@gmail.com 已提交
495 496 497 498 499
/**
 * This function will control thread behaviors according to control command.
 *
 * @param thread the specified thread to be controlled
 * @param cmd the control command, which includes
500
 *  RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread;
B
bernard.xiong@gmail.com 已提交
501 502 503 504 505 506
 *  RT_THREAD_CTRL_STARTUP for starting a thread;
 *  RT_THREAD_CTRL_CLOSE for delete a thread.
 * @param arg the argument of control command
 *
 * @return RT_EOK
 */
D
dzzxzz 已提交
507
rt_err_t rt_thread_control(rt_thread_t thread, rt_uint8_t cmd, void *arg)
508
{
509
    register rt_base_t temp;
510

511 512
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
513

514 515 516 517 518
    switch (cmd)
    {
    case RT_THREAD_CTRL_CHANGE_PRIORITY:
        /* disable interrupt */
        temp = rt_hw_interrupt_disable();
519

520 521 522 523 524
        /* for ready thread, change queue */
        if (thread->stat == RT_THREAD_READY)
        {
            /* remove thread from schedule queue first */
            rt_schedule_remove_thread(thread);
525

526 527
            /* change thread priority */
            thread->current_priority = *(rt_uint8_t *)arg;
528

529
            /* recalculate priority attribute */
530
#if RT_THREAD_PRIORITY_MAX > 32
531 532 533
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
534
#else
535
            thread->number_mask = 1 << thread->current_priority;
536 537
#endif

538 539 540 541 542 543
            /* insert thread to schedule queue again */
            rt_schedule_insert_thread(thread);
        }
        else
        {
            thread->current_priority = *(rt_uint8_t *)arg;
544

545
            /* recalculate priority attribute */
546
#if RT_THREAD_PRIORITY_MAX > 32
547 548 549
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
550
#else
551
            thread->number_mask = 1 << thread->current_priority;
552
#endif
553
        }
554

555 556 557
        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
        break;
558

559 560
    case RT_THREAD_CTRL_STARTUP:
        return rt_thread_startup(thread);
561 562

#ifdef RT_USING_HEAP
563 564
    case RT_THREAD_CTRL_CLOSE:
        return rt_thread_delete(thread);
565 566
#endif

567 568 569
    default:
        break;
    }
570

571
    return RT_EOK;
572
}
573
RTM_EXPORT(rt_thread_control);
574 575 576 577 578 579

/**
 * This function will suspend the specified thread.
 *
 * @param thread the thread to be suspended
 *
B
bernard.xiong@gmail.com 已提交
580
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
581
 *
B
bernard.xiong@gmail.com 已提交
582 583
 * @note if suspend self thread, after this function call, the
 * rt_schedule() must be invoked.
584
 */
D
dzzxzz 已提交
585
rt_err_t rt_thread_suspend(rt_thread_t thread)
586
{
587
    register rt_base_t temp;
588

589 590
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
591

592
    RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend:  %s\n", thread->name));
593

594 595 596
    if (thread->stat != RT_THREAD_READY)
    {
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, %d\n",
597
                                       thread->stat));
B
Bernard Xiong 已提交
598

599 600
        return -RT_ERROR;
    }
601

602 603
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
604

605 606 607
    /* change thread stat */
    thread->stat = RT_THREAD_SUSPEND;
    rt_schedule_remove_thread(thread);
608

609 610 611
    /* stop thread timer anyway */
    rt_timer_stop(&(thread->thread_timer));

612 613
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
614

615
    RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook,(thread));
616
    return RT_EOK;
617
}
618
RTM_EXPORT(rt_thread_suspend);
619 620 621 622 623 624

/**
 * This function will resume a thread and put it to system ready queue.
 *
 * @param thread the thread to be resumed
 *
B
bernard.xiong@gmail.com 已提交
625
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
626
 */
D
dzzxzz 已提交
627
rt_err_t rt_thread_resume(rt_thread_t thread)
628
{
629
    register rt_base_t temp;
630

631 632
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
633

634
    RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume:  %s\n", thread->name));
635

636 637 638
    if (thread->stat != RT_THREAD_SUSPEND)
    {
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
639
                                       thread->stat));
640

641 642
        return -RT_ERROR;
    }
643

644 645
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
646

647 648
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
649

650
    rt_timer_stop(&thread->thread_timer);
651

652 653
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
654

655 656
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
657

658
    RT_OBJECT_HOOK_CALL(rt_thread_resume_hook,(thread));
659
    return RT_EOK;
660
}
661
RTM_EXPORT(rt_thread_resume);
662 663

/**
B
bernard.xiong@gmail.com 已提交
664
 * This function is the timeout function for thread, normally which is invoked
665
 * when thread is timeout to wait some resource.
666 667 668
 *
 * @param parameter the parameter of thread timeout function
 */
D
dzzxzz 已提交
669
void rt_thread_timeout(void *parameter)
670
{
671
    struct rt_thread *thread;
672

673
    thread = (struct rt_thread *)parameter;
674

675 676 677
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(thread->stat == RT_THREAD_SUSPEND);
678

679 680
    /* set error number */
    thread->error = -RT_ETIMEOUT;
681

682 683
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
684

685 686
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
687

688 689
    /* do schedule */
    rt_schedule();
690
}
691
RTM_EXPORT(rt_thread_timeout);
692 693 694 695 696 697

/**
 * This function will find the specified thread.
 *
 * @param name the name of thread finding
 *
B
bernard.xiong@gmail.com 已提交
698 699 700
 * @return the found thread
 *
 * @note please don't invoke this function in interrupt status.
701
 */
D
dzzxzz 已提交
702
rt_thread_t rt_thread_find(char *name)
703
{
704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736
    struct rt_object_information *information;
    struct rt_object *object;
    struct rt_list_node *node;

    extern struct rt_object_information rt_object_container[];

    /* enter critical */
    if (rt_thread_self() != RT_NULL)
        rt_enter_critical();

    /* try to find device object */
    information = &rt_object_container[RT_Object_Class_Thread];
    for (node  = information->object_list.next;
         node != &(information->object_list);
         node  = node->next)
    {
        object = rt_list_entry(node, struct rt_object, list);
        if (rt_strncmp(object->name, name, RT_NAME_MAX) == 0)
        {
            /* leave critical */
            if (rt_thread_self() != RT_NULL)
                rt_exit_critical();

            return (rt_thread_t)object;
        }
    }

    /* leave critical */
    if (rt_thread_self() != RT_NULL)
        rt_exit_critical();

    /* not found */
    return RT_NULL;
737
}
738
RTM_EXPORT(rt_thread_find);
739 740

/*@}*/