📄 ipc.c.svn-base
字号:
*/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;}#endif/** * This function will take a mutex, if the mutex is unavailable, the * thread shall wait for a specified time. * * @param mutex the mutex object * @param time the waiting time * * @return the error code */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);#ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(mutex->parent.parent));#endif /* 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 */ mutex->owner = thread; mutex->hold ++; /* set thread error */ thread->error = RT_EOK; } } } } /* enable interrupt */ rt_hw_interrupt_enable(temp);#ifdef RT_USING_HOOK if (rt_object_take_hook != RT_NULL) rt_object_take_hook(&(mutex->parent.parent));#endif return RT_EOK;}/** * 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; /* disable interrupt */ temp = rt_hw_interrupt_disable();#ifdef IPC_DEBUG rt_kprintf("mutex_release:mutex value: %d, hold: %d\n", mutex->value, mutex->hold);#endif#ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(mutex->parent.parent));#endif /* get current thread */ thread = rt_thread_self(); /* mutex is only 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->owner->init_priority != mutex->owner->current_priority) { rt_thread_control(mutex->owner, RT_THREAD_CTRL_CHANGE_PRIORITY, &(mutex->owner->init_priority)); } /* wakeup suspended thread */ if (mutex->value <= 0 && mutex->parent.suspend_thread_count > 0) {#ifdef IPC_DEBUG rt_kprintf("mutex release: resume thread: %s\n", thread->name);#endif /* resume thread */ rt_ipc_object_resume(&(mutex->parent)); } /* increase value */ mutex->value ++; } /* enable interrupt */ rt_hw_interrupt_enable(temp); rt_schedule(); return RT_EOK;}/** * This function can get or set some extra attributions of a mutex object. * * @param mutex the mutex object * @param cmd the execution command * @param arg the execution argument * * @return the error code */rt_err_t rt_mutex_control(rt_mutex_t mutex, rt_uint8 cmd, void* arg){ return RT_EOK;}#endif /* end of RT_USING_MUTEX */#ifdef RT_USING_FASTEVENT/** * This function will initialize a fast event and put it under control of resource * management. * * @param event the fast event object * @param name the name of fast event * @param flag the flag of fast event * * @return the operation status, RT_EOK on successful */rt_err_t rt_fast_event_init(rt_fast_event_t event, const char* name, rt_uint8 flag){ register rt_base_t offset; RT_ASSERT(event != RT_NULL); /* init object */ rt_object_init(&(event->parent), RT_Object_Class_FastEvent, name); /* set parent */ event->parent.flag = flag; /* clear event set */ event->set = 0x00; /* init thread list */ for (offset = 0; offset < 32; offset ++) { rt_list_init(&(event->thread_list[offset])); } return RT_EOK;}/** * This function will detach a fast event from resource management * * @param event the fast event object * * @return the operation status, RT_EOK on successful */rt_err_t rt_fast_event_detach(rt_fast_event_t event){ register rt_base_t bit; struct rt_thread* thread; register rt_ubase_t level; RT_ASSERT(event != RT_NULL); for (bit = 0; bit < RT_EVENT_LENGTH; bit ++) { /* resume all suspend thread */ if (!rt_list_isempty(&(event->thread_list[bit]))) { /* wakeup all suspend threads */ while (!rt_list_isempty(&(event->thread_list[bit]))) { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(event->thread_list[bit].next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* resume thread */ rt_thread_resume(thread); /* enable interrupt */ rt_hw_interrupt_enable(level); } } } /* detach event object */ rt_object_detach(&(event->parent)); return RT_EOK;}#ifdef RT_USING_HEAP/** * This function will create a fast event object from system resource * * @param name the name of fast event * @param flag the flag of fast event * * @return the created fast event, RT_NULL on error happen */rt_fast_event_t rt_fast_event_create (const char* name, rt_uint8 flag){ rt_fast_event_t event; register rt_base_t offset; /* allocate object */ event = (rt_fast_event_t) rt_object_allocate(RT_Object_Class_FastEvent, name); if (event == RT_NULL) return event; /* set parent */ event->parent.flag = flag; /* clear event set */ event->set = 0x00; /* init thread list */ for (offset = 0; offset < 32; offset ++) { rt_list_init(&(event->thread_list[offset])); } return event;}/** * This function will delete a fast event object and release the memory * * @param event the fast event object * * @return the error code */rt_err_t rt_fast_event_delete (rt_fast_event_t event){ register rt_base_t bit; struct rt_thread* thread; register rt_ubase_t level; RT_ASSERT(event != RT_NULL); for (bit = 0; bit < RT_EVENT_LENGTH; bit ++) { /* resume all suspend thread */ if (!rt_list_isempty(&(event->thread_list[bit]))) { /* wakeup all suspend threads */ while (!rt_list_isempty(&(event->thread_list[bit]))) { /* disable interrupt */ level = rt_hw_interrupt_disable(); /* get next suspend thread */ thread = rt_list_entry(event->thread_list[bit].next, struct rt_thread, tlist); /* set error code to RT_ERROR */ thread->error = -RT_ERROR; /* resume thread */ rt_thread_resume(thread); /* enable interrupt */ rt_hw_interrupt_enable(level); } } } /* detach semaphore object */ rt_object_delete(&(event->parent)); return RT_EOK;}#endif/** * This function will send an event to the fast event object, if there are threads * suspended on fast event object, it will be waked up. * * @param event the fast event object * @param bit the event bit * * @return the error code */rt_err_t rt_fast_event_send(rt_fast_event_t event, rt_uint8 bit){ rt_uint32 offset; register rt_ubase_t level; struct rt_thread *thread; struct rt_list_node *n; /* parameter check */ RT_ASSERT(event != RT_NULL); RT_ASSERT(bit < RT_EVENT_LENGTH); offset = 1 << bit;#ifdef RT_USING_HOOK if (rt_object_put_hook != RT_NULL) rt_object_put_hook(&(event->parent));#endif /* disable interrupt */ level = rt_hw_interrupt_disable(); event->set |= offset; /* if thread list at offset is not empty */ n = event->thread_list[bit].next; while (n != &(event->thread_list[bit])) { /* get thread */ thread = rt_list_entry(n, struct rt_thread, tlist); /* move to next node */ n = n->next; /* clear bit or not */ if (thread->event_info & RT_EVENT_FLAG_CLEAR) event->set &= ~offset; /* resume thread */ rt_thread_resume(thread); } /* enable interrupt */ rt_hw_interrupt_enable(level); /* do a schedule */ rt_schedule(); return RT_EOK;}/** * This function will receive an event from fast event object, if the event is * unavailable, the thread shall wait for a specified time. * * @param event the fast event object * @param bit the interested event * @param option the receive option * @param timeout the waiting time * * @return the error code */rt_err_t rt_fast_event_recv(rt_fast_event_t event, rt_uint8 bit, rt_uint8 option, rt_int32 timeout){ rt_base_t offset; struct rt_thread* thread; register rt_ubase_t level; /* parameter check */ RT_ASSERT(event != RT_NULL); RT_ASSERT(bit < RT_EVENT_LENGTH); offset = 1 << bit;#ifdef RT_USING_HOOK if (rt_object_trytake_hook != RT_NULL) rt_object_trytake_hook(&(event->parent));#endif /* disable interrupt */ level = rt_hw_interrupt_disable(); /* get current thread */ thread = rt_thread_self(); thread->error = RT_EOK; /* get event successfully */ if (event->set & offset) { if (option & RT_EVENT_FLAG_CLEAR) event->set &= ~ offset; /* enable interrupt */ rt_hw_interrupt_enable(level); return RT_EOK; } /* no event happen */ /* check waiting time */ if (timeout == 0) { /* no waiting */ thread->error = -RT_ETIMEOUT; } else { /* there are no event, suspend thread */ rt_thread_suspend(thread); /* set event info in thread */ thread->event_info = option; switch (event->parent.flag) { case RT_IPC_FLAG_FIFO: rt_list_insert_after(&(event->thread_list[bit]), &(thread->tlist)); break; case RT_IPC_FLAG_PRIO: { struct rt_list_node* n; struct rt_thread* sthread; /* find a suitable position */ for (n = event->thread_list[bit].next; n != &(event->thread_list[bit]); n = n->next) { sthread = rt_list_entry(n, struct rt_thread, tlist); /* find out */ if (thread->current_priority < sthread->current_priority) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -