/** * Signal g_TimerSem to wake-up timer_task. * */ static void signal_timer_task(void) { #ifdef CONFIG_NANOKERNEL nano_sem_give(&g_TimerSem); #else T_EXEC_LEVEL execLvl; execLvl = _getExecLevel(); /* call the nanoK service that corresponds to the current execution level */ switch (execLvl) { case E_EXEC_LVL_ISR: isr_sem_give(g_TimerSem); break; case E_EXEC_LVL_FIBER: fiber_sem_give(g_TimerSem); break; case E_EXEC_LVL_TASK: task_sem_give(g_TimerSem); break; default: /* will not do that from unknown context */ panic(E_OS_ERR_NOT_SUPPORTED); break; } #endif }
/** * Delete a queue. * * Free a whole queue. * @param queue - The queue to free. */ void queue_delete(T_QUEUE queue, OS_ERR_TYPE* err) { OS_ERR_TYPE _err; queue_impl_t * q = (queue_impl_t*) queue; T_EXEC_LEVEL execLvl = _getExecLevel(); uint32_t data; T_QUEUE_MESSAGE p_msg = &data; /* check execution level */ if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl)) { lock_pool(); if (queue_used(q) && q->sema != NULL) { /* first empty the queue before to delete it to free all the elements */ do{ queue_get_message(q, &p_msg, OS_NO_WAIT, &_err); }while(_err == E_OS_OK); if(_err == E_OS_ERR_EMPTY) { semaphore_delete(q->sema, &_err); q->sema = NULL; if( _err == E_OS_OK) { queue_free(q); error_management (err, E_OS_OK); } else { panic(E_OS_ERR_UNKNOWN); // Panic because we should never reach this point. } } else { error_management (err, E_OS_ERR); } } else { error_management (err, E_OS_ERR); } unlock_pool(); } else { error_management (err, E_OS_ERR_NOT_ALLOWED); } return; }
/** * Read a message from a queue. * * Read and dequeue a message. * This service may panic if err parameter is NULL and: * -# queue parameter is invalid, or * -# message parameter is NULL, or * -# when called from an ISR. * * Authorized execution levels: task, fiber. * * @param queue : handler on the queue (value returned by queue_create). * * @param message (out): pointer to read message. * * @param timeout: maximum number of milliseconds to wait for the message. Special * values OS_NO_WAIT and OS_WAIT_FOREVER may be used. * * @param err (out): execution status: * -# E_OS_OK : a message was read * -# E_OS_ERR_TIMEOUT: no message was received * -# E_OS_ERR_EMPTY: the queue is empty * -# E_OS_ERR: invalid parameter * -# E_OS_ERR_NOT_ALLOWED: service cannot be executed from ISR context. */ void queue_get_message (T_QUEUE queue, T_QUEUE_MESSAGE* message, int timeout, OS_ERR_TYPE* err) { OS_ERR_TYPE _err; T_EXEC_LEVEL execLvl = _getExecLevel(); queue_impl_t * q = (queue_impl_t*) queue; /* check input parameters */ if( (message == NULL) || (!queue_used(q)) || (q->sema==NULL) || (timeout<OS_WAIT_FOREVER) ) { error_management (err, E_OS_ERR); return; } /* check execution level */ if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl)) { _err = semaphore_take(q->sema, timeout); switch(_err){ case E_OS_OK: { uint32_t it_mask = interrupt_lock(); _err = remove_data(q, message); interrupt_unlock(it_mask); error_management (err, E_OS_OK); } break; case E_OS_ERR_TIMEOUT: error_management (err, E_OS_ERR_TIMEOUT); break; case E_OS_ERR_BUSY: if(err){ //QUEUE EMPTY, is a common use case, do not panic even if err == NULL *err = E_OS_ERR_EMPTY; } break; default: //unknown error panic(E_OS_ERR_UNKNOWN); } } else { error_management (err, E_OS_ERR_NOT_ALLOWED); } return; }
/** * Create a message queue. * * Create a message queue. * This service may panic if err parameter is NULL and: * -# no queue is available, or * -# when called from an ISR. * * Authorized execution levels: task, fiber. * * As for semaphores and mutexes, queues are picked from a pool of * statically-allocated objects. * * @param maxSize: maximum number of messages in the queue. * (Rationale: queues only contain pointer to messages) * * @param err (out): execution status: * -# E_OS_OK : queue was created * -# E_OS_ERR: all queues from the pool are already being used * -# E_OS_ERR_NOT_ALLOWED: service cannot be executed from ISR context. * * @return Handler on the created queue. * NULL if all allocated queues are already being used. */ T_QUEUE queue_create(uint32_t max_size, OS_ERR_TYPE* err) { queue_impl_t * q = NULL; T_EXEC_LEVEL execLvl = _getExecLevel(); OS_ERR_TYPE _err; if(max_size==0 || max_size>QUEUE_ELEMENT_POOL_SIZE) { error_management (err, E_OS_ERR); return NULL; } /* check execution level */ if ((E_EXEC_LVL_FIBER == execLvl) || (E_EXEC_LVL_TASK == execLvl)) { /* Block concurrent accesses to the pool of queue_list */ lock_pool(); q = queue_alloc(); unlock_pool(); if (q != NULL) { list_init(&q->_list); // replace the following commented code q->current_size = 0; q->max_size = max_size; q->sema = semaphore_create(0, &_err); error_management (err, _err); } else { error_management (err, E_OS_ERR); } } else { error_management (err, E_OS_ERR_NOT_ALLOWED); } return (T_QUEUE)q; }