📄 ipc.c.svn-base
字号:
/* * File : ipc.c * This file is part of RT-Thread RTOS * COPYRIGHT (C) 2006, RT-Thread Development Team * * The license and distribution terms for this file may be * found in the file LICENSE in this distribution or at * http://www.fayfayspace.org/license/LICENSE. * * Change Logs: * Date Author Notes * 2006-03-14 Bernard the first version * 2006-04-25 Bernard implement semaphore * 2006-05-03 Bernard add IPC_DEBUG * modify the type of IPC waiting time to rt_int32 * 2006-05-10 Bernard fix the semaphore take bug and add IPC object * 2006-05-12 Bernard implement mailbox and message queue * 2006-05-20 Bernard implement mutex * 2006-05-23 Bernard implement fast event * 2006-05-24 Bernard implement event * 2006-06-03 Bernard fix the thread timer init bug * 2006-06-05 Bernard fix the mutex release bug * 2006-06-07 Bernard fix the message queue send bug */#include <rtthread.h>#include <rthw.h>#include "kservice.h"/** * @addtogroup Kernel *//*@{*/// #define IPC_DEBUGrt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc){ /* init ipc object */ rt_list_init(&(ipc->suspend_thread)); ipc->suspend_thread_count = 0; return RT_EOK;}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_after(&(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;}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 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;}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;}#ifdef RT_USING_SEMAPHORE/** * @brief init a semaphore * * This function will init a semaphore * * @param sem the semaphore handler * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the created semaphore, RT_NULL on error hanpen * * @see rt_sem_init */rt_err_t rt_sem_init (rt_sem_t sem, const char* name, rt_uint32 value, rt_uint8 flag){ RT_ASSERT(sem != RT_NULL); /* init object */ rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name); /* init ipc object */ rt_ipc_object_init(&(sem->parent)); /* set init value */ sem->value = value; /* set parent */ sem->parent.parent.flag = flag; return RT_EOK;}/** * @brief detach a semaphore * * This function will detach a semaphore from resource management * * @param sem the semaphore handler * * @return the error code * * @see rt_sem_delete */rt_err_t rt_sem_detach (rt_sem_t sem){ RT_ASSERT(sem != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(sem->parent)); /* detach semaphore object */ rt_object_detach(&(sem->parent.parent)); return RT_EOK;}/** * @brief create a semaphore * * This function will create a semaphore from system resource * * @param name the name of semaphore * @param value the init value of semaphore * @param flag the flag of semaphore * * @return the created semaphore, RT_NULL on error hanpen * * @see rt_sem_init */rt_sem_t rt_sem_create (const char* name, rt_uint32 value, rt_uint8 flag){ rt_sem_t sem; /* allocate object */ sem = (rt_sem_t) rt_object_allocate(RT_Object_Class_Semaphore, name); if (sem == RT_NULL) return sem; /* init ipc object */ rt_ipc_object_init(&(sem->parent)); /* set init value */ sem->value = value; /* set parent */ sem->parent.parent.flag = flag; return sem;}/** * @brief delete a semaphore * * This function will delete a semaphore and release the system resource * * @param sem the semaphore handler * * @return the error code * * @see rt_sem_detach */rt_err_t rt_sem_delete (rt_sem_t sem){ RT_ASSERT(sem != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(sem->parent)); /* delete semaphore object */ rt_object_delete(&(sem->parent.parent)); return RT_EOK;}/** * @brief take a semaphore * * This function will take a semaphore, if the semaphore is * unavailable, the thread shall wait for a specify time. * * @param sem the semaphore handler * @param time the waiting time * * @return the error code */rt_err_t rt_sem_take (rt_sem_t sem, rt_int32 time){ register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(sem != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG rt_kprintf("sem_take:sem value: %d\n", sem->value);#endif if (sem->value > 0) { /* semaphore is available */ sem->value --; /* enable interrupt */ rt_hw_interrupt_enable(temp); } else { /* no waiting, return with timeout */ if (time == 0 ) { rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* semaphore is unavailable, push to suspend list */ sem->value --; /* get current thread */ thread = rt_thread_self(); /* reset thread error number */ thread->error = RT_EOK;#ifdef IPC_DEBUG rt_kprintf("sem take: suspend thread - %s\n", thread->name);#endif /* suspend thread */ rt_ipc_object_suspend(&(sem->parent), thread); /* has waiting time, start thread timer */ if (time > 0) {#ifdef IPC_DEBUG rt_kprintf("set thread:%s to timer list\n", thread->name);#endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { return thread->error; } } } return RT_EOK;}/** * @brief try to take a semaphore * * This function will try to take a semaphore and immediately return * * @param sem the semaphore handler * * @return the error code */rt_err_t rt_sem_trytake(rt_sem_t sem){ return rt_sem_take(sem, 0);}/** * @brief release a semaphore * * This function will release a semaphore * * @param sem the semaphore handler * * @return the error code */rt_err_t rt_sem_release(rt_sem_t sem){ register rt_base_t temp; /* disable interrupt */ temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG rt_kprintf("sem_release:sem value(%d)\n", sem->value);#endif if (sem->value <= 0 && sem->parent.suspend_thread_count > 0) { rt_ipc_object_resume(&(sem->parent)); } /* increase value */ sem->value ++; /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK;}/** * @brief control a semaphore execution * * This function can get or set some extra attribute of a semaphore * * @param sem the semaphore handler * @param cmd the execution command * @param arg the execution argument * * @return the error code */rt_err_t rt_sem_control(rt_sem_t sem, rt_uint8 cmd, void* arg){ return RT_EOK;}#endif /* end of RT_USING_SEMAPHORE */#ifdef RT_USING_MUTEXrt_err_t rt_mutex_init (rt_mutex_t mutex, const char* name, rt_uint8 flag){ RT_ASSERT(mutex != RT_NULL); /* init object */ rt_object_init(&(mutex->parent.parent), RT_Object_Class_Mutex, name); /* init ipc object */ rt_ipc_object_init(&(mutex->parent)); mutex->value = 1; mutex->owner = RT_NULL; mutex->original_priority = 0xFF; mutex->hold = 0; /* set flag */ mutex->parent.parent.flag = flag; return RT_EOK;}rt_err_t rt_mutex_detach (rt_mutex_t mutex){ RT_ASSERT(mutex != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(mutex->parent)); /* detach semaphore object */ rt_object_detach(&(mutex->parent.parent)); return RT_EOK;}rt_mutex_t rt_mutex_create (const char* name, rt_uint8 flag){ struct rt_mutex *mutex; /* allocate object */ mutex = (rt_mutex_t) rt_object_allocate(RT_Object_Class_Mutex, name); if (mutex == RT_NULL) return mutex; /* init ipc object */ rt_ipc_object_init(&(mutex->parent)); mutex->value = 1; mutex->owner = RT_NULL; mutex->original_priority = 0xFF; mutex->hold = 0; /* set flag */ mutex->parent.parent.flag = flag; return mutex;}rt_err_t rt_mutex_delete (rt_mutex_t mutex){ RT_ASSERT(mutex != RT_NULL); /* wakeup all suspend threads */ rt_ipc_object_resume_all(&(mutex->parent)); /* delete semaphore object */ rt_object_delete(&(mutex->parent.parent)); return RT_EOK;}rt_err_t rt_mutex_take (rt_mutex_t mutex, rt_int32 time){ register rt_base_t temp; struct rt_thread* thread; RT_ASSERT(mutex != RT_NULL); /* disable interrupt */ temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG rt_kprintf("mutex_take:mutex value: %d, hold: %d\n", mutex->value, mutex->hold);#endif /* get current thread */ thread = rt_thread_self(); /* reset thread error */ thread->error = RT_EOK; if (mutex->owner == thread) { /* it's the same thread */ mutex->hold ++; } else { if (mutex->value > 0) { /* mutex is available */ mutex->value --; /* set mutex owner and original priority */ mutex->owner = thread; mutex->original_priority = thread->current_priority; mutex->hold ++; } else { /* no waiting, return with timeout */ if (time == 0 ) { /* set error as timeout */ thread->error = -RT_ETIMEOUT; /* enable interrupt */ rt_hw_interrupt_enable(temp); return -RT_ETIMEOUT; } else { /* mutex is unavailable, push to suspend list */ mutex->value --;#ifdef IPC_DEBUG rt_kprintf("sem take: suspend thread: %s\n", thread->name);#endif /* change the owner thread priority of mutex */ if (thread->current_priority < mutex->owner->current_priority) { /* change the owner thread priority */ rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &thread->current_priority); } /* suspend current thread */ rt_ipc_object_suspend(&(mutex->parent), thread); /* has waiting time, start thread timer */ if (time > 0) {#ifdef IPC_DEBUG rt_kprintf("set thread:%s to timer list\n", thread->name);#endif /* reset the timeout of thread timer and start it */ rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time); rt_timer_start(&(thread->thread_timer)); } /* enable interrupt */ rt_hw_interrupt_enable(temp); /* do schedule */ rt_schedule(); if (thread->error != RT_EOK) { /* return error */ return thread->error; } else { /* disable interrupt */ temp = rt_hw_interrupt_disable(); /* take mutex */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -