Пример #1
0
/**
 * This function will resume all suspended threads in an IPC object.
 *
 * @param ipc the IPC object
 *
 * @return the operation status, RT_EOK on successful
 */
rt_inline rt_err_t rt_ipc_object_resume_all(struct rt_ipc_object* ipc)
{
	struct rt_thread* thread;
	register rt_ubase_t temp;

	/* wakeup all suspend threads */
	while (!rt_list_isempty(&(ipc->suspend_thread)))
	{
		/* disable interrupt */
		temp = rt_hw_interrupt_disable();

		/* get next suspend thread */
		thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);
		/* set error code to RT_ERROR */
		thread->error = -RT_ERROR;

		/*
		 * resume thread
		 * In rt_thread_resume function, it will remove current thread from
		 * suspend list
		 */
		rt_thread_resume(thread);

		/* decrease suspended thread count */
		ipc->suspend_thread_count --;

		/* enable interrupt */
		rt_hw_interrupt_enable(temp);
	}

	return RT_EOK;
}
Пример #2
0
/**
 * This function will start a thread and put it to system ready queue
 *
 * @param thread the thread to be started
 *
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
 *
 */
rt_err_t rt_thread_startup(rt_thread_t thread)
{
	/* thread check */
	RT_ASSERT(thread != RT_NULL);
	RT_ASSERT(thread->stat == RT_THREAD_INIT);

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

	/* calculate priority attribute */
#if RT_THREAD_PRIORITY_MAX > 32
	thread->number      = thread->current_priority >> 3; 			/* 5bit */
	thread->number_mask = 1L << thread->number;
	thread->high_mask   = 1L << (thread->current_priority & 0x07); 	/* 3bit */
#else
	thread->number_mask = 1L << thread->current_priority;
#endif

	RT_DEBUG_LOG(RT_DEBUG_THREAD,\
		("startup a thread:%s with priority:%d\n", thread->name, thread->init_priority));
	/* 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;
}
Пример #3
0
void rt_completion_done(struct rt_completion *completion)
{
    rt_base_t level;
    RT_ASSERT(completion != RT_NULL);

    if(completion->flag == RT_COMPLETED) return;

    level = rt_hw_interrupt_disable();
    completion->flag = RT_COMPLETED;

    if (!rt_list_isempty(&(completion->suspended_list)))
    {
        /* there is one thread in suspended list */
        struct rt_thread *thread;

        /* get thread entry */
        thread = rt_list_entry(completion->suspended_list.next, struct rt_thread, tlist);

        /* resume it */
        rt_thread_resume(thread);
        rt_hw_interrupt_enable(level);

        /* perform a schedule */
        rt_schedule();
    }
    else
    {
Пример #4
0
static void _signal_deliver(rt_thread_t tid)
{
    rt_ubase_t level;

    /* thread is not interested in pended signals */
    if (!(tid->sig_pending & tid->sig_mask)) return;

    level = rt_hw_interrupt_disable();
    if (tid->stat == RT_THREAD_SUSPEND)
    {
        /* resume thread to handle signal */
        rt_thread_resume(tid);
		/* add signal state */
		tid->stat |= RT_THREAD_STAT_SIGNAL;

        rt_hw_interrupt_enable(level);

        /* re-schedule */
        rt_schedule();
    }
    else
    {
        if (tid == rt_thread_self())
        {
			/* add signal state */
			tid->stat |= RT_THREAD_STAT_SIGNAL;
            rt_hw_interrupt_enable(level);

            /* do signal action in self thread context */
            rt_thread_handle_sig(RT_TRUE);
        }
        else if (!(tid->stat & RT_THREAD_STAT_SIGNAL))
        {
            tid->stat |= RT_THREAD_STAT_SIGNAL;
            /* point to the signal handle entry */
            tid->sig_ret = tid->sp;
            tid->sp = rt_hw_stack_init((void*)_signal_entry, RT_NULL, 
                (void *)((char *)tid->sig_ret - 32), RT_NULL);

            rt_hw_interrupt_enable(level);
            dbg_log(DBG_LOG, "signal stack pointer @ 0x%08x\n", tid->sp);

            /* re-schedule */
            rt_schedule();
        }
        else
        {
            rt_hw_interrupt_enable(level);
        }
    }
}
Пример #5
0
/**
 * This function will delete a memory pool and release the object memory.
 *
 * @param mp the memory pool object
 *
 * @return RT_EOK
 */
rt_err_t rt_mp_delete(rt_mp_t mp)
{
	struct rt_thread *thread;
	register rt_ubase_t temp;

	RT_DEBUG_NOT_IN_INTERRUPT;

	/* parameter check */
	RT_ASSERT(mp != RT_NULL);

	/* wake up all suspended threads */
	while (!rt_list_isempty(&(mp->suspend_thread)))
	{
		/* disable interrupt */
		temp = rt_hw_interrupt_disable();

		/* get next suspend thread */
		thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
		/* set error code to RT_ERROR */
		thread->error = -RT_ERROR;

		/*
		 * resume thread
		 * In rt_thread_resume function, it will remove current thread from suspend
		 * list
		 */
		rt_thread_resume(thread);

		/* decrease suspended thread count */
		mp->suspend_thread_count --;

		/* enable interrupt */
		rt_hw_interrupt_enable(temp);
	}

#if defined(RT_USING_MODULE) && defined(RT_USING_SLAB)
	/* the mp object belongs to an application module */
	if (mp->parent.flag & RT_OBJECT_FLAG_MODULE) 
		rt_module_free(mp->parent.module_id, mp->start_address);
	else
#endif

	/* release allocated room */
	rt_free(mp->start_address);

	/* detach object */
	rt_object_delete(&(mp->parent));

	return RT_EOK;
}
Пример #6
0
/**
 * This function will resume the first thread in the list of a IPC object:
 * - remove the thread from suspend queue of IPC object
 * - put the thread into system ready queue
 *
 * @param list the thread list
 *
 * @return the operation status, RT_EOK on successful
 */
rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list)
{
	struct rt_thread *thread;

	/* get thread entry */
	thread = rt_list_entry(list->next, struct rt_thread, tlist);

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

	/* resume it */
	rt_thread_resume(thread);

	return RT_EOK;
}
/* 线程2入口 */
static void thread2_entry(void* parameter)
{
    /* 延时10个OS Tick */
    rt_thread_delay(10);

    /* 唤醒线程1 */
    rt_thread_resume(tid1);
    rt_kprintf("thread2: to resume thread1\n");

    /* 延时10个OS Tick */
    rt_thread_delay(10);

    /* 线程2自动退出 */
}
Пример #8
0
/**
 * This function will release a memory block
 *
 * @param block the address of memory block to be released
 *
 */
void rt_mp_free  (void *block)
{
	rt_uint8_t **block_ptr;
	struct rt_mempool *mp;
	struct rt_thread *thread;
	register rt_base_t level;

	/* get the control block of pool which the block belongs to */
	block_ptr = (rt_uint8_t**)((rt_uint8_t*)block - sizeof(rt_uint8_t*));
	mp = (struct rt_mempool*) *block_ptr;

#ifdef RT_USING_HOOK
	if (rt_mp_free_hook != RT_NULL) rt_mp_free_hook(mp, block);
#endif

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

	/* increase the free block count */
	mp->block_free_count ++;

	/* link the block into the block list */
	*block_ptr = mp->block_list;
	mp->block_list = (rt_uint8_t*)block_ptr;

	if (mp->suspend_thread_count > 0)
	{
		/* get the suspended thread */
		thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);

		/* set error */
		thread->error = RT_EOK;

		/* resume thread */
		rt_thread_resume(thread);

		/* decrease suspended thread count */
		mp->suspend_thread_count --;

		/* enable interrupt */
		rt_hw_interrupt_enable(level);

		/* do a schedule */
		rt_schedule();

		return;
	}
Пример #9
0
static void _rt_pipe_resume_writer(struct rt_audio_pipe *pipe)
{
    if (!rt_list_isempty(&pipe->suspended_write_list))
    {
        rt_thread_t thread;

        RT_ASSERT(pipe->flag & RT_PIPE_FLAG_BLOCK_WR);

        /* get suspended thread */
        thread = rt_list_entry(pipe->suspended_write_list.next,
                struct rt_thread,
                tlist);

        /* resume the write thread */
        rt_thread_resume(thread);

        rt_schedule();
    }
Пример #10
0
/**
 * This function will resume a thread from an IPC object:
 * - remove the thread from suspend queue of IPC object
 * - put the thread into system ready queue
 *
 * @param ipc the IPC object
 *
 * @return the operation status, RT_EOK on successful
 */
rt_inline rt_err_t rt_ipc_object_resume(struct rt_ipc_object* ipc)
{
	struct rt_thread *thread;

	/* get thread entry */
	thread = rt_list_entry(ipc->suspend_thread.next, struct rt_thread, tlist);

#ifdef RT_IPC_DEBUG
	rt_kprintf("resume thread:%s\n", thread->name);
#endif

	/* resume it */
	rt_thread_resume(thread);

	/* decrease suspended thread count */
	ipc->suspend_thread_count --;

	return RT_EOK;
}
Пример #11
0
/**
 * This function will delete a memory pool and release the object memory.
 *
 * @param mp the memory pool object
 *
 * @return the operation status, RT_EOK on OK; -RT_ERROR on error
 *
 */
rt_err_t rt_mp_delete(rt_mp_t mp)
{
	struct rt_thread* thread;
	register rt_ubase_t temp;

	/* parameter check */
	RT_ASSERT(mp != RT_NULL);

	/* wakeup all suspended threads */
	while (!rt_list_isempty(&(mp->suspend_thread)))
	{
		/* disable interrupt */
		temp = rt_hw_interrupt_disable();

		/* get next suspend thread */
		thread = rt_list_entry(mp->suspend_thread.next, struct rt_thread, tlist);
		/* set error code to RT_ERROR */
		thread->error = -RT_ERROR;

		/*
		 * resume thread
		 * In rt_thread_resume function, it will remove current thread from suspend
		 * list
		 */
		rt_thread_resume(thread);

		/* decrease suspended thread count */
		mp->suspend_thread_count --;

		/* enable interrupt */
		rt_hw_interrupt_enable(temp);
	}

	/* release allocated room */
	rt_free(mp->start_address);

	/* detach object */
	rt_object_delete(&(mp->parent));

	return RT_EOK;
}
Пример #12
0
rt_err_t rt_prio_queue_push(struct rt_prio_queue *que,
                            rt_uint8_t prio,
                            void *data,
                            rt_int32_t timeout)
{
    rt_ubase_t level;
    struct rt_prio_queue_item *item;

    RT_ASSERT(que);

    if (prio >= RT_PRIO_QUEUE_PRIO_MAX)
        return -RT_ERROR;

    item = rt_mp_alloc(&que->pool, timeout);
    if (item == RT_NULL)
        return -RT_ENOMEM;

    rt_memcpy(item+1, data, que->item_sz);
    item->next = RT_NULL;

    level = rt_hw_interrupt_disable();

    _do_push(que, prio, item);

    if (!rt_list_isempty(&(que->suspended_pop_list)))
    {
        rt_thread_t thread;

        /* get thread entry */
        thread = rt_list_entry(que->suspended_pop_list.next,
                               struct rt_thread,
                               tlist);
        /* resume it */
        rt_thread_resume(thread);
        rt_hw_interrupt_enable(level);

        /* perform a schedule */
        rt_schedule();

        return RT_EOK;
    }
Пример #13
0
void rt_prio_queue_detach(struct rt_prio_queue *que)
{
    /* wake up all suspended pop threads, push thread is suspended on mempool.
     */
    while (!rt_list_isempty(&(que->suspended_pop_list)))
    {
        rt_thread_t thread;

        /* disable interrupt */
        rt_ubase_t temp = rt_hw_interrupt_disable();

        /* get next suspend thread */
        thread = rt_list_entry(que->suspended_pop_list.next, struct rt_thread, tlist);
        /* set error code to RT_ERROR */
        thread->error = -RT_ERROR;

        rt_thread_resume(thread);

        /* enable interrupt */
        rt_hw_interrupt_enable(temp);
    }
    rt_mp_detach(&que->pool);
}
rt_err_t rt_data_queue_push(struct rt_data_queue *queue,
                            const void *data_ptr,
                            rt_size_t data_size,
                            rt_int32_t timeout)
{
    rt_uint16_t mask;
    rt_ubase_t  level;
    rt_thread_t thread;
    rt_err_t    result;

    RT_ASSERT(queue != RT_NULL);

    result = RT_EOK;
    thread = rt_thread_self();
    mask = queue->size - 1;

    level = rt_hw_interrupt_disable();
    while (queue->put_index - queue->get_index == queue->size)
    {
        queue->waiting_lwm = RT_TRUE;

        /* queue is full */
        if (timeout == 0)
        {
            result = -RT_ETIMEOUT;

            goto __exit;
        }

        /* current context checking */
        RT_DEBUG_NOT_IN_INTERRUPT;

        /* reset thread error number */
        thread->error = RT_EOK;

        /* suspend thread on the push list */
        rt_thread_suspend(thread);
        rt_list_insert_before(&(queue->suspended_push_list), &(thread->tlist));
        /* start timer */
        if (timeout > 0)
        {
            /* reset the timeout of thread timer and start it */
            rt_timer_control(&(thread->thread_timer),
                             RT_TIMER_CTRL_SET_TIME,
                             &timeout);
            rt_timer_start(&(thread->thread_timer));
        }

        /* enable interrupt */
        rt_hw_interrupt_enable(level);

        /* do schedule */
        rt_schedule();

        /* thread is waked up */
        result = thread->error;
        level = rt_hw_interrupt_disable();
        if (result != RT_EOK) goto __exit;
    }

    queue->queue[queue->put_index & mask].data_ptr  = data_ptr;
    queue->queue[queue->put_index & mask].data_size = data_size;
    queue->put_index += 1;

    if (!rt_list_isempty(&(queue->suspended_pop_list)))
    {
        /* there is at least one thread in suspended list */

        /* get thread entry */
        thread = rt_list_entry(queue->suspended_pop_list.next,
                               struct rt_thread,
                               tlist);

        /* resume it */
        rt_thread_resume(thread);
        rt_hw_interrupt_enable(level);

        /* perform a schedule */
        rt_schedule();

        return result;
    }
Пример #15
0
/**
 * This function will start the timer
 *
 * @param timer the timer to be started
 *
 * @return the operation status, RT_EOK on OK, -RT_ERROR on error
 */
rt_err_t rt_timer_start(rt_timer_t timer)
{
    int row_lvl;
    rt_list_t *timer_list;
    register rt_base_t level;
    rt_list_t *row_head[RT_TIMER_SKIP_LIST_LEVEL];
    unsigned int tst_nr;
    static unsigned int random_nr;

    /* timer check */
    RT_ASSERT(timer != RT_NULL);
    if (timer->parent.flag & RT_TIMER_FLAG_ACTIVATED)
        return -RT_ERROR;

    RT_OBJECT_HOOK_CALL(rt_object_take_hook, (&(timer->parent)));

    /*
     * get timeout tick,
     * the max timeout tick shall not great than RT_TICK_MAX/2
     */
    RT_ASSERT(timer->init_tick < RT_TICK_MAX / 2);
    timer->timeout_tick = rt_tick_get() + timer->init_tick;

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

#ifdef RT_USING_TIMER_SOFT
    if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
    {
        /* insert timer to soft timer list */
        timer_list = rt_soft_timer_list;
    }
    else
#endif
    {
        /* insert timer to system timer list */
        timer_list = rt_timer_list;
    }

    row_head[0]  = &timer_list[0];
    for (row_lvl = 0; row_lvl < RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
    {
        for (;row_head[row_lvl] != timer_list[row_lvl].prev;
             row_head[row_lvl]  = row_head[row_lvl]->next)
        {
            struct rt_timer *t;
            rt_list_t *p = row_head[row_lvl]->next;

            /* fix up the entry pointer */
            t = rt_list_entry(p, struct rt_timer, row[row_lvl]);

            /* If we have two timers that timeout at the same time, it's
             * preferred that the timer inserted early get called early.
             * So insert the new timer to the end the the some-timeout timer
             * list.
             */
            if ((t->timeout_tick - timer->timeout_tick) == 0)
            {
                continue;
            }
            else if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX / 2)
            {
                break;
            }
        }
        if (row_lvl != RT_TIMER_SKIP_LIST_LEVEL - 1)
            row_head[row_lvl+1] = row_head[row_lvl]+1;
    }

    /* Interestingly, this super simple timer insert counter works very very
     * well on distributing the list height uniformly. By means of "very very
     * well", I mean it beats the randomness of timer->timeout_tick very easily
     * (actually, the timeout_tick is not random and easy to be attacked). */
    random_nr++;
    tst_nr = random_nr;

    rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL-1],
                         &(timer->row[RT_TIMER_SKIP_LIST_LEVEL-1]));
    for (row_lvl = 2; row_lvl <= RT_TIMER_SKIP_LIST_LEVEL; row_lvl++)
    {
        if (!(tst_nr & RT_TIMER_SKIP_LIST_MASK))
            rt_list_insert_after(row_head[RT_TIMER_SKIP_LIST_LEVEL - row_lvl],
                                 &(timer->row[RT_TIMER_SKIP_LIST_LEVEL - row_lvl]));
        else
            break;
        /* Shift over the bits we have tested. Works well with 1 bit and 2
         * bits. */
        tst_nr >>= (RT_TIMER_SKIP_LIST_MASK+1)>>1;
    }

    timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

#ifdef RT_USING_TIMER_SOFT
    if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
    {
        /* check whether timer thread is ready */
        if (timer_thread.stat != RT_THREAD_READY)
        {
            /* resume timer thread to check soft timer */
            rt_thread_resume(&timer_thread);
            rt_schedule();
        }
    }
#endif

    return -RT_EOK;
}