/*============================================================================== * - semC_take() * * - take a semC. this function maybe block the call task */ OS_STATUS semC_take (SEM_CNT *pSemC, uint32 timeout) { int cpsr_c; OS_STATUS status = OS_STATUS_ERROR; cpsr_c = CPU_LOCK(); again: if (pSemC->count > 0) { pSemC->count--; G_p_current_tcb->delay_ticks = 0; status = OS_STATUS_OK; } else { if (timeout != 0) { readyQ_remove (G_p_current_tcb); G_p_current_tcb->delay_ticks = timeout; G_p_current_tcb->status = TASK_STATUS_PEND_SEM_C; G_p_current_tcb->pend_obj = pSemC; dlist_add (&pSemC->wait_list, (DL_NODE *)G_p_current_tcb); CONTEXT_SWITCH(); if (G_p_current_tcb->delay_ticks != 0) { timeout = G_p_current_tcb->delay_ticks; /* recalculate timeout value */ goto again; } } } CPU_UNLOCK(cpsr_c); return status; }
void raw_sched(void) { RAW_SR_ALLOC(); /*if it is in interrupt or system is locked, just return*/ if (raw_int_nesting || raw_sched_lock) { return; } USER_CPU_INT_DISABLE(); get_ready_task(&raw_ready_queue); /*if highest task is currently task, then no need to do switch and just return*/ if (high_ready_obj == raw_task_active) { USER_CPU_INT_ENABLE(); return; } TRACE_TASK_SWITCH(raw_task_active, high_ready_obj); CONTEXT_SWITCH(); USER_CPU_INT_ENABLE(); }
/*============================================================================== * - msgQ_send() * * - try to send a message to a msgQ, this maybe block the call task */ OS_STATUS msgQ_send (MSG_QUE *pMsgQ, const void *buffer, uint32 buf_len, uint32 timeout) { int cpsr_c; OS_STATUS status = OS_STATUS_ERROR; DL_NODE *pMsgNode = NULL; OS_TCB *pWaitTcb = NULL; cpsr_c = CPU_LOCK(); again: if (pMsgQ->cur_num < pMsgQ->max_num) { /* there is some space */ pMsgQ->cur_num++; G_p_current_tcb->delay_ticks = 0; /* * alloc a messege node and add it into messge list */ pMsgNode = malloc(sizeof(DL_NODE) + pMsgQ->max_len); memcpy((void *)(pMsgNode + 1), buffer, MIN(buf_len, pMsgQ->max_len)); dlist_add(&pMsgQ->msg_list, pMsgNode); /* * get a wait for Receive task and put it into readyQ */ pWaitTcb = (OS_TCB *)dlist_get(&pMsgQ->wait_recv_list); if (pWaitTcb != NULL) { readyQ_put(pWaitTcb); } status = OS_STATUS_OK; } else { /* there is no space */ if (timeout != 0) { readyQ_remove (G_p_current_tcb); G_p_current_tcb->delay_ticks = timeout; G_p_current_tcb->status = TASK_STATUS_PEND_MSG_S; /* msg send pend */ G_p_current_tcb->pend_obj = pMsgQ; dlist_add (&pMsgQ->wait_send_list, (DL_NODE *)G_p_current_tcb); CONTEXT_SWITCH(); if (G_p_current_tcb->delay_ticks != 0) { timeout = G_p_current_tcb->delay_ticks; /* recalculate timeout value */ goto again; } } } CPU_UNLOCK(cpsr_c); return status; }
/*============================================================================== * - msgQ_receive() * * - try to receive a message from a msgQ, this maybe block the call task */ OS_STATUS msgQ_receive (MSG_QUE *pMsgQ, void *buffer, uint32 buf_len, uint32 timeout) { int cpsr_c; OS_STATUS status = OS_STATUS_ERROR; DL_NODE *pMsgNode = NULL; OS_TCB *pWaitTcb = NULL; cpsr_c = CPU_LOCK(); again: if (pMsgQ->cur_num > 0) { /* have message(s) */ pMsgQ->cur_num--; G_p_current_tcb->delay_ticks = 0; /* * copy message context to msg_list */ pMsgNode = dlist_get(&pMsgQ->msg_list); memcpy(buffer, (void *)(pMsgNode + 1), MIN(buf_len, pMsgQ->max_len)); free(pMsgNode); /* * if there are some task wait for send, alive one of them */ pWaitTcb = (OS_TCB *)dlist_get(&pMsgQ->wait_send_list); if (pWaitTcb != NULL) { readyQ_put(pWaitTcb); } status = OS_STATUS_OK; } else { /* no message */ if (timeout != 0) { readyQ_remove (G_p_current_tcb); G_p_current_tcb->delay_ticks = timeout; G_p_current_tcb->status = TASK_STATUS_PEND_MSG_R; /* msg receive pend */ G_p_current_tcb->pend_obj = pMsgQ; dlist_add (&pMsgQ->wait_recv_list, (DL_NODE *)G_p_current_tcb); CONTEXT_SWITCH(); if (G_p_current_tcb->delay_ticks != 0) { timeout = G_p_current_tcb->delay_ticks; /* recalculate timeout value */ goto again; } } } CPU_UNLOCK(cpsr_c); return status; }
void hybrid_int_process(void) { TASK_0_EVENT_TYPE hybrid_ev; RAW_U8 *hybrid_data_temp; EVENT_HANLDER *hybrid_receiver; LIST *hybrid_node; RAW_U8 hybrid_highest_pri; RAW_SR_ALLOC(); register RAW_U8 hybrid_task_may_switch = 0u; while (1) { USER_CPU_INT_DISABLE(); if (task_0_events) { /*current running task can never be task 0*/ if (raw_int_nesting) { raw_sched_lock = 0; USER_CPU_INT_ENABLE(); return; } else { --task_0_events; /* There are events that we should deliver. */ hybrid_ev = task_0_events_queue[task_0_event_end].ev; hybrid_data_temp = task_0_events_queue[task_0_event_end].event_data; hybrid_receiver = task_0_events_queue[task_0_event_end].p; task_0_event_end++; if (task_0_event_end == MAX_TASK_EVENT) { task_0_event_end = 0; } USER_CPU_INT_ENABLE(); /*exceute the event handler*/ hybrid_receiver->handle_event(hybrid_ev, hybrid_data_temp); hybrid_task_may_switch = 1; } } else { raw_sched_lock = 0; if (hybrid_task_may_switch) { hybrid_highest_pri = raw_ready_queue.highest_priority; /*Highest priority task must be the first element on the list*/ hybrid_node = raw_ready_queue.task_ready_list[hybrid_highest_pri].next; /*Get the highest priority task object*/ high_ready_obj = raw_list_entry(hybrid_node, RAW_TASK_OBJ, task_list); /*if highest task is currently task, then no need to do switch and just return*/ if (high_ready_obj == raw_task_active) { USER_CPU_INT_ENABLE(); return; } CONTEXT_SWITCH(); } USER_CPU_INT_ENABLE(); return; } } }
static void task_0_process(void *pa) { TASK_0_EVENT_TYPE ev; RAW_U8 *data_temp; EVENT_HANLDER *receiver; RAW_SR_ALLOC(); pa = pa; /*to prevent interrupt happen here to cause system crash at task 0 start*/ USER_CPU_INT_DISABLE(); remove_ready_list(&raw_ready_queue, &raw_task_0_obj); USER_CPU_INT_ENABLE(); while (1) { /*Get the message info and update it*/ USER_CPU_INT_DISABLE(); if (task_0_events) { --task_0_events; /* There are events that we should deliver. */ ev = task_0_events_queue[task_0_event_end].ev; data_temp = task_0_events_queue[task_0_event_end].event_data; receiver = task_0_events_queue[task_0_event_end].p; task_0_event_end++; if (task_0_event_end == MAX_TASK_EVENT) { task_0_event_end = 0u; } /*lock the scheduler, so event handler can not be switched out*/ raw_sched_lock = 1u; USER_CPU_INT_ENABLE(); /*exceute the event handler*/ receiver->handle_event(ev, data_temp); } else { /*unlock the scheduler, so scheduler can work*/ raw_sched_lock = 0u; get_ready_task(&raw_ready_queue); CONTEXT_SWITCH(); USER_CPU_INT_ENABLE(); } } }