2 Star 2 Fork 1

MXQnNSBNci5DaGVu / ARMProjects

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
ipc.c 13.21 KB
一键复制 编辑 原始数据 按行查看 历史
MXQnNSBNci5DaGVu 提交于 2019-02-26 14:15 . 2019.2.26 事件集
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592
#include <rtthread.h>
#include <rthw.h>
rt_inline rt_err_t rt_ipc_object_init(struct rt_ipc_object *ipc)
{
rt_list_init(&(ipc->suspend_thread));
return RT_EOK;
}
rt_inline rt_err_t rt_ipc_list_suspend(rt_list_t *list, struct rt_thread *thread, rt_uint8_t flag){
struct rt_list_node *n;
struct rt_thread *sthread;
rt_thread_suspend(thread);
switch (flag){
case RT_IPC_FLAG_FIFO:
rt_list_insert_before(list, &(thread->tlist));
break;
case RT_IPC_FLAG_PRIO:
for(n = list->next; n != list; n = n->next){
sthread = rt_list_entry(n, struct rt_thread, tlist);
if(thread->current_priority < sthread->current_priority){
rt_list_insert_before(&(sthread->tlist), &(thread->tlist));
break;
}
}
if(n == list)
rt_list_insert_before(list, &(thread->tlist));
break;
}
return RT_EOK;
}
rt_inline rt_err_t rt_ipc_list_resume(rt_list_t *list){
struct rt_thread *thread;
thread = rt_list_entry(list->next, struct rt_thread, tlist);
rt_thread_resume(thread);
return RT_EOK;
}
rt_inline rt_err_t rt_ipc_list_resume_all(rt_list_t *list)
{
struct rt_thread *thread;
register rt_ubase_t temp;
while(!rt_list_isempty(list)){
temp = rt_hw_interrupt_disable();
thread = rt_list_entry(list->next, struct rt_thread, tlist);
rt_thread_resume(thread);
rt_hw_interrupt_enable(temp);
}
return RT_EOK;
}
rt_err_t rt_sem_init(rt_sem_t sem, const char *name, rt_uint32_t value, rt_uint8_t flag)
{
rt_object_init(&(sem->parent.parent), RT_Object_Class_Semaphore, name);
rt_ipc_object_init(&(sem->parent));
sem->value = (rt_uint16_t)value;
sem->parent.parent.flag = flag;
return RT_EOK;
}
rt_err_t rt_sem_detach(rt_sem_t sem)
{
rt_ipc_list_resume_all(&(sem->parent.suspend_thread));
rt_object_detach(&(sem->parent.parent));
return RT_EOK;
}
rt_sem_t rt_sem_create(const char *name, rt_uint32_t value, rt_uint8_t flag){
rt_sem_t sem;
sem = (rt_sem_t)rt_object_allocate(RT_Object_Class_Semaphore, name);
if(sem == RT_NULL){
return RT_NULL;
}
rt_ipc_object_init(&sem->parent);
sem->value = (rt_uint16_t)value;
sem->parent.parent.flag = flag;
return sem;
}
rt_err_t rt_sem_delete(rt_sem_t sem){
RT_ASSERT(sem != RT_NULL);
rt_ipc_list_resume_all(&(sem->parent.suspend_thread));
rt_object_delete((rt_object_t)sem);
return RT_EOK;
}
rt_err_t rt_sem_take(rt_sem_t sem, rt_int32_t time){
struct rt_thread *thread;
register rt_ubase_t temp;
RT_ASSERT(sem != RT_NULL);
RT_ASSERT(rt_object_get_type(&sem->parent.parent) == RT_Object_Class_Semaphore);
temp = rt_hw_interrupt_disable();
if(sem->value > 0){
sem->value--;
rt_hw_interrupt_enable(temp);
}else{
if(time == 0){
rt_hw_interrupt_enable(temp);
return -RT_ETIMEOUT;
}else{
thread = rt_thread_self();
thread->error = RT_EOK;
rt_ipc_list_suspend(&(sem->parent.suspend_thread), thread, sem->parent.parent.flag);
if(time > 0){
rt_timer_control(&(thread->thread_timer), RT_TIMER_CTRL_SET_TIME, &time);
rt_timer_start(&(thread->thread_timer));
}
rt_hw_interrupt_enable(temp);
rt_schedule();
/* 当线程恢复后,thread->error 不等于 RT_EOK 说明出错或超时 */
if(thread->error != RT_EOK){
return thread->error;
}
}
}
return RT_EOK;
}
rt_err_t rt_sem_trytake(rt_sem_t sem){
return rt_sem_take(sem, 0);
}
rt_err_t rt_sem_release(rt_sem_t sem){
rt_ubase_t temp;
rt_bool_t need_schedule;
RT_ASSERT(sem != RT_NULL);
need_schedule = RT_FALSE;
temp = rt_hw_interrupt_disable();
if(!rt_list_isempty(&(sem->parent.suspend_thread))){ // 判断是否有挂起线程
rt_ipc_list_resume(&(sem->parent.suspend_thread)); // 有,则唤起一个
need_schedule = RT_TRUE;
}else{
sem->value++;
}
rt_hw_interrupt_enable(temp);
if(need_schedule)
rt_schedule();
return RT_EOK;
}
rt_err_t rt_sem_contrl(rt_sem_t sem, int cmd, void *arg){
rt_ubase_t tmp;
RT_ASSERT(sem != RT_NULL);
if(cmd == RT_IPC_CMD_RESET){
tmp = rt_hw_interrupt_disable();
rt_ipc_list_resume_all(&(sem->parent.suspend_thread));
sem->value = (rt_uint16_t)arg;
rt_hw_interrupt_enable(tmp);
rt_schedule();
return RT_EOK;
}
return -RT_ERROR;
}
rt_err_t rt_mutex_init(rt_mutex_t mutex, const char *name, rt_uint8_t flag){
RT_ASSERT(mutex != RT_NULL);
rt_object_init(&mutex->parent.parent, RT_Object_Class_Mutex, name);
rt_ipc_object_init(&mutex->parent);
mutex->parent.parent.flag = flag;
mutex->value = 1;
mutex->original_priority = RT_THREAD_PRIORITY_MAX - 1;
mutex->hold = 0;
mutex->owner = RT_NULL;
return RT_EOK;
}
rt_err_t rt_mutex_detach(rt_mutex_t mutex){
rt_thread_t thread;
rt_ubase_t tmp;
RT_ASSERT(mutex != RT_NULL);
rt_ipc_list_resume_all(&mutex->parent.suspend_thread);
rt_object_detach((rt_object_t)mutex);
return RT_EOK;
}
rt_mutex_t rt_mutex_create(const char *name, rt_uint8_t flag){
rt_mutex_t mutex;
RT_ASSERT(mutex != RT_NULL);
mutex = (rt_mutex_t)rt_object_allocate(RT_Object_Class_Mutex, name);
if(mutex == RT_NULL){
return mutex;
}
rt_ipc_object_init(&mutex->parent);
mutex->parent.parent.flag = flag;
mutex->value = 1;
mutex->original_priority = RT_THREAD_PRIORITY_MAX - 1;
mutex->hold = 0;
mutex->owner = RT_NULL;
return mutex;
}
rt_err_t rt_mutex_delete(rt_mutex_t mutex){
RT_ASSERT(mutex != RT_NULL);
rt_ipc_list_resume_all(&mutex->parent.suspend_thread);
rt_object_delete((rt_object_t)mutex);
return RT_EOK;
}
rt_err_t rt_mutex_take(rt_mutex_t mutex, rt_int32_t time){
rt_thread_t thread;
rt_base_t tmp;
RT_ASSERT(mutex != RT_NULL);
thread = rt_thread_self();
tmp = rt_hw_interrupt_disable();
thread->error = RT_EOK;
if(mutex->owner == thread){
mutex->hold++;
}else{
if(mutex->value > 0){
mutex->value--;
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
mutex->hold++;
}else{
if(time == 0){
thread->error = -RT_ETIMEOUT;
rt_hw_interrupt_enable(tmp);
return -RT_ETIMEOUT;
}
if(mutex->original_priority > thread->current_priority){
rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &thread->current_priority);
}
rt_ipc_list_suspend(&mutex->parent.suspend_thread, thread, mutex->parent.parent.flag);
if(time > 0){
rt_timer_control(&thread->thread_timer, RT_TIMER_CTRL_SET_TIME, &time);
rt_timer_start(&thread->thread_timer);
}
rt_hw_interrupt_enable(tmp);
rt_schedule();
if(thread->error != RT_EOK){
return thread->error;
}
tmp = rt_hw_interrupt_disable();
}
}
rt_hw_interrupt_enable(tmp);
return RT_EOK;
}
rt_err_t rt_mutex_release(rt_mutex_t mutex){
rt_thread_t thread;
rt_base_t tmp;
rt_bool_t need_schedule = RT_FALSE;
RT_ASSERT(mutex != RT_NULL);
thread = rt_thread_self();
tmp = rt_hw_interrupt_disable();
if(mutex->owner != thread){
thread->error = -RT_ERROR;
rt_hw_interrupt_enable(tmp);
return -RT_ERROR;
}
mutex->hold--;
if(mutex->hold == 0){
if(mutex->original_priority != mutex->owner->current_priority){
rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &(mutex->original_priority));
}
if(!rt_list_isempty(&mutex->parent.suspend_thread)){
thread = rt_list_entry(mutex->parent.suspend_thread.next, struct rt_thread, tlist);
mutex->owner = thread;
mutex->original_priority = thread->current_priority;
mutex->hold++;
rt_ipc_list_resume(&mutex->parent.suspend_thread);
need_schedule = RT_TRUE;
}else{
mutex->value++;
mutex->owner = RT_NULL;
mutex->original_priority = RT_THREAD_PRIORITY_MAX - 1;
}
}
rt_hw_interrupt_enable(tmp);
if(need_schedule){
rt_schedule();
}
return RT_EOK;
}
rt_err_t rt_mutex_control(rt_mutex_t mutex, int cmd, void *arg){
RT_ASSERT(mutex != RT_NULL);
return -RT_ERROR;
}
rt_err_t rt_event_init(rt_event_t event, const char *name, rt_uint8_t flag){
RT_ASSERT(event != RT_NULL);
rt_object_init(&event->parent.parent, RT_Object_Class_Event, name);
rt_ipc_object_init(&event->parent);
event->parent.parent.flag = flag;
event->set = 0;
return RT_EOK;
}
rt_err_t rt_event_detach(rt_event_t event){
RT_ASSERT(event != RT_NULL);
rt_ipc_list_resume_all(&event->parent.suspend_thread);
rt_object_detach(&event->parent.parent);
event->set = 0;
return RT_EOK;
}
rt_event_t rt_event_create(const char *name, rt_uint8_t flag){
rt_event_t event;
event = (rt_event_t)rt_object_allocate(RT_Object_Class_Event, name);
if(event == RT_NULL){
return event;
}
rt_ipc_object_init(&(event->parent));
event->parent.parent.flag = flag;
event->set = 0;
return event;
}
rt_err_t rt_event_delete(rt_event_t event){
RT_ASSERT(event != RT_NULL);
rt_ipc_list_resume_all(&event->parent.suspend_thread);
rt_object_delete(&event->parent.parent);
return RT_EOK;
}
rt_err_t rt_event_send(rt_event_t event, rt_uint32_t set){
rt_ubase_t tmp;
rt_thread_t thread;
struct rt_list_node *n;
rt_base_t status;
rt_bool_t need_schedule = RT_FALSE;
RT_ASSERT(event != RT_NULL);
if(set == 0){
return -RT_ERROR;
}
tmp = rt_hw_interrupt_disable();
event->set |= set;
if(!rt_list_isempty(&event->parent.suspend_thread)){
n = event->parent.suspend_thread.next;
while(n != &event->parent.suspend_thread){
thread = rt_list_entry(n, struct rt_thread, tlist);
status = -RT_ERROR;
if(thread->event_info & RT_EVENT_FLAG_AND){
if((thread->event_set & event->set) == thread->event_set){
status = RT_EOK;
}
}else if(thread->event_info & RT_EVENT_FLAG_OR){
if(thread->event_set & event->set){
thread->event_set = thread->event_set & event->set;
status = RT_EOK;
}
}
n = n->next;
if(status == RT_EOK){
if(thread->event_info & RT_EVENT_FLAG_CLEAR){
event->set &= ~thread->event_set;
}
rt_thread_resume(thread); // 如果 n=n->next 放在后面,就改变了链表指向。
need_schedule = RT_TRUE;
}
}
}
rt_hw_interrupt_enable(tmp);
if(need_schedule == RT_TRUE){
rt_schedule();
}
return RT_EOK;
}
rt_err_t rt_event_recv(rt_event_t event, rt_uint32_t set, rt_uint8_t option,
rt_int32_t timeout, rt_uint32_t *recved){
rt_ubase_t tmp;
rt_thread_t thread;
rt_base_t status = -RT_ERROR;
RT_ASSERT(event != RT_NULL);
if (set == 0)
return -RT_ERROR;
thread = rt_thread_self();
thread->error = RT_EOK;
tmp = rt_hw_interrupt_disable();
if(option & RT_EVENT_FLAG_AND){
if((event->set & set) == set){
status = RT_EOK;
}
}else if(option & RT_EVENT_FLAG_OR){
if(event->set & set){
status = RT_EOK;
}
}
if(status == RT_EOK){
if(recved)
*recved = (event->set & set);
if(option & RT_EVENT_FLAG_CLEAR){
event->set &= ~set;
}
}else if(timeout == 0){
thread->error = -RT_ETIMEOUT;
}else{
thread->event_info = option;
thread->event_set = set;
rt_ipc_list_suspend(&event->parent.suspend_thread, thread, event->parent.parent.flag);
if(timeout > 0){
rt_timer_control(&thread->thread_timer, RT_TIMER_CTRL_SET_TIME, &timeout);
rt_timer_start(&thread->thread_timer);
}
rt_hw_interrupt_enable(tmp);
rt_schedule();
if(thread->error != RT_EOK){
return thread->error;
}
tmp = rt_hw_interrupt_disable();
if(recved)
*recved = thread->event_set;
}
rt_hw_interrupt_enable(tmp);
return thread->error;
}
rt_err_t rt_event_control(rt_event_t event, int cmd, void *arg){
rt_ubase_t level;
RT_ASSERT(event != RT_NULL);
if (cmd == RT_IPC_CMD_RESET){
level = rt_hw_interrupt_disable();
rt_ipc_list_resume_all(&event->parent.suspend_thread);
event->set = 0;
rt_hw_interrupt_enable(level);
rt_schedule();
return RT_EOK;
}
return -RT_ERROR;
}
C
1
https://gitee.com/cducode/ARMProjects.git
git@gitee.com:cducode/ARMProjects.git
cducode
ARMProjects
ARMProjects
master

搜索帮助