Exemplo n.º 1
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)
{
	struct rt_timer* t;
	register rt_base_t level;
	rt_list_t *n, *timer_list;

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

#ifdef RT_USING_HOOK
	if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(timer->parent));
#endif

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

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

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

	for (n = timer_list->next; n != timer_list; n = n->next)
	{
		t = rt_list_entry(n, struct rt_timer, list);
		
		/*
		 * It supposes that the new tick shall less than the half duration of tick max.
		 */
		if ((t->timeout_tick - timer->timeout_tick) < RT_TICK_MAX/2)
		{
			rt_list_insert_before(n, &(timer->list));
			break;
		}
	}
	/* no found suitable position in timer list */
	if (n == timer_list)
	{
		rt_list_insert_before(n, &(timer->list));
	}
		
	timer->parent.flag |= RT_TIMER_FLAG_ACTIVATED;

	/* enable interrupt */
	rt_hw_interrupt_enable(level);

	return -RT_EOK;
}
Exemplo n.º 2
0
/**
 * This function will suspend a thread for a specified IPC object and put the
 * thread into suspend queue of IPC object
 *
 * @param ipc the IPC object
 * @param thread the thread object to be suspended
 *
 * @return the operation status, RT_EOK on successful
 */
rt_inline rt_err_t rt_ipc_object_suspend(struct rt_ipc_object *ipc, struct rt_thread *thread)
{
	/* suspend thread */
	rt_thread_suspend(thread);
	ipc->suspend_thread_count ++;

	switch (ipc->parent.flag)
	{
	case RT_IPC_FLAG_FIFO:
		rt_list_insert_before(&(ipc->suspend_thread), &(thread->tlist));
		break;

	case RT_IPC_FLAG_PRIO:
		{
			struct rt_list_node* n;
			struct rt_thread* sthread;

			/* find a suitable position */
			for (n = ipc->suspend_thread.next; n != &(ipc->suspend_thread);
				n = n->next)
			{
				sthread = rt_list_entry(n, struct rt_thread, tlist);

				/* find out */
				if (thread->current_priority < sthread->current_priority) break;
			}

			rt_list_insert_before(&(ipc->suspend_thread), &(thread->tlist));
		}
		break;
	}

	return RT_EOK;
}
Exemplo n.º 3
0
/**
 * 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.
 *
 * @return RT_EOK
 *
 */
rt_err_t rt_thread_yield(void)
{
	register rt_base_t level;
	struct rt_thread *thread;

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

	/* set to current thread */
	thread = rt_current_thread;

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

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

		/* enable interrupt */
		rt_hw_interrupt_enable(level);

		rt_schedule();

		return RT_EOK;
	}

	/* enable interrupt */
	rt_hw_interrupt_enable(level);

	return RT_EOK;
}
Exemplo n.º 4
0
rt_err_t rt_completion_wait(struct rt_completion *completion, rt_int32_t timeout)
{
    rt_err_t result;
    rt_base_t level;
    rt_thread_t thread;
    RT_ASSERT(completion != RT_NULL);

    result = RT_EOK;
    thread = rt_thread_self();

    level = rt_hw_interrupt_disable();
    if (completion->flag != RT_COMPLETED)
    {
        /* only one thread can suspend on complete */
        RT_ASSERT(rt_list_isempty(&(completion->suspended_list)));

        if (timeout == 0)
        {
            result = -RT_ETIMEOUT;
            goto __exit;
        }
        else
        {
            /* reset thread error number */
            thread->error = RT_EOK;

            /* suspend thread */
            rt_thread_suspend(thread);
            /* add to suspended list */
            rt_list_insert_before(&(completion->suspended_list), &(thread->tlist));

            /* current context checking */
            RT_DEBUG_NOT_IN_INTERRUPT;

            /* 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();
            /* clean completed flag */
            completion->flag = RT_UNCOMPLETED;
        }
    }

__exit:
    rt_hw_interrupt_enable(level);
    return result;
}
Exemplo n.º 5
0
/**
 * This function will suspend a thread to a specified list. IPC object or some double-queue
 * object (mailbox etc.) contains this kind of list.
 *
 * @param ipc the IPC object
 * @param thread the thread object to be suspended
 *
 * @return the operation status, RT_EOK on successful
 */
rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, struct rt_thread *thread, rt_uint8_t flag)
{
	/* suspend thread */
	rt_thread_suspend(thread);

	switch (flag)
	{
	case RT_IPC_FLAG_FIFO:
		rt_list_insert_before(list, &(thread->tlist));
		break;

	case RT_IPC_FLAG_PRIO:
		{
			struct rt_list_node *n;
			struct rt_thread *sthread;

			/* find a suitable position */
			for (n = list->next; n != list; n = n->next)
			{
				sthread = rt_list_entry(n, struct rt_thread, tlist);

				/* find out */
				if (thread->current_priority < sthread->current_priority)
				{
					/* insert this thread before the sthread */
					rt_list_insert_before(&(sthread->tlist), &(thread->tlist));
					break;
				}
			}

			/* not found a suitable position, append to the end of suspend_thread list */
			if (n == list)
				rt_list_insert_before(list, &(thread->tlist));
		}
		break;
	}

	return RT_EOK;
}
Exemplo n.º 6
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)
{
	rt_list_t *n;
	struct rt_timer* t;
	register rt_base_t level;

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

#ifdef RT_USING_HOOK
	if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(timer->parent));
#endif

	timer->timeout_tick = rt_tick_get() + timer->init_tick;

	/* disable interrupt */
	level = rt_hw_interrupt_disable();
	if (timer->parent.flag & RT_TIMER_FLAG_SOFT_TIMER)
	{/* insert timer to soft timer list */	
		for (n = rt_soft_timer_list.next; n != &rt_soft_timer_list; n = n->next)
		{
			t = rt_list_entry(n, struct rt_timer, list);
			if (t->timeout_tick > timer->timeout_tick)
			{
				rt_list_insert_before(n, &(timer->list));
				break;
			}
		}
		/* no found suitable position in timer list */
		if (n == &rt_soft_timer_list)
		{
			rt_list_insert_before(n, &(timer->list));
		}
	}
	else
	{/* insert timer to system timer list */	
		/* insert timer to system timer list */	
		for (n = rt_timer_list.next; n != &rt_timer_list; n = n->next)
Exemplo n.º 7
0
/**
 * This function will add the zombie task to zombie queue, when time expired,
 * this task will be deleted
 */
rt_err_t rt_rms_detach(rt_rms_t rms)
{
    rt_base_t level;
    level = rt_hw_interrupt_disable();
    /* remove from ready queue */
    rt_schedule_remove_rms(rms);
    rms->thread->stat = RT_RMS_ZOMBIE;

    /* insert into idle queue */
    rt_list_insert_before(&(rt_rms_zombie_table[rms->thread->current_priority]),
                          &(rms->rlist));

    rt_hw_interrupt_enable(level);

    return RT_RMS_EOK;
}
Exemplo n.º 8
0
/**
 * This funciton will insert a rms thread to system ready queue.
 */
void rt_schedule_insert_rms(struct rt_rms *rms)
{
    register rt_base_t temp;

    RT_ASSERT(rms != RT_NULL);

    temp = rt_hw_interrupt_disable();

    rms->thread->stat = RT_RMS_READY;

    rt_list_insert_before(&(rt_thread_priority_table[rms->thread->current_priority]),
                          &(rms->rlist));

#if RT_THREAD_PRIORITY_MAX > 32
    rt_thread_ready_table[rms->thread->number] |= rms->thread->high_mask;
#endif
    rt_thread_ready_priority_group |= rms->thread->number_mask;

    rt_hw_interrupt_enable(temp);
}
Exemplo n.º 9
0
/*
 * This function will insert a thread to system ready queue. The state of
 * thread will be set as READY and remove from suspend queue.
 *
 * @param thread the thread to be inserted
 * @note Please do not invoke this function in user application.
 */
void rt_schedule_insert_thread(struct rt_thread *thread)
{
    register rt_base_t temp;

    RT_ASSERT(thread != RT_NULL);

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

    /* change stat */
    thread->stat = RT_THREAD_READY;

    /* insert thread to ready list */
    rt_list_insert_before(&(rt_thread_priority_table[thread->current_priority]),
                          &(thread->tlist));

    /* set priority mask */
#if RT_THREAD_PRIORITY_MAX <= 32
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER, ("insert thread[%.*s], the priority: %d\n",
                                      RT_NAME_MAX, thread->name, thread->current_priority));
#else
    RT_DEBUG_LOG(RT_DEBUG_SCHEDULER,
                 ("insert thread[%.*s], the priority: %d 0x%x %d\n",
                  RT_NAME_MAX,
                  thread->name,
                  thread->number,
                  thread->number_mask,
                  thread->high_mask));
#endif

#if RT_THREAD_PRIORITY_MAX > 32
    rt_thread_ready_table[thread->number] |= thread->high_mask;
#endif
    rt_thread_ready_priority_group |= thread->number_mask;

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
}
Exemplo n.º 10
0
/**
 * insert a task into the idle queue
 * when a periodic job finishes at the end of its period, it should call the rt_end_cycle() explicitly
 */
void rt_rms_end_cycle(void)
{
    register rt_base_t level;
    rt_int32_t deadline;
    struct rt_rms *rms;
    rt_tick_t tick;

    rms = rt_current_rms;
    deadline = rt_current_rms->deadline;
    tick = rt_tick_get();
    if(rt_current_rms->deadline < tick)
    {
        rt_kprintf("rms task(%s) miss its deadline at current_tick:%d\n", rt_current_rms->thread->name, rt_tick_get());
        rt_rms_detach(rt_current_rms);
    }
    if(tick < deadline)
    {
        level = rt_hw_interrupt_disable();
        /* remove from ready queue */
        rt_schedule_remove_rms(rt_current_rms);
        rms->thread->stat = RT_RMS_IDLE;

        /* insert into idle queue */
        rt_list_insert_before(&(rt_rms_idle_table[rms->thread->current_priority]),
                              &(rms->rlist));

        rt_hw_interrupt_enable(level);
    }
    else
    {
        deadline += rt_current_rms->period;
        rt_current_rms->deadline = deadline;
        rt_current_rms->thread->stat = RT_RMS_READY;
    }

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