/* * === FUNCTION ====================================================================== * Name: OS_SemPost * Description: This functions release the semaphore and wakes up the task * being blocked on it. A task can be also be waiting for a time event, so this * function vefiries whether the relased task is also waiting for a time event * or not. In case it is, the task is also removed from the time queue. * ===================================================================================== */ int OS_SemPost(OS_SemID_t _sem) { OS_task_t *task; OS_Node_t *n; OS_SemID_t id_sem = _sem; KTRACE_EVENT_SEM(KEVENT_UNLOCK, SEM(id_sem)->sem_id); if(OS_ListGetNum(&(SEM(id_sem)->list)) != 0) { /* Outs the task from the semaphore queue */ n = OS_ListGetNode(&(SEM(id_sem)->list)); task = GET_ELEMENT(OS_task_t, n, resource_node); /* Store what is the blocked thread in the semaphore structure */ SEM(id_sem)->tid_in = task->tid; KTRACE_EVENT_SEM_TID(KEVENT_LOCK_CATCHED, SEM(id_sem)->sem_id, task->tid); /* * Verifies if the thread is blocked in the time queue * due to a TimedWait system call */ if(task->status | TS_TIME_BLOCKED) { OS_TimeRemoveFromQueue(task); } /* Reset the wait_sem value */ task->wait_sem = 0; /* Add the blocked task to the ready task queue */ OS_SchedTaskReady(task->tid); } else { /* Increment the semaphore counter */ SEM(id_sem)->sem_value = 1; OS_ListReset(&(SEM(id_sem)->list)); } return 0; }
/* * Function: tid_t OS_TaskCreate(uint32_t _stack_size, void *_ip, uint8 _priority) * * This routine creates a new thread and returns the TCB created */ tid_t OS_TaskCreate(uint32_t *_stackaddr, uint32_t _stacksize, void *_ip, void *_arg, uint8_t _priority) { OS_task_t *task; OS_Node_t *n; // DEBUG ("(_stackaddr=%p, _stacksize=%p, _ip=%p, _arg=%p, priority=%d)", // _stackaddr, _stacksize, _ip, _arg, _priority); ASSERT (_priority <= SCHED_MIN_PRIORITY); /* get a free thread control block */ n = (OS_Node_t *) OS_ListGetNode (&tcb_list); /* assert that we really have a free tcb */ ASSERT (n != NULL); if (n == NULL) return -1; task = GET_ELEMENT(OS_task_t, n, node); TRACE (task->tid, "d"); KTRACE (KTRACE_CREATE, task->tid, _priority); /* Stablish the thread stack */ if (_stackaddr == NULL) { if (_stacksize < CONFIG_ERCOS_MIN_STACK) _stacksize = CONFIG_ERCOS_MIN_STACK; _stackaddr = OS_Malloc (_stacksize); } else { ASSERT (_stacksize >= CONFIG_ERCOS_MIN_STACK); } task->stack.size = _stacksize; task->stack.addr = (uint8_t *)_stackaddr; /* Fill the stack with the 0x5a mark */ #ifndef CONFIG_NDEBUG // unsigned i; // DEBUG ("Stack @ %p, %p bytes", _stackaddr, _stacksize); // for (i = 0; i < _stacksize; i++) ((uint8_t *) _stackaddr)[i] = 0x5a; #endif /* Init the new thread context */ ercos_hal_hwcontext_init (&(task->context), task->stack.addr, task->stack.size, 0, OS_ThreadWrapper); /* Stablish the thread status */ task->status = TS_READY; /* Stablish the thread entry point */ task->entry_point = _ip; task->arg = _arg; /* Init the pointer to the catched mutex */ task->pmutex =(OS_Mutex_t*) NULL; /* Set the thread base and temporal priorities */ task->priority = _priority; task->base_priority = _priority; /* Add the task to the correspond sched queue */ OS_SchedTaskReady(task->tid); return task->tid; }