Example #1
0
/**
 * @ingroup Thread
 *
 * This function will perform system background job when system idle.
 */
void rt_thread_idle_excute(void)
{
    /* check the defunct thread list */
    if (!rt_list_isempty(&rt_thread_defunct))
    {
        rt_base_t lock;
        rt_thread_t thread;
#ifdef RT_USING_MODULE
        rt_module_t module = RT_NULL;
#endif
        RT_DEBUG_NOT_IN_INTERRUPT;

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

        /* re-check whether list is empty */
        if (!rt_list_isempty(&rt_thread_defunct))
        {
            /* get defunct thread */
            thread = rt_list_entry(rt_thread_defunct.next,
                                   struct rt_thread,
                                   tlist);
#ifdef RT_USING_MODULE
            /* get thread's parent module */
            module = (rt_module_t)thread->module_id;

            /* if the thread is module's main thread */
            if (module != RT_NULL && module->module_thread == thread)
            {
                /* detach module's main thread */
                module->module_thread = RT_NULL;
            }
#endif
            /* remove defunct thread */
            rt_list_remove(&(thread->tlist));
            /* invoke thread cleanup */
            if (thread->cleanup != RT_NULL)
                thread->cleanup(thread);

            /* if it's a system object, not delete it */
            if (rt_object_is_systemobject((rt_object_t)thread) == RT_TRUE)
            {
                /* enable interrupt */
                rt_hw_interrupt_enable(lock);

                return;
            }
        }
Example #2
0
/**
 * This function will remove a rms task from system ready queue.
 */
void rt_schedule_remove_rms(struct rt_rms *rms)
{
    register rt_base_t temp;

    RT_ASSERT(rms != RT_NULL);

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

    /* remove thread from ready list */
    rt_list_remove(&(rms->rlist));
    if(rt_list_isempty(&(rt_thread_priority_table[rms->thread->current_priority])))
    {
#if RT_THREAD_PRIORITY_MAX > 32
        rt_thread_ready_table[rms->thread->number] &= ~rms->thread->high_mask;
        if(rt_thread_ready_table[rms->thread->number] == 0)
        {
            rt_thread_ready_priority_group &= ~rms->thread->number_mask;
        }
#else
        rt_thread_ready_priority_group &= ~rms->thread->number_mask;
#endif
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
}
Example #3
0
/**
 * This function will release a semaphore, if there are threads suspended on
 * semaphore, it will be waked up.
 *
 * @param sem the semaphore object
 *
 * @return the error code
 */
rt_err_t rt_sem_release(rt_sem_t sem)
{
	register rt_base_t temp;
	register rt_bool_t need_schedule;

	RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(sem->parent.parent)));

	need_schedule = RT_FALSE;

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

	RT_DEBUG_LOG(RT_DEBUG_IPC,
		("thread %s releases sem:%s, which value is: %d\n", rt_thread_self()->name,
		((struct rt_object *)sem)->name, sem->value));


	if (!rt_list_isempty(&sem->parent.suspend_thread))
	{
		/* resume the suspended thread */
		rt_ipc_list_resume(&(sem->parent.suspend_thread));
		need_schedule = RT_TRUE;
	}
	else sem->value ++; /* increase value */

	/* enable interrupt */
	rt_hw_interrupt_enable(temp);

	/* resume a thread, re-schedule */
	if (need_schedule == RT_TRUE) rt_schedule();

	return RT_EOK;
}
Example #4
0
static void rt_thread_idle_entry(void* parameter)
{
	while (1)
	{
#ifdef RT_USING_HOOK
		/* if there is an idle thread hook */
		if (rt_thread_idle_hook != RT_NULL) rt_thread_idle_hook();
#endif

#ifdef RT_USING_HEAP
		/* check the defunct thread list */
		if (!rt_list_isempty(&rt_thread_defunct))
		{
			rt_base_t lock;

			struct rt_thread* thread = rt_list_entry(rt_thread_defunct.next, struct rt_thread, tlist);

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

			rt_list_remove(&(thread->tlist));

			/* enable interrupt */
			rt_hw_interrupt_enable(lock);

			/* release thread's stack */
			rt_free(thread->stack_addr);

			/* delete thread object */
			rt_object_delete((rt_object_t)thread);
		}
#endif
	}
Example #5
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
    {
Example #6
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;
}
Example #7
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;
}
Example #8
0
/*
 * can interrupt routines
 */
rt_inline int _can_int_rx(struct rt_can_device *can, struct rt_can_msg *data, int msgs)
{
    int size;
    struct rt_can_rx_fifo* rx_fifo;

    RT_ASSERT(can != RT_NULL);
    size = msgs; 
    
    rx_fifo = (struct rt_can_rx_fifo*) can->can_rx;
    RT_ASSERT(rx_fifo != RT_NULL);

    /* read from software FIFO */
    while (msgs)
    {
        rt_base_t level;
        struct rt_can_msg_list *listmsg=RT_NULL;
        /* disable interrupt */
        level = rt_hw_interrupt_disable();
#ifdef RT_CAN_USING_HDR
        rt_int32_t hdr = data->hdr;
        if (hdr >=0 && can->hdr && hdr < can->config.maxhdr && !rt_list_isempty(&can->hdr[hdr].list))
        {
             listmsg=rt_list_entry(can->hdr[hdr].list.next, struct rt_can_msg_list, hdrlist);
             rt_list_remove(&listmsg->list);
             rt_list_remove(&listmsg->hdrlist);
             if(can->hdr[hdr].msgs) {
               can->hdr[hdr].msgs--;                     
             }
             listmsg->owner = RT_NULL;
        } else if(hdr == -1)
Example #9
0
/**
 * This function will check timer list, if a timeout event happens, the
 * corresponding timeout function will be invoked.
 *
 * @note this function shall be invoked in operating system timer interrupt.
 */
void rt_timer_check(void)
{
    struct rt_timer *t;
    rt_tick_t current_tick;
    register rt_base_t level;

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check enter\n"));

    current_tick = rt_tick_get();

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

    while (!rt_list_isempty(&rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL-1]))
    {
        t = rt_list_entry(rt_timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);

        /*
         * It supposes that the new tick shall less than the half duration of
         * tick max.
         */
        if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2)
        {
            RT_OBJECT_HOOK_CALL(rt_timer_timeout_hook, (t));

            /* remove timer from timer list firstly */
            _rt_timer_remove(t);

            /* call timeout function */
            t->timeout_func(t->parameter);

            /* re-get tick */
            current_tick = rt_tick_get();

            RT_DEBUG_LOG(RT_DEBUG_TIMER, ("current tick: %d\n", current_tick));

            if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
                (t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
            {
                /* start it */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
                rt_timer_start(t);
            }
            else
            {
                /* stop timer */
                t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
            }
        }
        else
            break;
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(level);

    RT_DEBUG_LOG(RT_DEBUG_TIMER, ("timer check leave\n"));
}
Example #10
0
static int rt_timer_count_height(struct rt_timer *timer)
{
    int i, cnt = 0;

    for (i = 0; i < RT_TIMER_SKIP_LIST_LEVEL; i++)
    {
        if (!rt_list_isempty(&timer->row[i]))
            cnt++;
    }
    return cnt;
}
Example #11
0
/* the fist timer always in the last row */
static rt_tick_t rt_timer_list_next_timeout(rt_list_t timer_list[])
{
    struct rt_timer *timer;

    if (rt_list_isempty(&timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1]))
        return RT_TICK_MAX;

    timer = rt_list_entry(timer_list[RT_TIMER_SKIP_LIST_LEVEL - 1].next,
                          struct rt_timer, row[RT_TIMER_SKIP_LIST_LEVEL - 1]);

    return timer->timeout_tick;
}
Example #12
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;
}
Example #13
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();
    }
Example #14
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;
}
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;
    }
Example #16
0
/*
 * This function will remove a thread from system ready queue.
 *
 * @param thread the thread to be removed
 *
 * @note Please do not invoke this function in user application.
 */
void rt_schedule_remove_thread(struct rt_thread *thread)
{
    register rt_base_t temp;

    RT_ASSERT(thread != RT_NULL);

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

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

    /* remove thread from ready list */
    rt_list_remove(&(thread->tlist));
    if (rt_list_isempty(&(rt_thread_priority_table[thread->current_priority])))
    {
#if RT_THREAD_PRIORITY_MAX > 32
        rt_thread_ready_table[thread->number] &= ~thread->high_mask;
        if (rt_thread_ready_table[thread->number] == 0)
        {
            rt_thread_ready_priority_group &= ~thread->number_mask;
        }
#else
        rt_thread_ready_priority_group &= ~thread->number_mask;
#endif
    }

    /* enable interrupt */
    rt_hw_interrupt_enable(temp);
}
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);
}
Example #18
0
void rt_timer_check(void)
{
	struct rt_timer *t;
	rt_tick_t current_tick;
	register rt_base_t level;

#ifdef RT_TIMER_DEBUG
	rt_kprintf("timer check enter\n");
#endif

	current_tick = rt_tick_get();

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

	while (!rt_list_isempty(&rt_timer_list))
	{
		t = rt_list_entry(rt_timer_list.next, struct rt_timer, list);
		
		/*
		 * It supposes that the new tick shall less than the half duration of tick max.
		 */
		if ((current_tick - t->timeout_tick) < RT_TICK_MAX/2)
		{
#ifdef RT_USING_HOOK
			if (rt_timer_timeout_hook != RT_NULL) rt_timer_timeout_hook(t);
#endif

			/* remove timer from timer list firstly */
			rt_list_remove(&(t->list));

			/* call timeout function */
			t->timeout_func(t->parameter);

			/* re-get tick */
			current_tick = rt_tick_get();

#ifdef RT_TIMER_DEBUG
			rt_kprintf("current tick: %d\n", current_tick);
#endif

			if ((t->parent.flag & RT_TIMER_FLAG_PERIODIC) &&
					(t->parent.flag & RT_TIMER_FLAG_ACTIVATED))
			{
				/* start it */
				t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
				rt_timer_start(t);
			}
			else
			{
				/* stop timer */
				t->parent.flag &= ~RT_TIMER_FLAG_ACTIVATED;
			}
		}
		else break;
	}

	/* enable interrupt */
	rt_hw_interrupt_enable(level);

	/* increase soft timer tick */
#ifdef RT_USING_TIMER_SOFT
	rt_soft_timer_tick_increase ( );
#endif

#ifdef RT_TIMER_DEBUG
	rt_kprintf("timer check leave\n");
#endif
}
Example #19
0
/**
 * This function will release a mutex, if there are threads suspended on mutex,
 * it will be waked up.
 *
 * @param mutex the mutex object
 *
 * @return the error code
 */
rt_err_t rt_mutex_release(rt_mutex_t mutex)
{
	register rt_base_t temp;
	struct rt_thread *thread;
	rt_bool_t need_schedule;

	need_schedule = RT_FALSE;

	/* get current thread */
	thread = rt_thread_self();

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

	RT_DEBUG_LOG(RT_DEBUG_IPC,
		("mutex_release:current thread %s, mutex value: %d, hold: %d\n",
		thread->name, mutex->value, mutex->hold));

	RT_OBJECT_HOOK_CALL(rt_object_put_hook, (&(mutex->parent.parent)));

	/* mutex only can be released by owner */
	if (thread != mutex->owner)
	{
		thread->error = -RT_ERROR;

		/* enable interrupt */
		rt_hw_interrupt_enable(temp);

		return -RT_ERROR;
	}

	/* decrease hold */
	mutex->hold --;
	/* if no hold */
	if (mutex->hold == 0)
	{
		/* change the owner thread to original priority */
		if (mutex->original_priority != mutex->owner->current_priority)
		{
			rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY,
				&(mutex->original_priority));
		}

		/* wakeup suspended thread */
		if (!rt_list_isempty(&mutex->parent.suspend_thread))
		{
			/* get suspended thread */
			thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist);

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

			/* set new owner and priority */
			mutex->owner = thread;
			mutex->original_priority = thread->current_priority;
			mutex->hold ++;

			/* resume thread */
			rt_ipc_list_resume(&(mutex->parent.suspend_thread));

			need_schedule = RT_TRUE;
		}
		else
		{
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;
    }