/*! * \brief Tests the event component for validity and consistency. * * \param[out] event_error_ptr Pointer to the lightweight event that has an * error if MQX found an error in the lightweight event component (NULL if no error * is found). * \param[out] td_error_ptr TD on the lightweight event in error (NULL if no * error is found). * * \return MQX_OK * \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.) * \return MQX_LWEVENT_INVALID (A lightweight event was invalid.) * \return code from _queue_test() (Waiting queue for a lightweight event has an error.) * * \warning Cannot be called from an ISR. * * \see _lwevent_create * \see _lwevent_destroy */ _mqx_uint _lwevent_test ( void **event_error_ptr, void **td_error_ptr ) { KERNEL_DATA_STRUCT_PTR kernel_data; LWEVENT_STRUCT_PTR event_ptr; _mqx_uint result; _mqx_uint queue_size; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_lwevent_test, event_error_ptr); *td_error_ptr = NULL; *event_error_ptr = NULL; #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwevent_test, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return (MQX_CANNOT_CALL_FUNCTION_FROM_ISR); }/* Endif */ #endif /* * It is not considered an error if the lwevent component has not been * created yet */ if (kernel_data->LWEVENTS.NEXT == NULL) { return (MQX_OK); } /* Endif */ result = _queue_test((QUEUE_STRUCT_PTR) &kernel_data->LWEVENTS, event_error_ptr); if (result != MQX_OK) { _KLOGX3(KLOG_lwevent_test, result, *event_error_ptr); return (result); } /* Endif */ event_ptr = (LWEVENT_STRUCT_PTR) ((void *) kernel_data->LWEVENTS.NEXT); queue_size = _QUEUE_GET_SIZE(&kernel_data->LWEVENTS); while (queue_size--) { if (event_ptr->VALID != LWEVENT_VALID) { result = MQX_LWEVENT_INVALID; break; } /* Endif */ result = _queue_test(&event_ptr->WAITING_TASKS, td_error_ptr); if (result != MQX_OK) { break; } /* Endif */ event_ptr = (LWEVENT_STRUCT_PTR) (void *) event_ptr->LINK.NEXT; } /* Endwhile */ _int_enable(); if (result != MQX_OK) { *event_error_ptr = (void *) event_ptr; } /* Endif */ _KLOGX4(KLOG_lwevent_test, result, *event_error_ptr, *td_error_ptr); return (result); }
/*! * \brief Tests all the periodic queues and their lightweight timers for * validity and consistency. * * \param[out] period_error_ptr Pointer to the first periodic queue that has * an error (NULL if no error is found). * \param[out] timer_error_ptr Pointer to the first timer that has an error * (NULL if no error is found). * * \return MQX_OK (No periodic queues have been created or no errors found * in any periodic queues or timers.) * \return MQX_LWTIMER_INVALID (Period_ptr points to an invalid periodic queue.) * \return Error from _queue_test() (A periodic queue or its queue was in error.) * * \warning Disables and enables interrupts. * * \see _lwtimer_add_timer_to_queue * \see _lwtimer_cancel_period * \see _lwtimer_cancel_timer * \see _lwtimer_create_periodic_queue */ _mqx_uint _lwtimer_test ( pointer _PTR_ period_error_ptr, pointer _PTR_ timer_error_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; LWTIMER_STRUCT_PTR timer_ptr; LWTIMER_PERIOD_STRUCT_PTR period_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwtimer_test, period_error_ptr, timer_error_ptr); *period_error_ptr = NULL; *timer_error_ptr = NULL; /* * It is not considered an error if the lwtimer component has not been * created yet */ if (kernel_data->LWTIMERS.NEXT == NULL) { return (MQX_OK); } /* Endif */ result = _queue_test(&kernel_data->LWTIMERS, period_error_ptr); if (result != MQX_OK) { _KLOGX3(KLOG_lwtimer_test, result, *period_error_ptr); return (result); } /* Endif */ _int_disable(); period_ptr = (pointer) kernel_data->LWTIMERS.NEXT; while ((pointer) period_ptr != (pointer) &kernel_data->LWTIMERS) { if (period_ptr->VALID != LWTIMER_VALID) { _int_enable(); *period_error_ptr = period_ptr; _KLOGX3(KLOG_lwtimer_test, MQX_LWTIMER_INVALID, period_ptr); return (MQX_LWTIMER_INVALID); } /* Endif */ result = _queue_test(&period_ptr->TIMERS, timer_error_ptr); if (result != MQX_OK) { _int_enable(); *period_error_ptr = period_ptr; _KLOGX4(KLOG_lwtimer_test, result, *period_error_ptr, *timer_error_ptr); return (result); } /* Endif */ timer_ptr = (pointer) period_ptr->TIMERS.NEXT; while (timer_ptr != (pointer) &period_ptr->TIMERS) { if (timer_ptr->VALID != LWTIMER_VALID) { *period_error_ptr = period_ptr; *timer_error_ptr = timer_ptr; _KLOGX4(KLOG_lwtimer_test, MQX_LWTIMER_INVALID, period_ptr, timer_ptr); return (MQX_LWTIMER_INVALID); } /* Endif */ timer_ptr = (pointer) timer_ptr->LINK.NEXT; } /* Endwhile */ period_ptr = (pointer) period_ptr->LINK.NEXT; } /* Endwhile */ _int_enable(); _KLOGX2(KLOG_lwtimer_test, MQX_OK); return (MQX_OK); } /* Endbody */
/*! * \cond DOXYGEN_PRIVATE * \private * * \brief Used by a task to create an instance of a lightweight event. * * \param[in] event_ptr Pointer representing location of the event. * \param[in] flags Flags for the light weight event. * \param[in] user User mode * * \return MQX_OK * \return MQX_EINVAL (lwevent is already initialized.) * \return MQX_LWEVENT_INVALID (In case of user mode, MQX tries to access * a lwevent with inappropriate access rights.) * * \see _lwevent_create * \see LWEVENT_STRUCT */ _mqx_uint _lwevent_create_internal ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint flags, bool user ) { KERNEL_DATA_STRUCT_PTR kernel_data; LWEVENT_STRUCT_PTR event_chk_ptr; #if MQX_ENABLE_USER_MODE if (user && !_psp_mem_check_access_mask((uint32_t)event_ptr, sizeof(LWEVENT_STRUCT), MPU_UM_R, MPU_UM_RW) ) { return MQX_LWEVENT_INVALID; } #endif _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_lwevent_create, event_ptr); _QUEUE_INIT(&event_ptr->WAITING_TASKS, 0); event_ptr->VALUE = 0; event_ptr->FLAGS = flags; if (flags & LWEVENT_AUTO_CLEAR) event_ptr->AUTO = ~0; else event_ptr->AUTO = 0; _int_disable(); #if MQX_ENABLE_USER_MODE if (user) { if (kernel_data->USR_LWEVENTS.NEXT == NULL) { /* Initialize the light weight event queue */ _QUEUE_INIT(&kernel_data->USR_LWEVENTS, 0); } } else #endif { if (kernel_data->LWEVENTS.NEXT == NULL) { /* Initialize the light weight event queue */ _QUEUE_INIT(&kernel_data->LWEVENTS, 0); } } event_ptr->VALID = LWEVENT_VALID; #if MQX_CHECK_ERRORS /* Check if lwevent is already initialized */ #if MQX_ENABLE_USER_MODE if (user) { event_chk_ptr = (LWEVENT_STRUCT_PTR)((void *)kernel_data->USR_LWEVENTS.NEXT); while (event_chk_ptr != (LWEVENT_STRUCT_PTR)((void *)&kernel_data->USR_LWEVENTS)) { if (event_chk_ptr == event_ptr) { _int_enable(); _KLOGX2(KLOG_lwevent_create, MQX_EINVAL); return(MQX_EINVAL); } event_chk_ptr = (LWEVENT_STRUCT_PTR)((void *)event_chk_ptr->LINK.NEXT); } } else #endif { event_chk_ptr = (LWEVENT_STRUCT_PTR) ((void *) kernel_data->LWEVENTS.NEXT); while (event_chk_ptr != (LWEVENT_STRUCT_PTR) ((void *) &kernel_data->LWEVENTS)) { if (event_chk_ptr == event_ptr) { _int_enable(); _KLOGX2(KLOG_lwevent_create, MQX_EINVAL); return (MQX_EINVAL); } event_chk_ptr = (LWEVENT_STRUCT_PTR) ((void *) event_chk_ptr->LINK.NEXT); } } #endif #if MQX_ENABLE_USER_MODE if (user) { _QUEUE_ENQUEUE(&kernel_data->USR_LWEVENTS, &event_ptr->LINK); } else #endif { _QUEUE_ENQUEUE(&kernel_data->LWEVENTS, &event_ptr->LINK); } _int_enable(); _KLOGX2(KLOG_lwevent_create, MQX_OK); return (MQX_OK); }
/*! * \brief Used by a task to set the specified event bits in an event. * * \param[in] event_ptr Pointer to the lightweight event to set bits in. * \param[in] bit_mask Bit mask. Each bit represents an event bit to be set. * * \return MQX_OK * \return MQX_LWEVENT_INVALID (Lightweight event was invalid.) * * \see _lwevent_create * \see _lwevent_destroy * \see _lwevent_set_auto_clear * \see _lwevent_clear * \see _lwevent_test * \see _lwevent_wait_for * \see _lwevent_wait_ticks * \see _lwevent_wait_until * \see _lwevent_get_signalled * \see LWEVENT_STRUCT */ _mqx_uint _lwevent_set ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint bit_mask ) { KERNEL_DATA_STRUCT_PTR kernel_data; QUEUE_ELEMENT_STRUCT_PTR q_ptr; QUEUE_ELEMENT_STRUCT_PTR next_q_ptr; TD_STRUCT_PTR td_ptr; _mqx_uint set_bits; #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwevent_set(event_ptr, bit_mask); } #endif _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwevent_set, event_ptr, bit_mask); _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); _KLOGX2(KLOG_lwevent_set, MQX_LWEVENT_INVALID); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif set_bits = event_ptr->VALUE | bit_mask; if (_QUEUE_GET_SIZE(&event_ptr->WAITING_TASKS)) { /* Schedule waiting task(s) to run if bits ok */ q_ptr = event_ptr->WAITING_TASKS.NEXT; while (q_ptr != (QUEUE_ELEMENT_STRUCT_PTR) ((void *) &event_ptr->WAITING_TASKS)) { td_ptr = (void *) q_ptr; _BACKUP_POINTER(td_ptr, TD_STRUCT, AUX_QUEUE); next_q_ptr = q_ptr->NEXT; if (((td_ptr->FLAGS & TASK_LWEVENT_ALL_BITS_WANTED) && ((td_ptr->LWEVENT_BITS & set_bits) == td_ptr->LWEVENT_BITS)) || ((!(td_ptr->FLAGS & TASK_LWEVENT_ALL_BITS_WANTED)) && (td_ptr->LWEVENT_BITS & set_bits))) { _QUEUE_REMOVE(&event_ptr->WAITING_TASKS, q_ptr); _TIME_DEQUEUE(td_ptr, kernel_data); td_ptr->INFO = 0; _TASK_READY(td_ptr, kernel_data); /* store information about which bits caused task to be unblocked */ td_ptr->LWEVENT_BITS &= set_bits; set_bits &= ~(event_ptr->AUTO & td_ptr->LWEVENT_BITS); } /* Endif */ q_ptr = next_q_ptr; } /* Endwhile */ } /* Endif */ event_ptr->VALUE = set_bits; _INT_ENABLE(); /* May need to let higher priority task run */ _CHECK_RUN_SCHEDULER(); _KLOGX2(KLOG_lwevent_set, MQX_OK); return (MQX_OK); }
_mqx_uint _watchdog_create_component ( /* [IN] the vector upon which timer interrupts on */ _mqx_uint timer_interrupt_vector, /* [IN] the function to call when a watchdog timer expires */ void (_CODE_PTR_ error_function)(pointer td_ptr) ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; WATCHDOG_COMPONENT_STRUCT_PTR watchdog_component_ptr; pointer interrupt_data; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_watchdog_create_component, timer_interrupt_vector, error_function); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_watchdog_create_component, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif _lwsem_wait((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); if (kernel_data->KERNEL_COMPONENTS[KERNEL_WATCHDOG] != NULL) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_watchdog_create_component, MQX_OK); return(MQX_OK); } /* Endif */ #if MQX_CHECK_ERRORS if (!error_function) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_watchdog_create_component, WATCHDOG_INVALID_ERROR_FUNCTION); return(WATCHDOG_INVALID_ERROR_FUNCTION); } /* Endif */ if ((timer_interrupt_vector < kernel_data->FIRST_USER_ISR_VECTOR) || (timer_interrupt_vector > kernel_data->LAST_USER_ISR_VECTOR)) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_watchdog_create_component, WATCHDOG_INVALID_INTERRUPT_VECTOR); return(WATCHDOG_INVALID_INTERRUPT_VECTOR); } /* Endif */ #endif /* Get the watchdog component data structure */ watchdog_component_ptr = (WATCHDOG_COMPONENT_STRUCT_PTR) _mem_alloc_system_zero((_mem_size)sizeof(WATCHDOG_COMPONENT_STRUCT)); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (watchdog_component_ptr == NULL){ _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_watchdog_create_component, MQX_OUT_OF_MEMORY); return(MQX_OUT_OF_MEMORY); } /* Endif */ #endif _mem_set_type(watchdog_component_ptr, MEM_TYPE_WATCHDOG_COMPONENT); watchdog_component_ptr->ERROR_FUNCTION = (void (_CODE_PTR_)(TD_STRUCT_PTR))error_function; watchdog_component_ptr->VALID = WATCHDOG_VALID; watchdog_component_ptr->INTERRUPT_VECTOR = timer_interrupt_vector; interrupt_data = _int_get_isr_data(timer_interrupt_vector); _INT_DISABLE(); watchdog_component_ptr->TIMER_INTERRUPT_HANDLER = _int_install_isr( timer_interrupt_vector, _watchdog_isr, interrupt_data); #if MQX_CHECK_ERRORS if (!watchdog_component_ptr->TIMER_INTERRUPT_HANDLER) { _int_enable(); _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _mem_free(watchdog_component_ptr); _KLOGX2(KLOG_watchdog_create_component, WATCHDOG_INVALID_INTERRUPT_VECTOR); return(WATCHDOG_INVALID_INTERRUPT_VECTOR); } /* Endif */ #endif kernel_data->KERNEL_COMPONENTS[KERNEL_WATCHDOG] = watchdog_component_ptr; #if MQX_TASK_DESTRUCTION kernel_data->COMPONENT_CLEANUP[KERNEL_WATCHDOG] = _watchdog_cleanup; #endif _INT_ENABLE(); _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_watchdog_create_component, MQX_OK); return(MQX_OK); } /* Endbody */
/*! * \cond DOXYGEN_PRIVATE * \private * * \brief Used by a task to destroy an instance of a lightweight event. * * \param[in] event_ptr Pointer to the lightweight event to be deinitialized. * \param[in] user User mode * * \return MQX_OK * \return MQX_LWEVENT_INVALID (Lightweight event was not valid.) * \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.) * * \see _lwevent_destroy * \see LWEVENT_STRUCT */ _mqx_uint _lwevent_destroy_internal ( LWEVENT_STRUCT_PTR event_ptr, bool user ) { KERNEL_DATA_STRUCT_PTR kernel_data; #if MQX_COMPONENT_DESTRUCTION TD_STRUCT_PTR td_ptr; #endif #if MQX_ENABLE_USER_MODE if (user && !_psp_mem_check_access_mask((uint32_t)event_ptr, sizeof(LWEVENT_STRUCT), MPU_UM_R, MPU_UM_RW)) { return MQX_LWEVENT_INVALID; } #endif _GET_KERNEL_DATA(kernel_data); /* Avoid warning for kernel_data in release targets combinated with lite configuration */ (void)kernel_data; _KLOGE2(KLOG_lwevent_destroy, event_ptr); #if MQX_COMPONENT_DESTRUCTION #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwevent_destroy, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return (MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif _int_disable(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); _KLOGX2(KLOG_lwevent_destroy, MQX_LWEVENT_INVALID); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif /* Effectively stop all access to the event */ event_ptr->VALID = 0; while (_QUEUE_GET_SIZE(&event_ptr->WAITING_TASKS)) { _QUEUE_DEQUEUE(&event_ptr->WAITING_TASKS, td_ptr); _BACKUP_POINTER(td_ptr, TD_STRUCT, AUX_QUEUE); _TIME_DEQUEUE(td_ptr, kernel_data); _TASK_READY(td_ptr, kernel_data); } /* Endwhile */ /* remove event from kernel LWEVENTS queue */ #if MQX_ENABLE_USER_MODE if (user) { _QUEUE_REMOVE(&kernel_data->USR_LWEVENTS, event_ptr); } else #endif { _QUEUE_REMOVE(&kernel_data->LWEVENTS, event_ptr); } _int_enable(); /* May need to let higher priority task run */ _CHECK_RUN_SCHEDULER(); #endif _KLOGX2(KLOG_lwevent_destroy, MQX_OK); return (MQX_OK); }
_mqx_uint _lwsem_wait ( /* [IN] the semaphore address */ LWSEM_STRUCT_PTR sem_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwsem_wait(sem_ptr); } #endif _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_lwsem_wait, sem_ptr); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwsem_wait, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } #endif #if MQX_CHECK_VALIDITY if (sem_ptr->VALID != LWSEM_VALID) { _KLOGX2(KLOG_lwsem_wait, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } #endif _INT_DISABLE(); if (sem_ptr->VALUE <= 0) { td_ptr = kernel_data->ACTIVE_PTR; td_ptr->STATE = LWSEM_BLOCKED; td_ptr->INFO = (_mqx_uint)&sem_ptr->TD_QUEUE; _QUEUE_UNLINK(td_ptr); _QUEUE_ENQUEUE(&sem_ptr->TD_QUEUE, &td_ptr->AUX_QUEUE); _sched_execute_scheduler_internal(); /* Let the other tasks run */ /* Another task has posted a semaphore, and it has been tranfered to this ** task. */ } else { --sem_ptr->VALUE; } //#if MQX_COMPONENT_DESTRUCTION /* We must check for component destruction */ if (sem_ptr->VALID != LWSEM_VALID) { _int_enable(); /* The semaphore has been deleted */ _KLOGX2(KLOG_lwsem_wait, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ //#endif _INT_ENABLE(); _KLOGX2(KLOG_lwsem_wait, MQX_OK); return(MQX_OK); }
_mqx_uint _taskq_suspend_task ( /* [IN] the task to suspend */ _task_id task_id, /* [IN] the task queue handle */ pointer users_task_queue_ptr ) { /* Body */ register KERNEL_DATA_STRUCT_PTR kernel_data; register TASK_QUEUE_STRUCT_PTR task_queue_ptr = (TASK_QUEUE_STRUCT_PTR)users_task_queue_ptr; register TD_STRUCT_PTR td_ptr; boolean me; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_taskq_suspend_task, task_id, users_task_queue_ptr); td_ptr = (TD_STRUCT_PTR)_task_get_td(task_id); me = (td_ptr == kernel_data->ACTIVE_PTR); #if MQX_CHECK_ERRORS if (td_ptr == NULL) { _KLOGX2(KLOG_taskq_suspend_task, MQX_INVALID_TASK_ID); return(MQX_INVALID_TASK_ID); } /* Endif */ if (task_queue_ptr == NULL){ _KLOGX2(KLOG_taskq_suspend_task, MQX_INVALID_PARAMETER); return(MQX_INVALID_PARAMETER); } /* Endif */ if (me && kernel_data->IN_ISR) { _KLOGX2(KLOG_taskq_suspend_task, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); }/* Endif */ #endif _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (task_queue_ptr->VALID != TASK_QUEUE_VALID) { _int_enable(); _KLOGX2(KLOG_taskq_suspend_task, MQX_INVALID_TASK_QUEUE); return(MQX_INVALID_TASK_QUEUE); } /* Endif */ #endif if (td_ptr->STATE != READY) { _INT_ENABLE(); _KLOGX2(KLOG_taskq_suspend_task, MQX_INVALID_TASK_STATE); return(MQX_INVALID_TASK_STATE); } /* Endif */ td_ptr->STATE = TASK_QUEUE_BLOCKED; _QUEUE_UNLINK(td_ptr); /* Remove task from ready to run queue */ td_ptr->INFO = (_mqx_uint)&task_queue_ptr->TD_QUEUE; if (task_queue_ptr->POLICY & MQX_TASK_QUEUE_BY_PRIORITY) { _sched_insert_priorityq_internal(&task_queue_ptr->TD_QUEUE, td_ptr); } else { _QUEUE_ENQUEUE(&task_queue_ptr->TD_QUEUE, td_ptr); } /* Endif */ if (me && (kernel_data->IN_ISR == 0)) { _sched_execute_scheduler_internal(); /* Let the other tasks run */ } /* Endif */ _INT_ENABLE(); _KLOGX2(KLOG_taskq_suspend_task, MQX_OK); return( MQX_OK ); } /* Endbody */
_mqx_uint _mutex_test ( /* [OUT] - the mutex in error */ pointer _PTR_ mutex_error_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MUTEX_COMPONENT_STRUCT_PTR mutex_component_ptr; MUTEX_STRUCT_PTR mutex_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_mutex_test, mutex_error_ptr); *mutex_error_ptr = NULL; mutex_component_ptr = (MUTEX_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_MUTEXES]; if (mutex_component_ptr == NULL) { _KLOGX2(KLOG_mutex_test, MQX_OK); return(MQX_OK); } /* Endif */ if (mutex_component_ptr->VALID != MUTEX_VALID) { _KLOGX2(KLOG_mutex_test, MQX_INVALID_COMPONENT_BASE); return(MQX_INVALID_COMPONENT_BASE); } /* Endif */ _int_disable(); /* Make sure that the queue of mutexes is ok */ result = _queue_test(&mutex_component_ptr->MUTEXES, mutex_error_ptr); if (result != MQX_OK) { _int_enable(); _KLOGX3(KLOG_mutex_test, result, *mutex_error_ptr); return(result); } /* Endif */ mutex_ptr = (MUTEX_STRUCT_PTR)((pointer)mutex_component_ptr->MUTEXES.NEXT); while (mutex_ptr != (MUTEX_STRUCT_PTR) ((pointer)&mutex_component_ptr->MUTEXES)) { if (mutex_ptr->VALID != MUTEX_VALID) { _int_enable(); *mutex_error_ptr = mutex_ptr; _KLOGX3(KLOG_mutex_test, MQX_EINVAL, mutex_ptr); return(MQX_EINVAL); } /* Endif */ result = _queue_test(&mutex_ptr->WAITING_TASKS, mutex_error_ptr); if (result != MQX_OK) { _int_enable(); *mutex_error_ptr = mutex_ptr; _KLOGX3(KLOG_mutex_test, result, mutex_ptr); return(result); } /* Endif */ mutex_ptr = (MUTEX_STRUCT_PTR)((pointer)mutex_ptr->LINK.NEXT); } /* Endif */ _int_enable(); _KLOGX2(KLOG_mutex_test, MQX_OK); return(MQX_OK); } /* Endbody */
_mqx_uint _timer_cancel ( /* [IN] id of the alarm to be cancelled */ _timer_id id ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TIMER_COMPONENT_STRUCT_PTR timer_component_ptr; TIMER_ENTRY_STRUCT_PTR timer_entry_ptr; QUEUE_STRUCT_PTR queue_ptr; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_timer_cancel, id); timer_component_ptr = kernel_data->KERNEL_COMPONENTS[KERNEL_TIMER]; #if MQX_CHECK_ERRORS if (timer_component_ptr == NULL) { _KLOGX2(KLOG_timer_cancel, MQX_COMPONENT_DOES_NOT_EXIST); return MQX_COMPONENT_DOES_NOT_EXIST; } /* Endif */ #endif #if MQX_CHECK_VALIDITY if (timer_component_ptr->VALID != TIMER_VALID) { _KLOGX2(KLOG_timer_cancel, MQX_INVALID_COMPONENT_BASE); return MQX_INVALID_COMPONENT_BASE; } /* Endif */ #endif #if MQX_CHECK_ERRORS if (id == 0) { _KLOGX2(KLOG_timer_cancel, MQX_INVALID_PARAMETER); return MQX_INVALID_PARAMETER; } /* Endif */ if (kernel_data->IN_ISR) { _KLOGX2(KLOG_timer_cancel, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return MQX_CANNOT_CALL_FUNCTION_FROM_ISR; } /* Endif */ #endif /* Gain exclusive access to the timer queues */ /* Start CR 1332 */ if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR) { if (_lwsem_wait(&timer_component_ptr->TIMER_ENTRIES_LWSEM) != MQX_OK) { _KLOGX2(KLOG_timer_cancel, MQX_INVALID_LWSEM); return(MQX_INVALID_LWSEM); } /* Endif */ } /*Endif */ timer_entry_ptr = _timer_find_entry_internal(timer_component_ptr, id); /* End CR 1332 */ if ((timer_entry_ptr == NULL) || (timer_entry_ptr->VALID != TIMER_VALID)) { if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR) { _lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM); } /* Endif */ _KLOGX2(KLOG_timer_cancel, MQX_INVALID_PARAMETER); return MQX_INVALID_PARAMETER; } /* Endif */ if (timer_entry_ptr->MODE == TIMER_ELAPSED_TIME_MODE) { queue_ptr = &timer_component_ptr->ELAPSED_TIMER_ENTRIES; } else { queue_ptr = &timer_component_ptr->KERNEL_TIMER_ENTRIES; } /* Endif */ timer_entry_ptr->VALID = 0; timer_entry_ptr->ID = 0; if (kernel_data->ACTIVE_PTR != timer_component_ptr->TIMER_TD_PTR) { _QUEUE_REMOVE(queue_ptr, timer_entry_ptr); _mem_free(timer_entry_ptr); _lwsem_post(&timer_component_ptr->TIMER_ENTRIES_LWSEM); } /* Endif */ _KLOGX2(KLOG_timer_cancel, MQX_OK); return(MQX_OK); } /* Endbody */
_mqx_uint _event_create_component ( /* [IN] the initial number of event */ _mqx_uint initial_number, /* ** [IN] the number of events to add when ** space is no longer available */ _mqx_uint grow_number, /* [IN] the maximum number of events allowed */ _mqx_uint maximum_number ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; register EVENT_COMPONENT_STRUCT_PTR event_component_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE4(KLOG_event_create_component, initial_number, grow_number, maximum_number); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_event_create_component, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif _lwsem_wait((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); event_component_ptr = (EVENT_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_EVENTS]; if (event_component_ptr != NULL) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_event_create_component, MQX_OK); return(MQX_OK); } /* Endif */ event_component_ptr = (EVENT_COMPONENT_STRUCT_PTR) _mem_alloc_system_zero((_mem_size)sizeof(EVENT_COMPONENT_STRUCT)); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (event_component_ptr == NULL) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_event_create_component, MQX_OUT_OF_MEMORY); return(MQX_OUT_OF_MEMORY); } /* Endif */ #endif _mem_set_type(event_component_ptr, MEM_TYPE_EVENT_COMPONENT); result = _name_create_handle_internal(&event_component_ptr->NAME_TABLE_HANDLE, initial_number, grow_number, maximum_number, initial_number); #if MQX_CHECK_ERRORS if (result != MQX_OK) { _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _mem_free(event_component_ptr); _KLOGX2(KLOG_event_create_component, result); return(result); } /* Endif */ #endif event_component_ptr->VALID = EVENT_VALID; event_component_ptr->GROW_NUMBER = grow_number; if (maximum_number == 0) { event_component_ptr->MAXIMUM_NUMBER = MAX_MQX_UINT; } else if (maximum_number < initial_number) { event_component_ptr->MAXIMUM_NUMBER = initial_number; } else { event_component_ptr->MAXIMUM_NUMBER = maximum_number; } /* Endif */ kernel_data->KERNEL_COMPONENTS[KERNEL_EVENTS] = event_component_ptr; #if MQX_TASK_DESTRUCTION kernel_data->COMPONENT_CLEANUP[KERNEL_EVENTS] = _event_cleanup; #endif _lwsem_post((LWSEM_STRUCT_PTR)(&kernel_data->COMPONENT_CREATE_LWSEM)); _KLOGX2(KLOG_event_create_component, MQX_OK); return(MQX_OK); } /* Endbody */
_mqx_uint _lwsem_test ( /* [OUT] the light weight semapohre in error */ pointer _PTR_ lwsem_error_ptr, /* [OUT] the td on a light weight semaphore in error */ pointer _PTR_ td_error_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; LWSEM_STRUCT_PTR sem_ptr; _mqx_uint queue_size; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE3(KLOG_lwsem_test, lwsem_error_ptr, td_error_ptr); *td_error_ptr = NULL; *lwsem_error_ptr = NULL; #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwsem_test, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); }/* Endif */ #endif _int_disable(); result = _queue_test((QUEUE_STRUCT_PTR)&kernel_data->LWSEM, lwsem_error_ptr); if (result != MQX_OK) { _KLOGX3(KLOG_lwsem_test, result, *lwsem_error_ptr); return(result); } /* Endif */ sem_ptr = (LWSEM_STRUCT_PTR)((pointer)kernel_data->LWSEM.NEXT); queue_size = _QUEUE_GET_SIZE(&kernel_data->LWSEM); while (queue_size--) { if (sem_ptr->VALID != LWSEM_VALID) { result = MQX_INVALID_LWSEM; break; } /* Endif */ result = _queue_test(&sem_ptr->TD_QUEUE, td_error_ptr); if (result != MQX_OK) { break; } /* Endif */ sem_ptr = sem_ptr->NEXT; } /* Endwhile */ _int_enable(); if (result != MQX_OK) { *lwsem_error_ptr = (pointer)sem_ptr; } /* Endif */ _KLOGX4(KLOG_lwsem_test, result, *lwsem_error_ptr, *td_error_ptr); return(result); }
_mqx_uint _event_create_internal ( /* [IN] the string name for the event */ char _PTR_ name_ptr, /* [OUT] where the event pointer is */ EVENT_STRUCT_PTR _PTR_ event_ptr_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; register EVENT_COMPONENT_STRUCT_PTR event_component_ptr; register EVENT_STRUCT_PTR event_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_event_create, name_ptr); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_event_create, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif event_component_ptr = (EVENT_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_EVENTS]; if (event_component_ptr == NULL) { result = _event_create_component(EVENT_DEFAULT_INITIAL_NUMBER, EVENT_DEFAULT_GROW_NUMBER, EVENT_DEFAULT_MAXIMUM_NUMBER); event_component_ptr = (EVENT_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_EVENTS]; #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (event_component_ptr == NULL){ _KLOGX2(KLOG_event_create, result); return(result); } /* Endif */ #endif } /* Endif */ #if MQX_CHECK_VALIDITY if (event_component_ptr->VALID != EVENT_VALID){ _KLOGX2(KLOG_event_create, MQX_INVALID_COMPONENT_BASE); return(MQX_INVALID_COMPONENT_BASE); } /* Endif */ #endif event_ptr = (EVENT_STRUCT_PTR)_mem_alloc_system_zero( (_mem_size)sizeof(EVENT_STRUCT)); #if MQX_CHECK_MEMORY_ALLOCATION_ERRORS if (event_ptr == NULL) { _KLOGX2(KLOG_event_create, MQX_OUT_OF_MEMORY); return(MQX_OUT_OF_MEMORY); } /* Endif */ #endif _mem_set_type(event_ptr, MEM_TYPE_EVENT); _QUEUE_INIT(&event_ptr->WAITING_TASKS, EVENT_MAX_WAITING_TASKS); strncpy(event_ptr->NAME, name_ptr, (_mqx_uint)NAME_MAX_NAME_SIZE-1); event_ptr->NAME[NAME_MAX_NAME_SIZE-1] = '\0'; result = _name_add_internal(event_component_ptr->NAME_TABLE_HANDLE, event_ptr->NAME, (_mqx_uint)event_ptr); #if MQX_CHECK_ERRORS if (result != MQX_OK) { _mem_free(event_ptr); if (result == NAME_EXISTS) { _KLOGX2(KLOG_event_create, EVENT_EXISTS); return(EVENT_EXISTS); } else if (result == NAME_TABLE_FULL) { _KLOGX2(KLOG_event_create, EVENT_TABLE_FULL); return(EVENT_TABLE_FULL); } /* Endif */ _KLOGX2(KLOG_event_create, result); return(result); } /* Endif */ #endif event_ptr->VALID = EVENT_VALID; *event_ptr_ptr = event_ptr; _KLOGX2(KLOG_event_create, result); return(result); } /* Endbody */
_mqx_uint _lwmsgq_send ( /* Handle to the queue */ pointer handle, /* location of message to copy in */ _mqx_max_type_ptr message, /* flags for blocking on full, blocking on send */ _mqx_uint flags ) {/* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; LWMSGQ_STRUCT_PTR q_ptr = (LWMSGQ_STRUCT_PTR)handle; _mqx_uint i; _mqx_max_type_ptr from_ptr; _mqx_max_type_ptr to_ptr; #if MQX_ENABLE_USER_MODE && MQX_ENABLE_USER_STDAPI if (MQX_RUN_IN_USER_MODE) { return _usr_lwmsgq_send(handle, message, flags); } #endif /* Start CR 1944 */ _GET_KERNEL_DATA(kernel_data); _KLOGE4(KLOG_lwmsgq_send, handle, message, flags); /* End CR 1944 */ _int_disable(); #if MQX_CHECK_VALIDITY if (q_ptr->VALID != LWMSGQ_VALID){ _int_enable(); /* Start CR 1944 */ _KLOGX2(KLOG_lwmsgq_send, LWMSGQ_INVALID); /* End CR 1944 */ return LWMSGQ_INVALID; } /* Endif */ #endif if (LWMSGQ_IS_FULL(q_ptr)) { if (flags & LWMSGQ_SEND_BLOCK_ON_FULL) { td_ptr = kernel_data->ACTIVE_PTR; while (LWMSGQ_IS_FULL(q_ptr)) { td_ptr->STATE = LWMSGQ_WRITE_BLOCKED; td_ptr->INFO = (_mqx_uint)&q_ptr->WAITING_WRITERS; _QUEUE_UNLINK(td_ptr); _QUEUE_ENQUEUE(&q_ptr->WAITING_WRITERS, &td_ptr->AUX_QUEUE); _sched_execute_scheduler_internal(); /* Let other tasks run */ } /* Endwhile */ } else { _int_enable(); /* Start CR 1944 */ _KLOGX2(KLOG_lwmsgq_send, LWMSGQ_FULL); /* End CR 1944 */ return LWMSGQ_FULL; } /* Endif */ }/* Endif */ to_ptr = q_ptr->MSG_WRITE_LOC; from_ptr = message; i = q_ptr->MSG_SIZE+1; while (--i) { *to_ptr++ = *from_ptr++; } /* Endwhile */ q_ptr->MSG_WRITE_LOC += q_ptr->MSG_SIZE; if (q_ptr->MSG_WRITE_LOC >= q_ptr->MSG_END_LOC) { q_ptr->MSG_WRITE_LOC = q_ptr->MSG_START_LOC; } /* Endif */ q_ptr->CURRENT_SIZE++; if (! _QUEUE_IS_EMPTY(&q_ptr->WAITING_READERS)) { _QUEUE_DEQUEUE(&q_ptr->WAITING_READERS, td_ptr); _BACKUP_POINTER(td_ptr, TD_STRUCT, AUX_QUEUE); _TIME_DEQUEUE(td_ptr, kernel_data); td_ptr->INFO = 0; /* Signal that post is activating the task */ _TASK_READY(td_ptr, kernel_data); if (flags & LWMSGQ_SEND_BLOCK_ON_SEND) { _task_block(); } else { _CHECK_RUN_SCHEDULER(); /* Let higher priority task run */ }/* Endif */ } else { if (flags & LWMSGQ_SEND_BLOCK_ON_SEND) { _task_block(); }/* Endif */ } /* Endif */ _int_enable(); /* Start CR 1944 */ _KLOGX2(KLOG_lwmsgq_send, MQX_OK); /* End CR 1944 */ return MQX_OK; }/* Endbody */
_mqx_uint _sem_post ( /* [IN] - The semaphore handle returned by _sem_open. */ pointer users_sem_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; SEM_STRUCT_PTR sem_ptr; #if MQX_COMPONENT_DESTRUCTION SEM_COMPONENT_STRUCT_PTR sem_component_ptr; #endif SEM_CONNECTION_STRUCT_PTR new_sem_connection_ptr; SEM_CONNECTION_STRUCT_PTR sem_connection_ptr; TD_STRUCT_PTR new_td_ptr; boolean task_added = FALSE; boolean destroying_semaphore = FALSE; _GET_KERNEL_DATA(kernel_data); _KLOGE2(KLOG_sem_post, users_sem_ptr); sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)users_sem_ptr; #if MQX_CHECK_VALIDITY if (sem_connection_ptr->VALID != SEM_VALID) { _KLOGX2(KLOG_sem_post, SEM_INVALID_SEMAPHORE_HANDLE); return(SEM_INVALID_SEMAPHORE_HANDLE); } /* Endif */ #endif sem_ptr = sem_connection_ptr->SEM_PTR; #if MQX_CHECK_ERRORS if (sem_ptr->POLICY & SEM_STRICT) { if (kernel_data->IN_ISR) { _KLOGX2(KLOG_sem_post, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ if (sem_connection_ptr->TD_PTR != kernel_data->ACTIVE_PTR) { /* ONLY OPENING task can use the semaphore */ _KLOGX2(KLOG_sem_post, SEM_INVALID_SEMAPHORE_HANDLE); return(SEM_INVALID_SEMAPHORE_HANDLE); } /* Endif */ if (sem_connection_ptr->POST_STATE == 0) { _KLOGX2(KLOG_sem_post, SEM_CANNOT_POST); return(SEM_CANNOT_POST); } /* Endif */ } /* Endif */ #endif _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (sem_ptr->VALID != SEM_VALID) { _int_enable(); _KLOGX2(KLOG_sem_post, SEM_INVALID_SEMAPHORE); return(SEM_INVALID_SEMAPHORE); } /* Endif */ #endif if (sem_ptr->POLICY & SEM_STRICT) { #if MQX_CHECK_ERRORS if (sem_ptr->COUNT > sem_ptr->MAX_COUNT) { /* Corruption somewhere */ _int_enable(); _KLOGX2(KLOG_sem_post, SEM_INVALID_SEMAPHORE_COUNT); return(SEM_INVALID_SEMAPHORE_COUNT); } /* Endif */ #endif --sem_connection_ptr->POST_STATE; if (sem_connection_ptr->POST_STATE == 0) { _QUEUE_REMOVE(&sem_ptr->OWNING_TASKS, sem_connection_ptr); } /* Endif */ } /* Endif */ if (_QUEUE_GET_SIZE(&sem_ptr->WAITING_TASKS)) { /* Schedule a waiting task to run */ new_sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR) ((pointer)sem_ptr->WAITING_TASKS.NEXT); while (new_sem_connection_ptr != (pointer)&sem_ptr->WAITING_TASKS) { new_td_ptr = new_sem_connection_ptr->TD_PTR; if ((new_td_ptr->STATE & STATE_MASK) == SEM_BLOCKED) { _TIME_DEQUEUE(new_td_ptr, kernel_data); _TASK_READY(new_td_ptr, kernel_data); new_td_ptr->INFO = SEM_AVAILABLE; task_added = TRUE; break; } /* Endif */ new_sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR) new_sem_connection_ptr->NEXT; } /* Endwhile */ } /* Endif */ if (!task_added) { ++sem_ptr->COUNT; #if MQX_COMPONENT_DESTRUCTION if ( sem_ptr->DELAYED_DESTROY ) { if ( ( (sem_ptr->POLICY & SEM_STRICT) && (sem_ptr->COUNT == sem_ptr->MAX_COUNT) ) || ( !(sem_ptr->POLICY & SEM_STRICT) ) ) { /* Destroy the semaphore name */ sem_ptr->VALID = 0; destroying_semaphore = TRUE; } /* Endif */ } /* Endif */ #endif } /* Endif */ if (sem_connection_ptr->BOOSTED && (sem_connection_ptr->POST_STATE == 0)) { /* This task was boosted by a waiting task */ _sched_unboost_priority_internal(kernel_data->ACTIVE_PTR, sem_connection_ptr->BOOSTED); sem_connection_ptr->BOOSTED = 0; } /* Endif */ _INT_ENABLE(); /* Let higher priority task run */ _CHECK_RUN_SCHEDULER(); #if MQX_COMPONENT_DESTRUCTION if (destroying_semaphore) { sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR) kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES]; if (sem_component_ptr != NULL) { _name_delete_internal(sem_component_ptr->NAME_TABLE_HANDLE, sem_ptr->NAME); } /* Endif */ _mem_free(sem_ptr); } /* Endif */ #endif _KLOGX2(KLOG_sem_post, MQX_OK); return(MQX_OK); } /* Endbody */