thread.c 24.0 KB
Newer Older
1
/*
2
 * Copyright (c) 2006-2018, RT-Thread Development Team
B
Bernard Xiong 已提交
3
 *
4
 * SPDX-License-Identifier: Apache-2.0
5 6 7 8 9
 *
 * Change Logs:
 * Date           Author       Notes
 * 2006-03-28     Bernard      first version
 * 2006-04-29     Bernard      implement thread timer
10 11 12 13 14
 * 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
15
 * 2006-09-03     Bernard      implement rt_thread_detach
16
 * 2008-02-16     Bernard      fixed the rt_thread_timeout bug
17 18
 * 2010-03-21     Bernard      change the errno of rt_thread_delay/sleep to
 *                             RT_EOK.
19
 * 2010-11-10     Bernard      add cleanup callback function in thread exit.
20 21
 * 2011-09-01     Bernard      fixed rt_thread_exit issue when the current
 *                             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
S
shaojinchun 已提交
26 27 28
 *                             bug when thread has not startup.
 * 2018-11-22     Jesven       yield is same to rt_schedule
 *                             add support for tasks bound to cpu
29 30 31
 */

#include <rthw.h>
S
shaojinchun 已提交
32
#include <rtthread.h>
33 34 35

extern rt_list_t rt_thread_defunct;

36 37
#ifdef RT_USING_HOOK
static void (*rt_thread_suspend_hook)(rt_thread_t thread);
B
Bernard Xiong 已提交
38 39 40
static void (*rt_thread_resume_hook) (rt_thread_t thread);
static void (*rt_thread_inited_hook) (rt_thread_t thread);

41 42
/**
 * @ingroup Hook
43
 * This function sets a hook function when the system suspend a thread.
44 45 46 47 48 49 50 51 52
 *
 * @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;
}
B
Bernard Xiong 已提交
53

54 55
/**
 * @ingroup Hook
56
 * This function sets a hook function when the system resume a thread.
57 58 59 60 61 62 63 64 65
 *
 * @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;
}
B
Bernard Xiong 已提交
66 67 68

/**
 * @ingroup Hook
69
 * This function sets a hook function when a thread is initialized.
B
Bernard Xiong 已提交
70 71 72 73 74
 *
 * @param hook the specified hook function
 */
void rt_thread_inited_sethook(void (*hook)(rt_thread_t thread))
{
75
    rt_thread_inited_hook = hook;
B
Bernard Xiong 已提交
76 77
}

78 79
#endif

80
void rt_thread_exit(void)
81
{
82 83 84 85
    struct rt_thread *thread;
    register rt_base_t level;

    /* get current thread */
S
shaojinchun 已提交
86
    thread = rt_thread_self();
87 88 89 90 91 92 93 94 95 96

    /* 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 */
97
    rt_timer_detach(&thread->thread_timer);
98 99 100 101 102 103 104 105 106 107 108 109 110 111

    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));
    }

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

    /* enable interrupt */
    rt_hw_interrupt_enable(level);
115
}
116

D
dzzxzz 已提交
117
static rt_err_t _rt_thread_init(struct rt_thread *thread,
118 119 120 121 122 123 124
                                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)
125
{
126 127 128 129 130 131 132 133
    /* init thread list */
    rt_list_init(&(thread->tlist));

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

    /* stack init */
    thread->stack_addr = stack_start;
W
weety 已提交
134
    thread->stack_size = stack_size;
135 136 137

    /* init thread stack */
    rt_memset(thread->stack_addr, '#', thread->stack_size);
138 139 140 141 142
#ifdef ARCH_CPU_STACK_GROWS_UPWARD
    thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
                                          (void *)((char *)thread->stack_addr),
                                          (void *)rt_thread_exit);
#else
143
    thread->sp = (void *)rt_hw_stack_init(thread->entry, thread->parameter,
144
                                          (rt_uint8_t *)((char *)thread->stack_addr + thread->stack_size - sizeof(rt_ubase_t)),
145
                                          (void *)rt_thread_exit);
146
#endif
147 148 149 150 151 152

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

153 154 155
    thread->number_mask = 0;
#if RT_THREAD_PRIORITY_MAX > 32
    thread->number = 0;
B
Bernard Xiong 已提交
156
    thread->high_mask = 0;
157 158
#endif

159 160 161 162 163 164 165 166
    /* tick init */
    thread->init_tick      = tick;
    thread->remaining_tick = tick;

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

S
shaojinchun 已提交
167 168 169 170 171 172 173 174
#ifdef RT_USING_SMP
    /* not bind on any cpu */
    thread->bind_cpu = RT_CPUS_NR;
    thread->oncpu = RT_CPU_DETACHED;

    /* lock init */
    thread->scheduler_lock_nest = 0;
    thread->cpus_lock_nest = 0;
S
shaojinchun 已提交
175
    thread->critical_lock_nest = 0;
S
shaojinchun 已提交
176 177
#endif /*RT_USING_SMP*/

178 179 180 181
    /* initialize cleanup function and user data */
    thread->cleanup   = 0;
    thread->user_data = 0;

B
Bernard Xiong 已提交
182
    /* initialize thread timer */
183 184 185 186 187 188 189
    rt_timer_init(&(thread->thread_timer),
                  thread->name,
                  rt_thread_timeout,
                  thread,
                  0,
                  RT_TIMER_FLAG_ONE_SHOT);

B
bernard 已提交
190 191 192 193 194
    /* initialize signal */
#ifdef RT_USING_SIGNALS
    thread->sig_mask    = 0x00;
    thread->sig_pending = 0x00;

S
shaojinchun 已提交
195
#ifndef RT_USING_SMP
B
bernard 已提交
196
    thread->sig_ret     = RT_NULL;
S
shaojinchun 已提交
197
#endif
B
bernard 已提交
198 199 200 201
    thread->sig_vectors = RT_NULL;
    thread->si_list     = RT_NULL;
#endif

H
heyuanjie 已提交
202 203 204 205
#ifdef RT_USING_LWP
    thread->lwp = RT_NULL;
#endif

206
    RT_OBJECT_HOOK_CALL(rt_thread_inited_hook, (thread));
B
Bernard Xiong 已提交
207

208
    return RT_EOK;
209 210 211 212 213 214
}

/**
 * @addtogroup Thread
 */

D
dogandog 已提交
215
/**@{*/
216 217

/**
B
bernard.xiong@gmail.com 已提交
218 219
 * This function will initialize a thread, normally it's used to initialize a
 * static thread object.
220 221 222 223 224 225 226 227 228 229
 *
 * @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 已提交
230
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
231
 */
D
dzzxzz 已提交
232
rt_err_t rt_thread_init(struct rt_thread *thread,
233 234 235 236 237 238 239
                        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)
240
{
241 242 243 244
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(stack_start != RT_NULL);

B
Bernard Xiong 已提交
245
    /* initialize thread object */
246 247 248 249 250 251 252 253 254 255
    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);
256
}
257
RTM_EXPORT(rt_thread_init);
258 259 260 261 262 263

/**
 * This function will return self thread object
 *
 * @return the self thread object
 */
D
dzzxzz 已提交
264
rt_thread_t rt_thread_self(void)
265
{
S
shaojinchun 已提交
266 267 268 269 270 271 272 273 274 275 276
#ifdef RT_USING_SMP
    rt_base_t lock;
    rt_thread_t self;

    lock = rt_hw_local_irq_disable();
    self = rt_cpu_self()->current_thread;
    rt_hw_local_irq_enable(lock);
    return self;
#else
    extern rt_thread_t rt_current_thread;

277
    return rt_current_thread;
S
shaojinchun 已提交
278
#endif
279
}
280
RTM_EXPORT(rt_thread_self);
281 282 283 284 285 286

/**
 * 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 已提交
287
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
288
 */
D
dzzxzz 已提交
289
rt_err_t rt_thread_startup(rt_thread_t thread)
290
{
291 292
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
B
bernard 已提交
293
    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_INIT);
294
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
295

B
Bernard Xiong 已提交
296
    /* set current priority to initialize priority */
297
    thread->current_priority = thread->init_priority;
298

299
    /* calculate priority attribute */
300
#if RT_THREAD_PRIORITY_MAX > 32
301 302 303
    thread->number      = thread->current_priority >> 3;            /* 5bit */
    thread->number_mask = 1L << thread->number;
    thread->high_mask   = 1L << (thread->current_priority & 0x07);  /* 3bit */
304
#else
305
    thread->number_mask = 1L << thread->current_priority;
306 307
#endif

308
    RT_DEBUG_LOG(RT_DEBUG_THREAD, ("startup a thread:%s with priority:%d\n",
309
                                   thread->name, thread->init_priority));
310 311 312 313 314 315 316 317 318 319 320
    /* 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;
321
}
322
RTM_EXPORT(rt_thread_startup);
323 324

/**
B
bernard.xiong@gmail.com 已提交
325 326
 * This function will detach a thread. The thread object will be removed from
 * thread queue and detached/deleted from system object management.
327 328 329
 *
 * @param thread the thread to be deleted
 *
B
bernard.xiong@gmail.com 已提交
330
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
331
 */
D
dzzxzz 已提交
332
rt_err_t rt_thread_detach(rt_thread_t thread)
333
{
334
    rt_base_t lock;
335

336 337
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
338 339
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
    RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread));
340

B
bernard 已提交
341
    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
342 343 344 345
    {
        /* remove from schedule */
        rt_schedule_remove_thread(thread);
    }
346

347 348
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
349

350 351
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;
352

B
Bernard Xiong 已提交
353 354 355 356 357 358
    if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
        thread->cleanup == RT_NULL)
    {
        rt_object_detach((rt_object_t)thread);
    }
    else
359 360 361 362 363 364 365 366
    {
        /* disable interrupt */
        lock = rt_hw_interrupt_disable();
        /* insert to defunct thread list */
        rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
        /* enable interrupt */
        rt_hw_interrupt_enable(lock);
    }
367

368
    return RT_EOK;
369
}
370 371
RTM_EXPORT(rt_thread_detach);

372
#ifdef RT_USING_HEAP
373 374 375 376 377 378 379 380 381 382 383 384 385 386
/**
 * 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,
387 388 389 390 391
                             void (*entry)(void *parameter),
                             void       *parameter,
                             rt_uint32_t stack_size,
                             rt_uint8_t  priority,
                             rt_uint32_t tick)
392
{
393 394 395 396 397 398 399 400
    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 已提交
401
    stack_start = (void *)RT_KERNEL_MALLOC(stack_size);
402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419
    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;
420
}
421
RTM_EXPORT(rt_thread_create);
422

423
/**
B
bernard.xiong@gmail.com 已提交
424
 * This function will delete a thread. The thread object will be removed from
425
 * thread queue and deleted from system object management in the idle thread.
426 427 428
 *
 * @param thread the thread to be deleted
 *
B
bernard.xiong@gmail.com 已提交
429
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
430
 */
D
dzzxzz 已提交
431
rt_err_t rt_thread_delete(rt_thread_t thread)
432
{
433
    rt_base_t lock;
434

435 436
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
437 438
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
    RT_ASSERT(rt_object_is_systemobject((rt_object_t)thread) == RT_FALSE);
439

B
bernard 已提交
440
    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
441 442 443 444
    {
        /* remove from schedule */
        rt_schedule_remove_thread(thread);
    }
445

446 447
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
448

449 450
    /* disable interrupt */
    lock = rt_hw_interrupt_disable();
451

452 453 454
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;

455 456
    /* insert to defunct thread list */
    rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
457

458 459
    /* enable interrupt */
    rt_hw_interrupt_enable(lock);
460

461
    return RT_EOK;
462
}
463
RTM_EXPORT(rt_thread_delete);
464 465 466
#endif

/**
B
bernard.xiong@gmail.com 已提交
467 468 469
 * 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.
470
 *
B
bernard.xiong@gmail.com 已提交
471
 * @return RT_EOK
472
 */
D
dzzxzz 已提交
473
rt_err_t rt_thread_yield(void)
474
{
S
shaojinchun 已提交
475
    rt_schedule();
476

477
    return RT_EOK;
478
}
479
RTM_EXPORT(rt_thread_yield);
480 481 482 483 484 485

/**
 * This function will let current thread sleep for some ticks.
 *
 * @param tick the sleep ticks
 *
B
bernard.xiong@gmail.com 已提交
486
 * @return RT_EOK
487
 */
D
dzzxzz 已提交
488
rt_err_t rt_thread_sleep(rt_tick_t tick)
489
{
490 491
    register rt_base_t temp;
    struct rt_thread *thread;
492

493
    /* set to current thread */
S
shaojinchun 已提交
494
    thread = rt_thread_self();
495
    RT_ASSERT(thread != RT_NULL);
496
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
497

S
shaojinchun 已提交
498 499 500
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();

501 502
    /* suspend thread */
    rt_thread_suspend(thread);
503

504 505 506
    /* 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));
507

508 509
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
510

511
    rt_schedule();
512

513 514 515
    /* clear error number of this thread to RT_EOK */
    if (thread->error == -RT_ETIMEOUT)
        thread->error = RT_EOK;
516

517
    return RT_EOK;
518 519 520 521 522 523 524
}

/**
 * This function will let current thread delay for some ticks.
 *
 * @param tick the delay ticks
 *
B
bernard.xiong@gmail.com 已提交
525
 * @return RT_EOK
526 527 528
 */
rt_err_t rt_thread_delay(rt_tick_t tick)
{
529
    return rt_thread_sleep(tick);
530
}
531
RTM_EXPORT(rt_thread_delay);
532

533 534 535 536 537 538 539 540 541 542 543 544 545
/**
 * This function will let current thread delay util (*tick + inc_tick).
 *
 * @param tick the tick of last wakeup.
 * @param inc_tick the increment tick
 *
 * @return RT_EOK
 */
rt_err_t rt_thread_delay_util(rt_tick_t *tick, rt_tick_t inc_tick)
{
    register rt_base_t level;
    struct rt_thread *thread;

B
Bernard Xiong 已提交
546 547
    RT_ASSERT(tick != RT_NULL);

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582
    /* set to current thread */
    thread = rt_thread_self();
    RT_ASSERT(thread != RT_NULL);
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);

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

    if (rt_tick_get() - *tick < inc_tick)
    {
        *tick = rt_tick_get() - *tick + inc_tick;

        /* suspend thread */
        rt_thread_suspend(thread);

        /* 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));

        /* enable interrupt */
        rt_hw_interrupt_enable(level);

        rt_schedule();

        /* clear error number of this thread to RT_EOK */
        if (thread->error == -RT_ETIMEOUT)
        {
            thread->error = RT_EOK;
        }
    }
    else
    {
        rt_hw_interrupt_enable(level);
    }

B
Bernard Xiong 已提交
583 584 585
    /* get the wakeup tick */
    *tick = rt_tick_get();

586 587 588 589
    return RT_EOK;
}
RTM_EXPORT(rt_thread_delay_util);

H
heyuanjie 已提交
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606
/**
 * This function will let current thread delay for some milliseconds.
 *
 * @param tick the delay time
 *
 * @return RT_EOK
 */
rt_err_t rt_thread_mdelay(rt_int32_t ms)
{
    rt_tick_t tick;

    tick = rt_tick_from_millisecond(ms);

    return rt_thread_sleep(tick);
}
RTM_EXPORT(rt_thread_mdelay);

B
bernard.xiong@gmail.com 已提交
607 608 609 610 611
/**
 * 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
612
 *  RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread;
B
bernard.xiong@gmail.com 已提交
613
 *  RT_THREAD_CTRL_STARTUP for starting a thread;
S
shaojinchun 已提交
614 615
 *  RT_THREAD_CTRL_CLOSE for delete a thread;
 *  RT_THREAD_CTRL_BIND_CPU for bind the thread to a CPU.
B
bernard.xiong@gmail.com 已提交
616 617 618 619
 * @param arg the argument of control command
 *
 * @return RT_EOK
 */
B
bernard 已提交
620
rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
621
{
622
    register rt_base_t temp;
623

624 625
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
626
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
627

628 629 630 631 632
    switch (cmd)
    {
    case RT_THREAD_CTRL_CHANGE_PRIORITY:
        /* disable interrupt */
        temp = rt_hw_interrupt_disable();
633

634
        /* for ready thread, change queue */
B
bernard 已提交
635
        if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
636 637 638
        {
            /* remove thread from schedule queue first */
            rt_schedule_remove_thread(thread);
639

640 641
            /* change thread priority */
            thread->current_priority = *(rt_uint8_t *)arg;
642

643
            /* recalculate priority attribute */
644
#if RT_THREAD_PRIORITY_MAX > 32
645 646 647
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
648
#else
649
            thread->number_mask = 1 << thread->current_priority;
650 651
#endif

652 653 654 655 656 657
            /* insert thread to schedule queue again */
            rt_schedule_insert_thread(thread);
        }
        else
        {
            thread->current_priority = *(rt_uint8_t *)arg;
658

659
            /* recalculate priority attribute */
660
#if RT_THREAD_PRIORITY_MAX > 32
661 662 663
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
664
#else
665
            thread->number_mask = 1 << thread->current_priority;
666
#endif
667
        }
668

669 670 671
        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
        break;
672

673 674
    case RT_THREAD_CTRL_STARTUP:
        return rt_thread_startup(thread);
675 676

#ifdef RT_USING_HEAP
677 678
    case RT_THREAD_CTRL_CLOSE:
        return rt_thread_delete(thread);
679 680
#endif

S
shaojinchun 已提交
681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696
#ifdef RT_USING_SMP
    case RT_THREAD_CTRL_BIND_CPU:
    {
        rt_uint8_t cpu;

        if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
        {
            /* we only support bind cpu before started phase. */
            return RT_ERROR;
        }

        cpu = (rt_uint8_t)(size_t)arg;
        thread->bind_cpu = cpu > RT_CPUS_NR? RT_CPUS_NR : cpu;
        break;
    }
#endif /*RT_USING_SMP*/
697 698 699
    default:
        break;
    }
700

701
    return RT_EOK;
702
}
703
RTM_EXPORT(rt_thread_control);
704 705 706 707 708 709

/**
 * This function will suspend the specified thread.
 *
 * @param thread the thread to be suspended
 *
B
bernard.xiong@gmail.com 已提交
710
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
711
 *
B
bernard.xiong@gmail.com 已提交
712 713
 * @note if suspend self thread, after this function call, the
 * rt_schedule() must be invoked.
714
 */
D
dzzxzz 已提交
715
rt_err_t rt_thread_suspend(rt_thread_t thread)
716
{
717
    register rt_base_t stat;
718
    register rt_base_t temp;
719

720 721
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
722
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
723

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

726 727
    stat = thread->stat & RT_THREAD_STAT_MASK;
    if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING))
728
    {
729
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
730
                                       thread->stat));
731 732
        return -RT_ERROR;
    }
733

734 735
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
736 737 738 739 740
    if (stat == RT_THREAD_RUNNING)
    {
        /* not suspend running status thread on other core */
        RT_ASSERT(thread == rt_thread_self());
    }
741

742 743
    /* change thread stat */
    rt_schedule_remove_thread(thread);
744
    thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
745

746 747 748
    /* stop thread timer anyway */
    rt_timer_stop(&(thread->thread_timer));

749 750
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
751

752
    RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
753
    return RT_EOK;
754
}
755
RTM_EXPORT(rt_thread_suspend);
756 757 758 759 760 761

/**
 * 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 已提交
762
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
763
 */
D
dzzxzz 已提交
764
rt_err_t rt_thread_resume(rt_thread_t thread)
765
{
766
    register rt_base_t temp;
767

768 769
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
770
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
771

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

B
bernard 已提交
774
    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
775 776
    {
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
777
                                       thread->stat));
778

779 780
        return -RT_ERROR;
    }
781

782 783
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
784

785 786
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
787

788
    rt_timer_stop(&thread->thread_timer);
789

790 791
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
792

793 794
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
795

796
    RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread));
797
    return RT_EOK;
798
}
799
RTM_EXPORT(rt_thread_resume);
800 801

/**
B
bernard.xiong@gmail.com 已提交
802
 * This function is the timeout function for thread, normally which is invoked
803
 * when thread is timeout to wait some resource.
804 805 806
 *
 * @param parameter the parameter of thread timeout function
 */
D
dzzxzz 已提交
807
void rt_thread_timeout(void *parameter)
808
{
809
    struct rt_thread *thread;
810

811
    thread = (struct rt_thread *)parameter;
812

813 814
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
B
bernard 已提交
815
    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
816
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
817

818 819
    /* set error number */
    thread->error = -RT_ETIMEOUT;
820

821 822
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
823

824 825
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
826

827 828
    /* do schedule */
    rt_schedule();
829
}
830
RTM_EXPORT(rt_thread_timeout);
831 832 833 834 835 836

/**
 * This function will find the specified thread.
 *
 * @param name the name of thread finding
 *
B
bernard.xiong@gmail.com 已提交
837 838 839
 * @return the found thread
 *
 * @note please don't invoke this function in interrupt status.
840
 */
D
dzzxzz 已提交
841
rt_thread_t rt_thread_find(char *name)
842
{
843 844 845 846 847 848 849 850 851
    struct rt_object_information *information;
    struct rt_object *object;
    struct rt_list_node *node;

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

    /* try to find device object */
852 853
    information = rt_object_get_information(RT_Object_Class_Thread);
    RT_ASSERT(information != RT_NULL);
854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874
    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;
875
}
876
RTM_EXPORT(rt_thread_find);
877

D
dogandog 已提交
878
/**@}*/