thread.c 24.1 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

C
cliff-cmc 已提交
341
    if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
342 343
        return RT_EOK;

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

350 351
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
352

353 354
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;
355

B
Bernard Xiong 已提交
356 357 358 359 360 361
    if ((rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE) &&
        thread->cleanup == RT_NULL)
    {
        rt_object_detach((rt_object_t)thread);
    }
    else
362 363 364 365 366 367 368 369
    {
        /* 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);
    }
370

371
    return RT_EOK;
372
}
373 374
RTM_EXPORT(rt_thread_detach);

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

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

438 439
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
440 441
    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);
442

C
cliff-cmc 已提交
443
    if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_CLOSE)
444 445
        return RT_EOK;

B
bernard 已提交
446
    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_INIT)
447 448 449 450
    {
        /* remove from schedule */
        rt_schedule_remove_thread(thread);
    }
451

452 453
    /* release thread timer */
    rt_timer_detach(&(thread->thread_timer));
454

455 456
    /* disable interrupt */
    lock = rt_hw_interrupt_disable();
457

458 459 460
    /* change stat */
    thread->stat = RT_THREAD_CLOSE;

461 462
    /* insert to defunct thread list */
    rt_list_insert_after(&rt_thread_defunct, &(thread->tlist));
463

464 465
    /* enable interrupt */
    rt_hw_interrupt_enable(lock);
466

467
    return RT_EOK;
468
}
469
RTM_EXPORT(rt_thread_delete);
470 471 472
#endif

/**
B
bernard.xiong@gmail.com 已提交
473 474 475
 * 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.
476
 *
B
bernard.xiong@gmail.com 已提交
477
 * @return RT_EOK
478
 */
D
dzzxzz 已提交
479
rt_err_t rt_thread_yield(void)
480
{
S
shaojinchun 已提交
481
    rt_schedule();
482

483
    return RT_EOK;
484
}
485
RTM_EXPORT(rt_thread_yield);
486 487 488 489 490 491

/**
 * This function will let current thread sleep for some ticks.
 *
 * @param tick the sleep ticks
 *
B
bernard.xiong@gmail.com 已提交
492
 * @return RT_EOK
493
 */
D
dzzxzz 已提交
494
rt_err_t rt_thread_sleep(rt_tick_t tick)
495
{
496 497
    register rt_base_t temp;
    struct rt_thread *thread;
498

499
    /* set to current thread */
S
shaojinchun 已提交
500
    thread = rt_thread_self();
501
    RT_ASSERT(thread != RT_NULL);
502
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
503

S
shaojinchun 已提交
504 505 506
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();

507 508
    /* suspend thread */
    rt_thread_suspend(thread);
509

510 511 512
    /* 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));
513

514 515
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
516

517
    rt_schedule();
518

519 520 521
    /* clear error number of this thread to RT_EOK */
    if (thread->error == -RT_ETIMEOUT)
        thread->error = RT_EOK;
522

523
    return RT_EOK;
524 525 526 527 528 529 530
}

/**
 * This function will let current thread delay for some ticks.
 *
 * @param tick the delay ticks
 *
B
bernard.xiong@gmail.com 已提交
531
 * @return RT_EOK
532 533 534
 */
rt_err_t rt_thread_delay(rt_tick_t tick)
{
535
    return rt_thread_sleep(tick);
536
}
537
RTM_EXPORT(rt_thread_delay);
538

539
/**
B
Bernard Xiong 已提交
540
 * This function will let current thread delay until (*tick + inc_tick).
541 542 543 544 545 546
 *
 * @param tick the tick of last wakeup.
 * @param inc_tick the increment tick
 *
 * @return RT_EOK
 */
B
Bernard Xiong 已提交
547
rt_err_t rt_thread_delay_until(rt_tick_t *tick, rt_tick_t inc_tick)
548 549 550 551
{
    register rt_base_t level;
    struct rt_thread *thread;

B
Bernard Xiong 已提交
552 553
    RT_ASSERT(tick != RT_NULL);

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 583 584 585 586 587 588
    /* 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 已提交
589 590 591
    /* get the wakeup tick */
    *tick = rt_tick_get();

592 593
    return RT_EOK;
}
594
RTM_EXPORT(rt_thread_delay_until);
595

H
heyuanjie 已提交
596 597 598
/**
 * This function will let current thread delay for some milliseconds.
 *
S
suhui 已提交
599
 * @param ms the delay ms time
H
heyuanjie 已提交
600 601 602 603 604 605 606 607 608 609 610 611 612
 *
 * @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 已提交
613 614 615 616 617
/**
 * 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
618
 *  RT_THREAD_CTRL_CHANGE_PRIORITY for changing priority level of thread;
B
bernard.xiong@gmail.com 已提交
619
 *  RT_THREAD_CTRL_STARTUP for starting a thread;
S
shaojinchun 已提交
620 621
 *  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 已提交
622 623 624 625
 * @param arg the argument of control command
 *
 * @return RT_EOK
 */
B
bernard 已提交
626
rt_err_t rt_thread_control(rt_thread_t thread, int cmd, void *arg)
627
{
628
    register rt_base_t temp;
629

630 631
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
632
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
633

634 635 636 637 638
    switch (cmd)
    {
    case RT_THREAD_CTRL_CHANGE_PRIORITY:
        /* disable interrupt */
        temp = rt_hw_interrupt_disable();
639

640
        /* for ready thread, change queue */
B
bernard 已提交
641
        if ((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_READY)
642 643 644
        {
            /* remove thread from schedule queue first */
            rt_schedule_remove_thread(thread);
645

646 647
            /* change thread priority */
            thread->current_priority = *(rt_uint8_t *)arg;
648

649
            /* recalculate priority attribute */
650
#if RT_THREAD_PRIORITY_MAX > 32
651 652 653
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
654
#else
655
            thread->number_mask = 1 << thread->current_priority;
656 657
#endif

658 659 660 661 662 663
            /* insert thread to schedule queue again */
            rt_schedule_insert_thread(thread);
        }
        else
        {
            thread->current_priority = *(rt_uint8_t *)arg;
664

665
            /* recalculate priority attribute */
666
#if RT_THREAD_PRIORITY_MAX > 32
667 668 669
            thread->number      = thread->current_priority >> 3;            /* 5bit */
            thread->number_mask = 1 << thread->number;
            thread->high_mask   = 1 << (thread->current_priority & 0x07);   /* 3bit */
670
#else
671
            thread->number_mask = 1 << thread->current_priority;
672
#endif
673
        }
674

675 676 677
        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
        break;
678

679 680
    case RT_THREAD_CTRL_STARTUP:
        return rt_thread_startup(thread);
681 682

#ifdef RT_USING_HEAP
683 684
    case RT_THREAD_CTRL_CLOSE:
        return rt_thread_delete(thread);
685 686
#endif

S
shaojinchun 已提交
687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702
#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*/
703 704 705
    default:
        break;
    }
706

707
    return RT_EOK;
708
}
709
RTM_EXPORT(rt_thread_control);
710 711 712 713 714 715

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

726 727
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
728
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
729

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

732 733
    stat = thread->stat & RT_THREAD_STAT_MASK;
    if ((stat != RT_THREAD_READY) && (stat != RT_THREAD_RUNNING))
734
    {
735
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread suspend: thread disorder, 0x%2x\n",
736
                                       thread->stat));
737 738
        return -RT_ERROR;
    }
739

740 741
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
742 743 744 745 746
    if (stat == RT_THREAD_RUNNING)
    {
        /* not suspend running status thread on other core */
        RT_ASSERT(thread == rt_thread_self());
    }
747

748 749
    /* change thread stat */
    rt_schedule_remove_thread(thread);
750
    thread->stat = RT_THREAD_SUSPEND | (thread->stat & ~RT_THREAD_STAT_MASK);
751

752 753 754
    /* stop thread timer anyway */
    rt_timer_stop(&(thread->thread_timer));

755 756
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
757

758
    RT_OBJECT_HOOK_CALL(rt_thread_suspend_hook, (thread));
759
    return RT_EOK;
760
}
761
RTM_EXPORT(rt_thread_suspend);
762 763 764 765 766 767

/**
 * 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 已提交
768
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
769
 */
D
dzzxzz 已提交
770
rt_err_t rt_thread_resume(rt_thread_t thread)
771
{
772
    register rt_base_t temp;
773

774 775
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
776
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
777

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

B
bernard 已提交
780
    if ((thread->stat & RT_THREAD_STAT_MASK) != RT_THREAD_SUSPEND)
781 782
    {
        RT_DEBUG_LOG(RT_DEBUG_THREAD, ("thread resume: thread disorder, %d\n",
783
                                       thread->stat));
784

785 786
        return -RT_ERROR;
    }
787

788 789
    /* disable interrupt */
    temp = rt_hw_interrupt_disable();
790

791 792
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
793

794
    rt_timer_stop(&thread->thread_timer);
795

796 797
    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
798

799 800
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
801

802
    RT_OBJECT_HOOK_CALL(rt_thread_resume_hook, (thread));
803
    return RT_EOK;
804
}
805
RTM_EXPORT(rt_thread_resume);
806 807

/**
B
bernard.xiong@gmail.com 已提交
808
 * This function is the timeout function for thread, normally which is invoked
809
 * when thread is timeout to wait some resource.
810 811 812
 *
 * @param parameter the parameter of thread timeout function
 */
D
dzzxzz 已提交
813
void rt_thread_timeout(void *parameter)
814
{
815
    struct rt_thread *thread;
816

817
    thread = (struct rt_thread *)parameter;
818

819 820
    /* thread check */
    RT_ASSERT(thread != RT_NULL);
B
bernard 已提交
821
    RT_ASSERT((thread->stat & RT_THREAD_STAT_MASK) == RT_THREAD_SUSPEND);
822
    RT_ASSERT(rt_object_get_type((rt_object_t)thread) == RT_Object_Class_Thread);
823

824 825
    /* set error number */
    thread->error = -RT_ETIMEOUT;
826

827 828
    /* remove from suspend list */
    rt_list_remove(&(thread->tlist));
829

830 831
    /* insert to schedule ready list */
    rt_schedule_insert_thread(thread);
832

833 834
    /* do schedule */
    rt_schedule();
835
}
836
RTM_EXPORT(rt_thread_timeout);
837 838 839 840 841 842

/**
 * This function will find the specified thread.
 *
 * @param name the name of thread finding
 *
B
bernard.xiong@gmail.com 已提交
843 844 845
 * @return the found thread
 *
 * @note please don't invoke this function in interrupt status.
846
 */
D
dzzxzz 已提交
847
rt_thread_t rt_thread_find(char *name)
848
{
849 850 851 852 853 854 855 856 857
    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 */
858 859
    information = rt_object_get_information(RT_Object_Class_Thread);
    RT_ASSERT(information != RT_NULL);
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880
    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;
881
}
882
RTM_EXPORT(rt_thread_find);
883

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