/*! * \private * * \brief This is internal function used by a task to wait for a specified event. * * \param[in] event_ptr Read only. Pointer to the lightweight event. * \param[in] bit_mask Bit mask. Each set bit represents an event bit * to wait for. * \param[in] all TRUE (wait for all bits in bit_mask to be set), * FALSE (wait for any bit in bit_mask to be set). * \param[in] tick_ptr Pointer to the maximum number of ticks to wait * for the events to be set. If the value is NULL, then the timeout will be infinite. * \param[in] ticks_are_absolute TRUE (ticks represents absolute time), FALSE * (ticks represents relative time). * * \return MQX_OK * \return LWEVENT_WAIT_TIMEOUT (The time elapsed before an event signalled.) * \return MQX_LWEVENT_INVALID (Lightweight event is no longer valid or was never valid.) * \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.) * * \see _lwevent_wait_for * \see _usr_lwevent_wait_for * \see _lwevent_wait_until * \see _usr_lwevent_wait_until * \see _lwevent_wait_ticks * \see _usr_lwevent_wait_ticks * \see LWEVENT_STRUCT * \see MQX_TICK_STRUCT */ _mqx_uint _lwevent_wait_internal ( LWEVENT_STRUCT_PTR event_ptr, _mqx_uint bit_mask, bool all, MQX_TICK_STRUCT_PTR tick_ptr, bool ticks_are_absolute ) { KERNEL_DATA_STRUCT_PTR kernel_data; TD_STRUCT_PTR td_ptr; _mqx_uint result; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _KLOGX2(KLOG_lwevent_wait_internal, MQX_CANNOT_CALL_FUNCTION_FROM_ISR); return (MQX_CANNOT_CALL_FUNCTION_FROM_ISR); } /* Endif */ #endif result = MQX_OK; td_ptr = kernel_data->ACTIVE_PTR; _INT_DISABLE(); #if MQX_CHECK_VALIDITY if (event_ptr->VALID != LWEVENT_VALID) { _int_enable(); return (MQX_LWEVENT_INVALID); } /* Endif */ #endif if ( (all && (event_ptr->VALUE & bit_mask) == bit_mask) || (!all && (event_ptr->VALUE & bit_mask))) { /* store information about which bits caused task to be unblocked */ td_ptr->LWEVENT_BITS = event_ptr->VALUE & bit_mask; /* clear used automatic events */ event_ptr->VALUE &= ~(event_ptr->AUTO & bit_mask); _INT_ENABLE(); return (result); } /* Endif */ /* Must wait for a event to become available */ td_ptr->LWEVENT_BITS = bit_mask; if (all) { td_ptr->FLAGS |= TASK_LWEVENT_ALL_BITS_WANTED; } else { td_ptr->FLAGS &= ~TASK_LWEVENT_ALL_BITS_WANTED; } /* Endif */ /* Enqueue at end */ _QUEUE_ENQUEUE(&event_ptr->WAITING_TASKS, &td_ptr->AUX_QUEUE); /* Now put the task to sleep */ td_ptr->STATE = LWEVENT_BLOCKED; td_ptr->INFO = (_mqx_uint) &event_ptr->WAITING_TASKS; if (tick_ptr) { if (ticks_are_absolute) { _time_delay_until(tick_ptr); } else { _time_delay_for(tick_ptr); } /* Endif */ if (td_ptr->INFO) { /* Must have timed out */ /*_QUEUE_REMOVE(&event_ptr->WAITING_TASKS, &td_ptr->AUX_QUEUE);*/ result = LWEVENT_WAIT_TIMEOUT; } /* Endif */ } else { _task_block(); } /* Endif */ #if MQX_COMPONENT_DESTRUCTION if (event_ptr->VALID == 0) { /* We've been deleted */ result = MQX_LWEVENT_INVALID; } /* Endif */ #endif _INT_ENABLE(); return (result); }
MESSAGE_HEADER_STRUCT_PTR _msgq_receive_internal ( /* [IN] id of the queue from which a message is to be received */ _queue_id queue_id, /* [IN] indication of the number of ticks which can expire before ** this request times out */ MQX_TICK_STRUCT_PTR timeout_tick_ptr, /* [IN] relative or absolute time specified in tick_ptr */ _mqx_uint mode, /* [OUT] where the error code is to be stored */ _mqx_uint_ptr error_ptr ) { /* Body */ KERNEL_DATA_STRUCT_PTR kernel_data; MSG_COMPONENT_STRUCT_PTR msg_component_ptr; register TD_STRUCT_PTR td_ptr; MESSAGE_HEADER_STRUCT_PTR message_ptr; register INTERNAL_MESSAGE_STRUCT_PTR imsg_ptr; register MSGQ_STRUCT_PTR msgq_ptr; _queue_number queue; *error_ptr = MQX_OK; _GET_KERNEL_DATA(kernel_data); #if MQX_CHECK_ERRORS if (kernel_data->IN_ISR) { _task_set_error(MQX_CANNOT_CALL_FUNCTION_FROM_ISR); *error_ptr = MQX_CANNOT_CALL_FUNCTION_FROM_ISR; return(NULL); }/* Endif */ #endif msg_component_ptr = _GET_MSG_COMPONENT_STRUCT_PTR(kernel_data); #if MQX_CHECK_ERRORS if (msg_component_ptr == NULL){ _task_set_error(MQX_COMPONENT_DOES_NOT_EXIST); *error_ptr = MQX_COMPONENT_DOES_NOT_EXIST; return(NULL); } /* Endif */ #endif message_ptr = NULL; td_ptr = kernel_data->ACTIVE_PTR; if (queue_id == MSGQ_ANY_QUEUE){ /* if queue_id is 0 than a receive from any queue is performed */ /* Does the task own a queue */ if (td_ptr->MSG_QUEUE_HEAD == NULL){ /* Does NOT */ _task_set_error(MSGQ_QUEUE_IS_NOT_OPEN); *error_ptr = MSGQ_QUEUE_IS_NOT_OPEN; return NULL; } /* Endif */ _INT_DISABLE(); if (td_ptr->MESSAGES_AVAILABLE == 0){ td_ptr->STATE = RCV_ANY_BLOCKED; td_ptr->INFO = queue_id; td_ptr->MESSAGE = NULL; if (mode == MSG_TIMEOUT_NONE) { _task_block(); } else if (mode == MSG_TIMEOUT_RELATIVE) { _time_delay_for(timeout_tick_ptr); } else { _time_delay_until(timeout_tick_ptr); } /* Endif */ /* ** SHORT CUT... ** The message send routine does not queue up a message in this case. ** the message is deposited directly into the task descriptor */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)td_ptr->MESSAGE; if (message_ptr == NULL){ /* A timeout has occurred */ #if MQXCFG_ENABLE_MSG_TIMEOUT_ERROR _task_set_error(MSGQ_MESSAGE_NOT_AVAILABLE); #endif } /* Endif */ td_ptr->MESSAGE = NULL; } else { /* Check all queues for an available entry .. There must be at least ** one entry available */ msgq_ptr = (MSGQ_STRUCT_PTR)td_ptr->MSG_QUEUE_HEAD; while (msgq_ptr != NULL){ if (msgq_ptr->NO_OF_ENTRIES){ /* dequeue the top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); break; } /* Endif */ msgq_ptr = msgq_ptr->NEXT_MSGQ_PTR; } /* Endwhile */ } /* Endif */ } else { /* RECEIVE from a specific qid */ queue = QUEUE_FROM_QID(queue_id); #if MQX_CHECK_ERRORS if ( (PROC_NUMBER_FROM_QID(queue_id) != kernel_data->INIT.PROCESSOR_NUMBER) || (! VALID_QUEUE(queue)) ) { _task_set_error(MSGQ_INVALID_QUEUE_ID); *error_ptr = MSGQ_INVALID_QUEUE_ID; return (pointer)message_ptr; } /* Endif */ #endif msgq_ptr = &msg_component_ptr->MSGQS_PTR[queue]; #if MQX_CHECK_ERRORS if ( msgq_ptr->QUEUE != queue ) { _task_set_error(MSGQ_QUEUE_IS_NOT_OPEN); *error_ptr = MSGQ_QUEUE_IS_NOT_OPEN; return message_ptr; } /* Endif */ if ( (msgq_ptr->TD_PTR != NULL) && (msgq_ptr->TD_PTR != td_ptr) ) { _task_set_error(MSGQ_NOT_QUEUE_OWNER); *error_ptr = MSGQ_NOT_QUEUE_OWNER; return message_ptr; } /* Endif */ #endif /* ** check the specified queue for an entry ** if not entry, then block until an entry is received or ** timeout occurs */ _INT_DISABLE(); if (msgq_ptr->NO_OF_ENTRIES == 0) { if (msgq_ptr->TD_PTR == NULL) { /* A system message queue, indicate none available */ message_ptr = NULL; } else { td_ptr->STATE = RCV_SPECIFIC_BLOCKED; td_ptr->INFO = queue; td_ptr->MESSAGE = NULL; if (mode == MSG_TIMEOUT_NONE) { _task_block(); } else if (mode == MSG_TIMEOUT_RELATIVE) { _time_delay_for(timeout_tick_ptr); } else { _time_delay_until(timeout_tick_ptr); } /* Endif */ message_ptr = (MESSAGE_HEADER_STRUCT_PTR)td_ptr->MESSAGE; if ( message_ptr == NULL ) { #if MQXCFG_ENABLE_MSG_TIMEOUT_ERROR _task_set_error(MSGQ_MESSAGE_NOT_AVAILABLE); #endif } else if ((message_ptr->TARGET_QID != queue_id) && (msgq_ptr->NO_OF_ENTRIES > 0)) { /* The original msg was swapped out in msgq_sendi() for a higher priority msg with a different target_qid. Enqueue this msg, and then dequeue the msg we need. */ register MSGQ_STRUCT_PTR tmp_msgq_ptr; register _queue_number tmp_queue; /* Get the msg's queue */ tmp_queue = QUEUE_FROM_QID(message_ptr->TARGET_QID); tmp_msgq_ptr = &msg_component_ptr->MSGQS_PTR[tmp_queue]; if ((tmp_msgq_ptr->MAX_ENTRIES == 0) || (tmp_msgq_ptr->NO_OF_ENTRIES < tmp_msgq_ptr->MAX_ENTRIES)) { /* the msg's queue has room */ imsg_ptr = GET_INTERNAL_MESSAGE_PTR(message_ptr); #if MQX_CHECK_ERRORS if (imsg_ptr->VALID != MSG_VALID){ /* An invalid message was input by the application. */ _task_set_error(MSGQ_INVALID_MESSAGE); message_ptr = NULL; } else #endif { /* enqueue the msg */ _msgq_insert_message_internal(tmp_msgq_ptr, imsg_ptr, TRUE); if (tmp_msgq_ptr->TD_PTR) { ++(tmp_msgq_ptr->TD_PTR->MESSAGES_AVAILABLE); } /* Endif */ /* now dequeue our queue's top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); } } else { /* Queue full, error - this should not happen since msgq_sendi() checks for room on the queue for all msgs, including short-cut msgs. */ _task_set_error(MSGQ_QUEUE_FULL); message_ptr = NULL; } } /* Endif */ td_ptr->MESSAGE = NULL; } /* Endif */ } else { /* dequeue the top entry */ DEQUEUE_TOP_MSG_ENTRY(msgq_ptr, imsg_ptr, message_ptr, td_ptr); } /* Endif */ } /* Endif */ _INT_ENABLE(); return message_ptr; } /* Endbody */