0
mirror of https://github.com/Indemsys/Frequency_Inverter.git synced 2026-06-13 11:22:09 +00:00
Files
2022-01-04 12:22:53 +02:00

2200 lines
67 KiB
C

/*HEADER*********************************************************************
*
* Copyright (c) 2008 Freescale Semiconductor;
* All Rights Reserved
*
* Copyright (c) 2004-2008 Embedded Access Inc.;
* All Rights Reserved
*
* Copyright (c) 1989-2008 ARC International;
* All Rights Reserved
*
***************************************************************************
*
* THIS SOFTWARE IS PROVIDED BY FREESCALE "AS IS" AND ANY EXPRESSED OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL FREESCALE OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*
**************************************************************************
*
* $FileName: sem.c$
* $Version : 3.8.2.0$
* $Date : Jun-25-2012$
*
* Comments:
*
* This file contains functions of the Semaphore component.
*
*END************************************************************************/
#include <string.h>
#include "mqx_inc.h"
#if MQX_USE_SEMAPHORES
#include "name.h"
#include "name_prv.h"
#include "sem.h"
#include "sem_prv.h"
#include "mqx_str.h"
/*!
* \brief Closes the connection to the semaphore.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (Semaphore is no longer valid or sem_handle
* is not a valid semaphore connection)
* \return Error from _mem_free() (Task is not the one that opened the connection.)
*
* \warning If the semaphore is strict, posts the appropriate number of times to
* the semaphore for this connection.
* \warning Might dispatch tasks that are waiting for the semaphore.
* \warning Cannot be called from an ISR.
*
* \see _sem_destroy
* \see _sem_destroy_fast
* \see _sem_open
* \see _sem_open_fast
*/
_mqx_uint _sem_close
(
pointer users_sem_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_sem_close, users_sem_ptr);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_sem_close, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)users_sem_ptr;
#if MQX_CHECK_ERRORS
if (sem_connection_ptr->TD_PTR != kernel_data->ACTIVE_PTR)
{
_KLOGX2(KLOG_sem_close, SEM_INVALID_SEMAPHORE_HANDLE);
return(SEM_INVALID_SEMAPHORE_HANDLE);
} /* Endif */
#endif
#if MQX_CHECK_VALIDITY
if (sem_connection_ptr->VALID != SEM_VALID)
{
_KLOGX2(KLOG_sem_close, SEM_INVALID_SEMAPHORE_HANDLE);
return(SEM_INVALID_SEMAPHORE_HANDLE);
} /* Endif */
#endif
if (sem_connection_ptr->SEM_PTR->VALID)
{
/* Release all held semaphores */
while (sem_connection_ptr->POST_STATE > 0)
{
_sem_post(sem_connection_ptr);
} /* Endwhile */
} /* Endif */
sem_connection_ptr->VALID = 0;
if (_mem_free(sem_connection_ptr) != MQX_OK)
{
_KLOGX2(KLOG_sem_close, kernel_data->ACTIVE_PTR->TASK_ERROR_CODE);
return(kernel_data->ACTIVE_PTR->TASK_ERROR_CODE);
}
else
{
_KLOGX2(KLOG_sem_close, MQX_OK);
return(MQX_OK);
} /* Endif */
} /* Endbody */
/*!
* \brief Creates the semaphore component.
*
* If an application previously called the function and maximum_number is greater
* that what was specified, MQX changes the maximum number of semaphores to
* maximum_number.
* \n If an application does not explicitly create the semaphore component, MQX
* does so with the following default values the first time that a task calls
* _sem_create() or _sem_create_fast().
* \n Parameter default values:
* \li Initial_number = 8(default)
* \li Grow_number = 8(default)
* \li Maximum_number = 0(unlimited)
*
* \param[in] initial_number Initial number of semaphores that can be created.
* \param[in] grow_number Number of semaphores to be added when the initial
* number have been created.
* \param[in] maximum_number If grow_number is not 0, one of:
* \li Maximum number of semaphores that can be created.
* \li 0 (Unlimited number.)
*
* \return MQX_OK (success)
* \return MQX_OUT_OF_MEMORY (Failure: MQX cannot allocate memory for semaphore
* component data.)
*
* \warning On failure, the task error code might be set.
*
* \see _sem_create
* \see _sem_create_fast
* \see _sem_open
* \see _sem_open_fast
* \see _task_set_error
*/
_mqx_uint _sem_create_component
(
_mqx_uint initial_number,
_mqx_uint grow_number,
_mqx_uint maximum_number
)
{ /* Body */
SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
KERNEL_DATA_STRUCT_PTR kernel_data;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE4(KLOG_sem_create_component, initial_number, grow_number, maximum_number);
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
if (sem_component_ptr != NULL)
{
if (maximum_number > sem_component_ptr->MAXIMUM_NUMBER)
{
sem_component_ptr->MAXIMUM_NUMBER = maximum_number;
} /* Endif */
_KLOGX2(KLOG_sem_create_component, MQX_OK);
return(MQX_OK);
} /* Endif */
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
_mem_alloc_system_zero((_mem_size)sizeof(SEM_COMPONENT_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_component_ptr == NULL)
{
_KLOGX2(KLOG_sem_create_component, MQX_OUT_OF_MEMORY);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(sem_component_ptr, MEM_TYPE_SEMAPHORE_COMPONENT);
result = _name_create_handle_internal(&sem_component_ptr->NAME_TABLE_HANDLE,
initial_number, grow_number, maximum_number, initial_number);
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (result != MQX_OK)
{
_mem_free(sem_component_ptr);
_KLOGX2(KLOG_sem_create_component, result);
return(result);
} /* Endif */
#endif
sem_component_ptr->GROW_NUMBER = grow_number;
if (maximum_number == 0)
{
sem_component_ptr->MAXIMUM_NUMBER = MAX_MQX_UINT;
}
else if (maximum_number < initial_number)
{
sem_component_ptr->MAXIMUM_NUMBER = initial_number;
}
else
{
sem_component_ptr->MAXIMUM_NUMBER = maximum_number;
} /* Endif */
sem_component_ptr->VALID = SEM_VALID;
_int_disable();
#if MQX_CHECK_ERRORS
if (kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES] != NULL)
{
SEM_COMPONENT_STRUCT_PTR new_sem_component_ptr;
new_sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
if (maximum_number > new_sem_component_ptr->MAXIMUM_NUMBER)
{
new_sem_component_ptr->MAXIMUM_NUMBER = maximum_number;
} /* Endif */
_int_enable();
_name_destroy_handle_internal(sem_component_ptr->NAME_TABLE_HANDLE);
_mem_free(sem_component_ptr);
_KLOGX2(KLOG_sem_create_component, MQX_OK);
return(MQX_OK);
} /* Endif */
#endif
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES] = sem_component_ptr;
#if MQX_COMPONENT_DESTRUCTION
kernel_data->COMPONENT_CLEANUP[KERNEL_SEMAPHORES] = _sem_cleanup;
#endif
_int_enable();
_KLOGX2(KLOG_sem_create_component, MQX_OK);
return(MQX_OK);
} /* Endbody */
/*!
* \brief Creates a named semaphore.
*
* After the semaphore is created, tasks open a connection to it with _sem_open()
* and close the connection with _sem_close(). A named semaphore is destroyed
* with _sem_destroy().
* <table>
* <tr>
* <td><b>Bit flag</b></td>
* <td><b>Set</b></td>
* <td><b>Not set</b></td>
* </tr>
* <tr>
* <td><b>SEM_PRIORITY_INHERITANCE</b>(<b>SEM_STRICT</b> must also be set)</td>
* <td>If a task that waits for the semaphore has a higher priority than a
* task that owns the semaphore, MQX boosts the priority of one of the owning
* tasks to the priority of the waiting task. When the boosted task posts its
* semaphore, MQX returns its priorities to its original values.</td>
* <td>MQX does not boost priorities</td>
* </tr>
* <tr>
* <td><b>SEM_PRIORITY_QUEUEING</b></td>
* <td>Task that waits for the semaphore is queued according to the task's
* priority. Within a priority, tasks are in FIFO order.</td>
* <td>Task that waits for the semaphore is queued in FIFO order.</td>
* </tr>
* <tr>
* <td><b>SEM_STRICT</b></td>
* <td>Task must wait for the semaphore before it can post the semaphore.</td>
* <td>Task need not wait before posting.</td>
* </tr>
* <tr>
* <td><b>SEM_STRICT</b></td>
* <td>Sem_count must be greater than or equal to 1.</td>
* <td>Sem_count must be greater than or equal to 0.</td>
* </tr>
* </table>
*
* \param[in] name_ptr Name by which to identify the semaphore.
* \param[in] initial_count Number of requests that can concurrently have the
* semaphore.
* \param[in] flags Bit flags: 0 or as in Description.
*
* \return MQX_OK (success)
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component was not created and
* cannot be created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the semaphore.)
* \return SEM_INCORRECT_INITIAL_COUNT (sem_count cannot be 0 if SEM_STRICT is set.)
* \return SEM_INVALID_POLICY (SEM_STRICT must be set if SEM_PRIORITY_INHERITANCE
* is set.)
* \return SEM_SEMAPHORE_EXISTS (Semaphore with the name exists.)
* \return SEM_SEMAPHORE_TABLE_FULL (Semaphore names database is full and cannot
* be expanded.)
*
* \warning Creates the semaphore component with default values if it was not
* previously created.
* \warning Cannot be called from an ISR.
* \warning On failure, the task error code might be set.
*
* \see _sem_create_component
* \see _sem_destroy
* \see _sem_destroy_fast
* \see _sem_open
* \see _sem_open_fast
* \see _sem_close
* \see _task_set_error
*/
_mqx_uint _sem_create
(
char_ptr name_ptr,
_mqx_uint initial_count,
_mqx_uint flags
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
register SEM_STRUCT_PTR sem_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE4(KLOG_sem_create, name_ptr, initial_count, flags);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_sem_create, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (flags & SEM_STRICT)
{
if (initial_count == 0)
{
_KLOGX2(KLOG_sem_create, SEM_INCORRECT_INITIAL_COUNT);
return(SEM_INCORRECT_INITIAL_COUNT);
}/* Endif */
}
else
{
if (flags & SEM_PRIORITY_INHERITANCE)
{
_KLOGX2(KLOG_sem_create, SEM_INVALID_POLICY);
return(SEM_INVALID_POLICY);
} /* Endif */
}/* Endif */
#endif
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
if (sem_component_ptr == NULL)
{
result = _sem_create_component(SEM_DEFAULT_INITIAL_NUMBER,
SEM_DEFAULT_GROW_NUMBER, SEM_DEFAULT_MAXIMUM_NUMBER);
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_component_ptr == NULL)
{
_KLOGX2(KLOG_sem_create, result);
return(result);
} /* Endif */
#endif
} /* Endif */
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX2(KLOG_sem_create, MQX_INVALID_COMPONENT_BASE);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
sem_ptr = (SEM_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(SEM_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_ptr == NULL)
{
_KLOGX2(KLOG_sem_create, MQX_OUT_OF_MEMORY);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(sem_ptr, MEM_TYPE_SEMAPHORE);
sem_ptr->POLICY = flags;
sem_ptr->COUNT = initial_count;
if (flags & SEM_STRICT)
{
sem_ptr->MAX_COUNT = initial_count;
}
else
{
sem_ptr->MAX_COUNT = MAX_MQX_UINT;
}/* Endif */
_QUEUE_INIT(&sem_ptr->WAITING_TASKS, SEM_MAX_WAITING_TASKS);
_QUEUE_INIT(&sem_ptr->OWNING_TASKS, SEM_MAX_WAITING_TASKS);
result = _name_add_internal(sem_component_ptr->NAME_TABLE_HANDLE, name_ptr,
(_mqx_uint)sem_ptr);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
_mem_free(sem_ptr);
if (result == NAME_EXISTS)
{
_KLOGX2(KLOG_sem_create, SEM_SEMAPHORE_EXISTS);
return(SEM_SEMAPHORE_EXISTS);
}
else if (result == NAME_TABLE_FULL)
{
_KLOGX2(KLOG_sem_create, SEM_SEMAPHORE_TABLE_FULL);
return(SEM_SEMAPHORE_TABLE_FULL);
} /* Endif */
_KLOGX2(KLOG_sem_create, result);
return(result);
} /* Endif */
#endif
strncpy(sem_ptr->NAME, name_ptr, (_mqx_uint)NAME_MAX_NAME_SIZE-1);
sem_ptr->NAME[NAME_MAX_NAME_SIZE-1] = '\0';
sem_ptr->VALID = SEM_VALID;
_KLOGX2(KLOG_sem_create, result);
return(result);
} /* Endbody */
/*!
* \brief Destroys the named semaphore.
*
* <table>
* <tr>
* <td><b>force_destroy is TRUE</b></td>
* <td><b>force_destroy is FALSE</b></td>
* </tr>
* <tr>
* <td> \li Tasks that are waiting for the semaphore are made ready.
* \li Semaphore is destroyed after all the owners post the semaphore.</td>
* <td> \li Semaphore is destroyed after the last waiting task gets and posts
* the semaphore.
* \li This is the action if the semaphore is strict.</td>
* </tr>
* </table>
*
* \param[in] name_ptr Name of the semaphore to destroy, created using
* _sem_create().
* \param[in] force_destroy A boolean flag, see Description.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component is not created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return SEM_SEMAPHORE_NOT_FOUND (Name_ptr is not in the semaphore names database.)
* \return SEM_INVALID_SEMAPHORE (Semaphore data that is associated with name or index is not valid.)
* _name_find_internal
* \return NAME_TOO_SHORT (Name is 0 lenght string.)
* \return NAME_TOO_LONG (Name is longer than NAME_MAX_NAME_SIZE.)
*
* \warning Cannot be called from an ISR.
*
* \see _sem_destroy_fast
* \see _sem_close
* \see _sem_create
* \see _sem_create_fast
*/
_mqx_uint _sem_destroy
(
char_ptr name_ptr,
boolean force_destroy
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
SEM_STRUCT_PTR sem_ptr;
SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
QUEUE_STRUCT_PTR queue_ptr;
TD_STRUCT_PTR td_ptr;
_mqx_max_type tmp;
_mqx_uint result;
_mqx_uint i;
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_sem_destroy, name_ptr, force_destroy);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_sem_destroy, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES] == NULL)
{
_KLOGX2(KLOG_sem_destroy, MQX_COMPONENT_DOES_NOT_EXIST);
return(MQX_COMPONENT_DOES_NOT_EXIST);
} /* Endif */
#endif
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX2(KLOG_sem_destroy, MQX_INVALID_COMPONENT_BASE);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
result = _name_find_internal(sem_component_ptr->NAME_TABLE_HANDLE,
name_ptr, &tmp);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
if (result == NAME_NOT_FOUND)
{
_KLOGX2(KLOG_sem_destroy, SEM_SEMAPHORE_NOT_FOUND);
return(SEM_SEMAPHORE_NOT_FOUND);
} /* Endif */
_KLOGX2(KLOG_sem_destroy, result);
return(result);
} /* Endif */
#endif
sem_ptr = (SEM_STRUCT_PTR)tmp;
_int_disable();
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
_int_enable();
_KLOGX2(KLOG_sem_destroy, SEM_INVALID_SEMAPHORE);
return(SEM_INVALID_SEMAPHORE);
} /* Endif */
#endif
queue_ptr = &sem_ptr->WAITING_TASKS;
if (force_destroy)
{
/* Get rid of all waiting tasks */
i = _QUEUE_GET_SIZE(queue_ptr) + 1;
while (--i)
{
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
((pointer)queue_ptr->NEXT);
td_ptr = sem_connection_ptr->TD_PTR;
if ((td_ptr->STATE & STATE_MASK)== SEM_BLOCKED)
{
_TIME_DEQUEUE(td_ptr,kernel_data);
_task_set_error_td_internal(td_ptr,SEM_SEMAPHORE_DELETED);
_TASK_READY(td_ptr,kernel_data);
} /* Endif */
} /* Endwhile */
} /* Endif */
if (
( (sem_ptr->POLICY & SEM_STRICT) &&
(sem_ptr->COUNT == sem_ptr->MAX_COUNT) &&
(_QUEUE_GET_SIZE(queue_ptr) == 0))
||
( (!(sem_ptr->POLICY & SEM_STRICT)) &&
(_QUEUE_GET_SIZE(queue_ptr) == 0)))
{
/* Destroy the semaphore */
sem_ptr->VALID = 0;
_int_enable();
/* May need to let higher priority task run */
_CHECK_RUN_SCHEDULER();
result = _name_delete_internal(sem_component_ptr->NAME_TABLE_HANDLE,
name_ptr);
if (result == NAME_NOT_FOUND)
{
result = SEM_SEMAPHORE_NOT_FOUND;
} /* Endif */
_mem_free(sem_ptr);
}
else
{
sem_ptr->DELAYED_DESTROY = TRUE;
_int_enable();
/* May need to let higher priority task run */
_CHECK_RUN_SCHEDULER();
} /* Endif */
_KLOGX2(KLOG_sem_destroy, result);
return(result);
} /* Endbody */
/*!
* \brief Creates the fast semaphore.
*
* After the semaphore is created, tasks open a connection to it with
* _sem_open_fast() and close the connection with _sem_close(). A fast semaphore
* is destroyed with _sem_destroy_fast().
* \n _sem_create_fast() access the semaphore via an index number rather than a
* name.
*
* \param[in] sem_index Number by which to identify the semaphore.
* \param[in] initial_count Number of tasks that can concurrently have the semaphore.
* \param[in] flags Bit flags, as described for _sem_create().
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component was not created and
* cannot be created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the semaphore.)
* \return SEM_SEMAPHORE_TABLE_FULL (Semaphore names database is full and cannot
* be expanded.)
* \return SEM_SEMAPHORE_EXISTS (Semaphore with the name exists.)
* \return SEM_INCORRECT_INITIAL_COUNT (Sem_count cannot be 0 if SEM_STRICT is set.)
* \return SEM_INVALID_POLICY (SEM_STRICT must be set if SEM_PRIORITY_INHERITANCE
* is set.)
*
* \warning Creates the semaphore component with default values if it was not
* previously created.
* \warning Cannot be called from an ISR.
* \warning On failure, the task error code might be set.
*
* \see _sem_create_component
* \see _sem_destroy
* \see _sem_destroy_fast
* \see _sem_open
* \see _sem_open_fast
* \see _sem_close
* \see _sem_create
*
*/
_mqx_uint _sem_create_fast
(
_mqx_uint sem_index,
_mqx_uint initial_count,
_mqx_uint flags
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
register SEM_STRUCT_PTR sem_ptr;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE4(KLOG_sem_create_fast, sem_index, initial_count, flags);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_sem_create_fast, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (flags & SEM_STRICT)
{
if (initial_count == 0)
{
_KLOGX2(KLOG_sem_create_fast, SEM_INCORRECT_INITIAL_COUNT);
return(SEM_INCORRECT_INITIAL_COUNT);
}/* Endif */
}
else
{
if (flags & SEM_PRIORITY_INHERITANCE)
{
_KLOGX2(KLOG_sem_create_fast, SEM_INVALID_POLICY);
return(SEM_INVALID_POLICY);
} /* Endif */
}/* Endif */
#endif
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
if (sem_component_ptr == NULL)
{
result = _sem_create_component(SEM_DEFAULT_INITIAL_NUMBER,
SEM_DEFAULT_GROW_NUMBER, SEM_DEFAULT_MAXIMUM_NUMBER);
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_component_ptr == NULL)
{
_KLOGX2(KLOG_sem_create_fast, result);
return(result);
} /* Endif */
#endif
} /* Endif */
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX2(KLOG_sem_create_fast, MQX_INVALID_COMPONENT_BASE);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
sem_ptr = (SEM_STRUCT_PTR)_mem_alloc_system_zero((_mem_size)sizeof(SEM_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_ptr == NULL)
{
_KLOGX2(KLOG_sem_create_fast, MQX_OUT_OF_MEMORY);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(sem_ptr, MEM_TYPE_SEMAPHORE);
sem_ptr->POLICY = flags;
sem_ptr->COUNT = initial_count;
if (flags & SEM_STRICT)
{
sem_ptr->MAX_COUNT = initial_count;
}
else
{
sem_ptr->MAX_COUNT = MAX_MQX_UINT;
}/* Endif */
_QUEUE_INIT(&sem_ptr->WAITING_TASKS, SEM_MAX_WAITING_TASKS);
_QUEUE_INIT(&sem_ptr->OWNING_TASKS, SEM_MAX_WAITING_TASKS);
_str_mqx_uint_to_hex_string(sem_index, sem_ptr->NAME);
result = _name_add_internal_by_index(sem_component_ptr->NAME_TABLE_HANDLE,
sem_ptr->NAME, (_mqx_uint)sem_ptr, sem_index);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
_mem_free(sem_ptr);
if (result == NAME_EXISTS)
{
_KLOGX2(KLOG_sem_create_fast, SEM_SEMAPHORE_EXISTS);
return(SEM_SEMAPHORE_EXISTS);
}
else if (result == NAME_TABLE_FULL)
{
_KLOGX2(KLOG_sem_create_fast, SEM_SEMAPHORE_TABLE_FULL);
return(SEM_SEMAPHORE_TABLE_FULL);
} /* Endif */
_KLOGX2(KLOG_sem_create_fast, result);
return(result);
} /* Endif */
#endif
sem_ptr->VALID = SEM_VALID;
_KLOGX2(KLOG_sem_create_fast, result);
return(result);
} /* Endbody */
/*!
* \brief Destroys the fast semaphore.
*
* <table>
* <tr>
* <td><b>force_destroy is TRUE</b></td>
* <td><b>force_destroy is FALSE</b></td>
* </tr>
* <tr>
* <td> \li Tasks that are waiting for the semaphore are made ready.
* \li Semaphore is destroyed after all the owners post the semaphore.</td>
* <td> \li Semaphore is destroyed after the last waiting task gets and posts
* the semaphore.
* \li This is the action if the semaphore is strict.</td>
* </tr>
* </table>
*
* \param[in] sem_index Number that identifies the semaphore to destroy,
* created using _sem_create_fast().
* \param[in] force_destroy A boolean flag, see Description.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component is not created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return SEM_SEMAPHORE_NOT_FOUND (Name_ptr is not in the semaphore names database.)
* \return SEM_INVALID_SEMAPHORE (Semaphore data that is associated with name or index is not valid.)
* _name_find_internal_by_index
* \return NAME_TOO_SHORT (Name is 0 lenght string.)
* \return NAME_TOO_LONG (Name is longer than NAME_MAX_NAME_SIZE.)
*
* \warning Cannot be called from an ISR.
*
* \see _sem_destroy
* \see _sem_close
* \see _sem_create
* \see _sem_create_fast
*/
_mqx_uint _sem_destroy_fast
(
_mqx_uint sem_index,
boolean force_destroy
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
SEM_STRUCT_PTR sem_ptr;
SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
QUEUE_STRUCT_PTR queue_ptr;
TD_STRUCT_PTR td_ptr;
_mqx_max_type tmp;
_mqx_uint result;
_mqx_uint i;
#if MQX_CHECK_ERRORS
char name[9];
#endif
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_sem_destroy_fast, sem_index, force_destroy);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
_KLOGX2(KLOG_sem_destroy_fast, MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
#if MQX_CHECK_ERRORS
if (kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES] == NULL)
{
_KLOGX2(KLOG_sem_destroy_fast, MQX_COMPONENT_DOES_NOT_EXIST);
return(MQX_COMPONENT_DOES_NOT_EXIST);
} /* Endif */
#endif
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX2(KLOG_sem_destroy_fast, MQX_INVALID_COMPONENT_BASE);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
result = _name_find_internal_by_index(sem_component_ptr->NAME_TABLE_HANDLE,
sem_index, &tmp);
sem_ptr = (SEM_STRUCT_PTR)tmp;
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
if (result == NAME_NOT_FOUND)
{
_KLOGX2(KLOG_sem_destroy_fast, SEM_SEMAPHORE_NOT_FOUND);
return(SEM_SEMAPHORE_NOT_FOUND);
} /* Endif */
_KLOGX2(KLOG_sem_destroy_fast, result);
return(result);
} /* Endif */
_str_mqx_uint_to_hex_string(sem_index, name);
if (strncmp(name, sem_ptr->NAME, 8))
{
/* Name does not match */
_KLOGX2(KLOG_sem_destroy_fast, SEM_SEMAPHORE_NOT_FOUND);
return(SEM_SEMAPHORE_NOT_FOUND);
} /* Endif */
#endif
_int_disable();
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
_int_enable();
_KLOGX2(KLOG_sem_destroy_fast, SEM_INVALID_SEMAPHORE);
return(SEM_INVALID_SEMAPHORE);
} /* Endif */
#endif
queue_ptr = &sem_ptr->WAITING_TASKS;
if (force_destroy)
{
/* Get rid of all waiting tasks */
i = _QUEUE_GET_SIZE(queue_ptr) + 1;
while (--i)
{
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
((pointer)queue_ptr->NEXT);
td_ptr = sem_connection_ptr->TD_PTR;
if ((td_ptr->STATE & STATE_MASK)== SEM_BLOCKED)
{
_TIME_DEQUEUE(td_ptr,kernel_data);
_task_set_error_td_internal(td_ptr,SEM_SEMAPHORE_DELETED);
_TASK_READY(td_ptr,kernel_data);
} /* Endif */
} /* Endwhile */
} /* Endif */
if (
( (sem_ptr->POLICY & SEM_STRICT) &&
(sem_ptr->COUNT == sem_ptr->MAX_COUNT) &&
(_QUEUE_GET_SIZE(queue_ptr) == 0))
||
( (!(sem_ptr->POLICY & SEM_STRICT)) &&
(_QUEUE_GET_SIZE(queue_ptr) == 0)))
{
/* Destroy the semaphore */
sem_ptr->VALID = 0;
_int_enable();
/* May need to let higher priority task run */
_CHECK_RUN_SCHEDULER();
result = _name_delete_internal_by_index(sem_component_ptr->NAME_TABLE_HANDLE,
sem_index);
if (result == NAME_NOT_FOUND)
{
result = SEM_SEMAPHORE_NOT_FOUND;
} /* Endif */
_mem_free(sem_ptr);
}
else
{
sem_ptr->DELAYED_DESTROY = TRUE;
_int_enable();
/* May need to let higher priority task run */
_CHECK_RUN_SCHEDULER();
} /* Endif */
_KLOGX2(KLOG_sem_destroy_fast, result);
return(result);
} /* Endbody */
/*!
* \brief Opens a connection to the fast semaphore.
*
* \param[in] sem_index Number that identifies the semaphore that was
* created using _sem_create_fast().
* \param[out] returned_sem_ptr Pointer to the semaphore handle, which is a
* connection to the semaphore.
*
* \return MQX_OK
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component is not created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the connection.)
* \return SEM_SEMAPHORE_NOT_FOUND (Name is not in the semaphore names database.)
* \return SEM_INVALID_SEMAPHORE (Data that is associated with the semaphore is
* not valid.)
* \return SEM_SEMAPHORE_DELETED (Semaphore is in the process of being destroyed.)
*
* \see _sem_open
* \see _sem_close
* \see _sem_create
* \see _sem_post
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
*/
_mqx_uint _sem_open_fast
(
_mqx_uint sem_index,
pointer _PTR_ returned_sem_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
SEM_STRUCT_PTR sem_ptr;
register SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
_mqx_uint result;
_mqx_max_type tmp;
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_sem_open_fast, sem_index, returned_sem_ptr);
*returned_sem_ptr = NULL;
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_ERRORS
if (sem_component_ptr == NULL)
{
_KLOGX3(KLOG_sem_open_fast, MQX_COMPONENT_DOES_NOT_EXIST, 0);
return(MQX_COMPONENT_DOES_NOT_EXIST);
} /* Endif */
#endif
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX3(KLOG_sem_open_fast, MQX_INVALID_COMPONENT_BASE, 0);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
result = _name_find_internal_by_index(sem_component_ptr->NAME_TABLE_HANDLE,
sem_index, &tmp);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
if (result == NAME_NOT_FOUND)
{
_KLOGX3(KLOG_sem_open_fast, SEM_SEMAPHORE_NOT_FOUND, 0);
return(SEM_SEMAPHORE_NOT_FOUND);
} /* Endif */
_KLOGX3(KLOG_sem_open_fast, result, 0);
return(result);
} /* Endif */
#endif
sem_ptr = (SEM_STRUCT_PTR)tmp;
#if MQX_CHECK_ERRORS
if (sem_ptr->VALID != SEM_VALID)
{
/* Semaphore not valid */
_KLOGX3(KLOG_sem_open_fast, SEM_INVALID_SEMAPHORE, 0);
return(SEM_INVALID_SEMAPHORE);
} /* Endif */
#endif
#if MQX_COMPONENT_DESTRUCTION
if (sem_ptr->DELAYED_DESTROY)
{
/* Semaphore in delayed destroy state */
_KLOGX3(KLOG_sem_open_fast, SEM_SEMAPHORE_DELETED, 0);
return(SEM_SEMAPHORE_DELETED);
} /* Endif */
#endif
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)_mem_alloc_zero(
(_mem_size)sizeof(SEM_CONNECTION_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_connection_ptr == NULL)
{
_KLOGX3(KLOG_sem_open_fast, MQX_OUT_OF_MEMORY, 0);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(sem_connection_ptr, MEM_TYPE_SEMAPHORE_CONNECTION);
sem_connection_ptr->SEM_PTR = sem_ptr;
sem_connection_ptr->VALID = SEM_VALID;
sem_connection_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
*returned_sem_ptr = (pointer)sem_connection_ptr;
_KLOGX3(KLOG_sem_open_fast, MQX_OK, sem_connection_ptr);
return(MQX_OK);
} /* Endbody */
/*!
* \private
*
* \brief This function inserts a connection pointer by priority onto a queue.
*
* \param[in] queue_ptr The queue to insert the member into.
* \param[in] sem_connection_ptr The connection pointer to insert into the queue.
*/
void _sem_insert_priority_internal
(
QUEUE_STRUCT_PTR queue_ptr,
SEM_CONNECTION_STRUCT_PTR sem_connection_ptr
)
{ /* Body */
SEM_CONNECTION_STRUCT_PTR conn2_ptr;
SEM_CONNECTION_STRUCT_PTR conn_prev_ptr;
_mqx_uint count;
_mqx_uint priority;
conn_prev_ptr = (SEM_CONNECTION_STRUCT_PTR)((pointer)queue_ptr);
conn2_ptr = (SEM_CONNECTION_STRUCT_PTR)((pointer)queue_ptr->NEXT);
count = _QUEUE_GET_SIZE(queue_ptr) + 1;
priority = sem_connection_ptr->TD_PTR->MY_QUEUE->PRIORITY;
while (--count)
{
if (conn2_ptr->TD_PTR->MY_QUEUE->PRIORITY > priority)
{
break;
} /* Endif */
conn_prev_ptr = conn2_ptr;
conn2_ptr = (SEM_CONNECTION_STRUCT_PTR)conn2_ptr->NEXT;
} /* Endwhile */
_QUEUE_INSERT(queue_ptr, conn_prev_ptr, sem_connection_ptr);
} /* Endbody */
/*!
* \brief Opens a connection to the named semaphore.
*
* \param[in] name_ptr Name that identifies the semaphore that was created
* using _sem_create().
* \param[out] returned_sem_ptr Pointer to the semaphore handle, which is a
* connection to the semaphore.
*
* \return MQX_OK
* \return MQX_COMPONENT_DOES_NOT_EXIST (Semaphore component is not created.)
* \return MQX_INVALID_COMPONENT_BASE (Semaphore component data is not valid.)
* \return MQX_OUT_OF_MEMORY (MQX cannot allocate memory for the connection.)
* \return SEM_SEMAPHORE_NOT_FOUND (Name is not in the semaphore names database.)
* \return SEM_INVALID_SEMAPHORE (Data that is associated with the semaphore is
* not valid.)
* \return SEM_SEMAPHORE_DELETED (Semaphore is in the process of being destroyed.)
*
* \see _sem_open_fast
* \see _sem_close
* \see _sem_create
* \see _sem_post
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
*/
_mqx_uint _sem_open
(
char_ptr name_ptr,
pointer _PTR_ returned_sem_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
register SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
SEM_STRUCT_PTR sem_ptr;
register SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
_mqx_max_type tmp;
_mqx_uint result;
_GET_KERNEL_DATA(kernel_data);
_KLOGE3(KLOG_sem_open, name_ptr, returned_sem_ptr);
*returned_sem_ptr = NULL;
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
#if MQX_CHECK_ERRORS
if (sem_component_ptr == NULL)
{
_KLOGX3(KLOG_sem_open, MQX_COMPONENT_DOES_NOT_EXIST, 0);
return(MQX_COMPONENT_DOES_NOT_EXIST);
} /* Endif */
#endif
#if MQX_CHECK_VALIDITY
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX3(KLOG_sem_open, MQX_INVALID_COMPONENT_BASE, 0);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
#endif
result = _name_find_internal(sem_component_ptr->NAME_TABLE_HANDLE,
name_ptr, &tmp);
#if MQX_CHECK_ERRORS
if (result != MQX_OK)
{
if (result == NAME_NOT_FOUND)
{
_KLOGX3(KLOG_sem_open, SEM_SEMAPHORE_NOT_FOUND, NULL);
return(SEM_SEMAPHORE_NOT_FOUND);
} /* Endif */
_KLOGX3(KLOG_sem_open, result, 0);
return(result);
} /* Endif */
#endif
sem_ptr = (SEM_STRUCT_PTR)tmp;
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
/* Semaphore not valid */
_KLOGX2(KLOG_sem_open, SEM_INVALID_SEMAPHORE);
return(SEM_INVALID_SEMAPHORE);
} /* Endif */
#endif
#if MQX_COMPONENT_DESTRUCTION
if (sem_ptr->DELAYED_DESTROY)
{
/* Semaphore in delayed destroy state */
_KLOGX3(KLOG_sem_open, SEM_SEMAPHORE_DELETED, 0);
return(SEM_SEMAPHORE_DELETED);
} /* Endif */
#endif
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
_mem_alloc_zero((_mem_size)sizeof(SEM_CONNECTION_STRUCT));
#if MQX_CHECK_MEMORY_ALLOCATION_ERRORS
if (sem_connection_ptr == NULL)
{
_KLOGX3(KLOG_sem_open, MQX_OUT_OF_MEMORY, 0);
return(MQX_OUT_OF_MEMORY);
} /* Endif */
#endif
_mem_set_type(sem_connection_ptr, MEM_TYPE_SEMAPHORE_CONNECTION);
sem_connection_ptr->SEM_PTR = sem_ptr;
sem_connection_ptr->VALID = SEM_VALID;
sem_connection_ptr->TD_PTR = kernel_data->ACTIVE_PTR;
*returned_sem_ptr = (pointer)sem_connection_ptr;
_KLOGX3(KLOG_sem_open, MQX_OK, sem_connection_ptr);
return(MQX_OK);
} /* Endbody */
/*!
* \brief Returns a semaphore to the semaphore, so another task may use it.
*
* MQX gives the semaphore to the first waiting task and puts the task in the
* task's ready queue.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Semaphore is strict and sem_handle was obtained byanother task.)
* \return SEM_CANNOT_POST (Semaphore is strict and the task has not first waited
* for the semaphore.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle represents a semaphore that is no
* longer valid.)
* \return SEM_INVALID_SEMAPHORE_COUNT (Semaphore data are corrupted.)
*
* \warning Might put a task in its ready queue.
* \warning For a strict semaphore, cannot be called from an ISR (ISR can call
* the function for a non-strict semaphore).
*
* \see _sem_open
* \see _sem_open_fast
* \see _sem_get_wait_count
* \see _sem_get_value
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
*/
_mqx_uint _sem_post
(
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 */
/*!
* \brief Used during task destruction to free up any semaphore resources owned
* by this task.
*
* \param[in] td_ptr The task being destroyed.
*/
void _sem_cleanup
(
TD_STRUCT_PTR td_ptr
)
{ /* Body */
SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
SEM_CONNECTION_STRUCT_PTR connection_ptr;
SEM_STRUCT_PTR sem_ptr;
connection_ptr = _mem_get_next_block_internal(td_ptr, NULL);
while (connection_ptr)
{
if ((connection_ptr->VALID == SEM_VALID) &&
(connection_ptr->TD_PTR == td_ptr) )
{
sem_ptr = connection_ptr->SEM_PTR;
if (sem_ptr->VALID == SEM_VALID)
{
/* Check if the connection is on the queue */
_int_disable();
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
((pointer)sem_ptr->WAITING_TASKS.NEXT);
while (sem_connection_ptr != (pointer)&sem_ptr->WAITING_TASKS.NEXT)
{
if (sem_connection_ptr == connection_ptr)
{
/* Connection is queued, so dequeue it */
_QUEUE_REMOVE(&sem_ptr->WAITING_TASKS, connection_ptr);
break;
}/* Endif */
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
sem_connection_ptr->NEXT;
} /* Endwhile */
if (sem_ptr->POLICY & SEM_STRICT)
{
while (connection_ptr->POST_STATE)
{
_sem_post(connection_ptr);
} /* Endwhile */
}/* Endif */
_int_enable();
}/* Endif */
} /* Endif */
connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
_mem_get_next_block_internal(td_ptr, connection_ptr);
} /* Endwhile */
} /* Endbody */
/*!
* \brief Tests the semaphore component for validity and consistency.
*
* The function does the following:
* \li Verifies semaphore component data.
* \li Verifies the integrity of the entries in the semaphore names database.
* \li For each semaphore, checks: validity of data (VALID field), integrity of
* the queue of waiting tasks and integrity of the queue of tasks that have the
* semaphore.
*
* \param[out] sem_error_ptr Pointer to the semaphore that has an error (NULL if
* no errors are found).
*
* \return MQX_OK (No errors were found.)
* \return MQX_CORRUPT_QUEUE (Error was found in a semaphore queue.)
* \return MQX_INVALID_COMPONENT_BASE (Error was found in semaphore component data.)
* \return SEM_INVALID_SEMAPHORE (Error was found in semaphore data.)
*
* \warning Disables and enables interrupts.
*
* \see _sem_close
* \see _sem_create
* \see _sem_create_fast
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
*/
_mqx_uint _sem_test
(
pointer _PTR_ sem_error_ptr
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
SEM_COMPONENT_STRUCT_PTR sem_component_ptr;
SEM_STRUCT_PTR sem_ptr;
pointer table_ptr;
_mqx_max_type data;
_mqx_uint result;
_mqx_uint i;
_GET_KERNEL_DATA(kernel_data);
_KLOGE2(KLOG_sem_test, sem_error_ptr);
*sem_error_ptr = NULL;
sem_component_ptr = (SEM_COMPONENT_STRUCT_PTR)
kernel_data->KERNEL_COMPONENTS[KERNEL_SEMAPHORES];
if (sem_component_ptr == NULL)
{
_KLOGX3(KLOG_sem_test, MQX_OK, 0);
return(MQX_OK);
} /* Endif */
if (sem_component_ptr->VALID != SEM_VALID)
{
_KLOGX3(KLOG_sem_test, MQX_INVALID_COMPONENT_BASE, 0);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
_int_disable();
/* Test the semaphore name table */
result = _name_test_internal((NAME_COMPONENT_STRUCT_PTR)
sem_component_ptr->NAME_TABLE_HANDLE, &table_ptr, sem_error_ptr);
_int_enable();
if (result != MQX_OK)
{
_KLOGX3(KLOG_sem_test, MQX_INVALID_COMPONENT_BASE, *sem_error_ptr);
return(MQX_INVALID_COMPONENT_BASE);
} /* Endif */
i = 0;
while (TRUE)
{
_int_disable();
result = _name_find_internal_by_index(
sem_component_ptr->NAME_TABLE_HANDLE, i++, &data);
if (result != MQX_OK)
{
result = MQX_OK;
break;
} /* Endif */
sem_ptr = (SEM_STRUCT_PTR)data;
if (sem_ptr->VALID != SEM_VALID)
{
result = SEM_INVALID_SEMAPHORE;
break;
} /* Endif */
result = _queue_test(&sem_ptr->WAITING_TASKS, sem_error_ptr);
if (result != MQX_OK)
{
break;
} /* Endif */
result = _queue_test(&sem_ptr->OWNING_TASKS, sem_error_ptr);
if (result != MQX_OK)
{
break;
} /* Endif */
_int_enable();
} /* Endwhile */
_int_enable();
_KLOGX3(KLOG_sem_test, result, *sem_error_ptr);
return(result);
} /* Endbody */
/*!
* \brief Gets the value of the semaphore counter; that is, the number of
* subsequent requests that can get the semaphore without waiting.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
*
* \return Current value of the semaphore counter (success).
* \return MAX_MQX_UINT (failure)
*
* \warning On failure, calls _task_set_error() to set one of the following task
* error codes:
* \li SEM_INVALID_SEMAPHORE_HANDLE (Sem_ptr is not a valid semaphore handle.)
* \li SEM_INVALID_SEMAPHORE (Sem_ptr does not point to a valid semaphore.)
*
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_get_wait_count
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
* \see _task_set_error
*/
_mqx_uint _sem_get_value
(
pointer users_sem_ptr
)
{ /* Body */
register SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
register SEM_STRUCT_PTR sem_ptr;
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)users_sem_ptr;
#if MQX_CHECK_VALIDITY
if (sem_connection_ptr->VALID != SEM_VALID)
{
_task_set_error(SEM_INVALID_SEMAPHORE_HANDLE);
return(MAX_MQX_UINT);
} /* Endif */
#endif
sem_ptr = sem_connection_ptr->SEM_PTR;
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
_task_set_error(SEM_INVALID_SEMAPHORE);
return(MAX_MQX_UINT);
} /* Endif */
#endif
return(sem_ptr->COUNT);
} /* Endbody */
/*!
* \brief Gets the number of tasks that are waiting for the semaphore.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
*
* \return Number of tasks waiting for the semaphore (success).
* \return MAX_MQX_UINT (failure)
*
* \warning On failure, calls _task_set_error() to set one of the task error codes
* described for _sem_get_value().
*
* \see _sem_get_value
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
* \see _task_set_error
*/
_mqx_uint _sem_get_wait_count
(
pointer users_sem_ptr
)
{ /* Body */
register SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
register SEM_STRUCT_PTR sem_ptr;
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)users_sem_ptr;
#if MQX_CHECK_VALIDITY
if (sem_connection_ptr->VALID != SEM_VALID)
{
_task_set_error(SEM_INVALID_SEMAPHORE_HANDLE);
return(MAX_MQX_UINT);
} /* Endif */
#endif
sem_ptr = sem_connection_ptr->SEM_PTR;
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
_task_set_error(SEM_INVALID_SEMAPHORE);
return(MAX_MQX_UINT);
} /* Endif */
#endif
return(_QUEUE_GET_SIZE(&(sem_ptr->WAITING_TASKS)));
} /* Endbody */
/*!
* \private
*
* \brief This function waits for a semaphore to become available. If one is not
* the task is queued according to the queueing policy for this semaphore.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or
* _sem_open_fast().
* \param[in] tick_ptr One of the following:
* \li Pointer to the maximum number of ticks to wait.
* \li NULL (Unlimited wait.)
* \param[in] ticks_are_absolute Specifies whether the wait time specified in
* ticks represents absolute or relative time.
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_EDEADLK (Function was aborted to prevent deadlock: the task has
* all the semaphore locks and, since the semaphore is strict, the task cannot
* post to "wake" itself.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Sem_handle was obtained by another task.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle is for a semaphore that is no longer
* valid.)
* \return SEM_SEMAPHORE_DELETED (MQX is in the process of destroying the semaphore.)
* \return SEM_WAIT_TIMEOUT (Timeout expired before the task can get the semaphore.)
*/
_mqx_uint _sem_wait_internal
(
pointer users_sem_ptr,
MQX_TICK_STRUCT_PTR tick_ptr,
boolean ticks_are_absolute
)
{ /* Body */
KERNEL_DATA_STRUCT_PTR kernel_data;
TD_STRUCT_PTR td_ptr;
SEM_STRUCT_PTR sem_ptr;
register SEM_CONNECTION_STRUCT_PTR sem_connection_ptr;
register SEM_CONNECTION_STRUCT_PTR list_connection_ptr;
SEM_CONNECTION_STRUCT_PTR saved_connection_ptr;
_mqx_uint priority;
_GET_KERNEL_DATA(kernel_data);
#if MQX_CHECK_ERRORS
if (kernel_data->IN_ISR)
{
return(MQX_CANNOT_CALL_FUNCTION_FROM_ISR);
} /* Endif */
#endif
sem_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)users_sem_ptr;
#if MQX_CHECK_VALIDITY
if (sem_connection_ptr->VALID != SEM_VALID)
{
return(SEM_INVALID_SEMAPHORE_HANDLE);
} /* Endif */
#endif
sem_ptr = sem_connection_ptr->SEM_PTR;
td_ptr = kernel_data->ACTIVE_PTR;
#if MQX_CHECK_ERRORS
if (sem_connection_ptr->TD_PTR != td_ptr)
{
/* Only OPENING task can wait on the semaphore */
return(SEM_INVALID_SEMAPHORE_HANDLE);
} /* Endif */
#endif
_INT_DISABLE();
#if MQX_CHECK_VALIDITY
if (sem_ptr->VALID != SEM_VALID)
{
_int_enable();
return(SEM_INVALID_SEMAPHORE);
} /* Endif */
#endif
if (sem_ptr->COUNT == 0)
{
/* Must wait for a semaphore to become available */
if (sem_ptr->POLICY & SEM_STRICT)
{
/*
* First check for deadlock... See if this task already
* owns all the semaphores, thus cannot post to wake itself up
*/
if (sem_connection_ptr->POST_STATE == sem_ptr->MAX_COUNT)
{
_int_enable();
return(MQX_EDEADLK);
} /* Endif */
/*
* May need to raise priorities of one task with semaphore,
* If the current task has a higher priority.
*/
if ((sem_ptr->POLICY & SEM_PRIORITY_INHERITANCE) &&
(_QUEUE_GET_SIZE(&sem_ptr->OWNING_TASKS) > 0))
{
/* Find owning task with highest priority */
list_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
((pointer)sem_ptr->OWNING_TASKS.NEXT);
saved_connection_ptr = list_connection_ptr;
priority = kernel_data->LOWEST_TASK_PRIORITY;
while ((pointer)list_connection_ptr !=
(pointer)&sem_ptr->OWNING_TASKS)
{
if (list_connection_ptr->TD_PTR->MY_QUEUE->PRIORITY < priority)
{
priority = list_connection_ptr->TD_PTR->MY_QUEUE->PRIORITY;
saved_connection_ptr = list_connection_ptr;
} /* Endif */
list_connection_ptr = (SEM_CONNECTION_STRUCT_PTR)
list_connection_ptr->NEXT;
} /* Endwhile */
if (priority > td_ptr->HOME_QUEUE->PRIORITY)
{
if (priority > td_ptr->MY_QUEUE->PRIORITY)
{
/* Not high enough, boost the tasks priority */
_sched_boost_priority_internal(saved_connection_ptr->TD_PTR,
(_mqx_uint)td_ptr->MY_QUEUE->PRIORITY);
} /* Endif */
saved_connection_ptr->BOOSTED++;
} /* Endif */
} /* Endif */
} /* Endif */
if (sem_ptr->POLICY & SEM_PRIORITY_QUEUEING)
{
/*
* We must insert the waiting task into the waiting list in order
* of the priority of the waiting task.
*/
_sem_insert_priority_internal(&sem_ptr->WAITING_TASKS, sem_connection_ptr);
}
else
{
/* Enqueue at end */
_QUEUE_ENQUEUE(&sem_ptr->WAITING_TASKS, sem_connection_ptr);
} /* Endif */
/* Now put the task to sleep */
td_ptr->STATE = SEM_BLOCKED;
td_ptr->INFO = SEM_WANT_SEMAPHORE;
/* Indicate wanting semaphore */
if (tick_ptr)
{
if (ticks_are_absolute)
{
_time_delay_until(tick_ptr);
}
else
{
_time_delay_for(tick_ptr);
} /* Endif */
#if MQX_COMPONENT_DESTRUCTION
if (sem_ptr->VALID != SEM_VALID)
{
_int_enable();
return(SEM_SEMAPHORE_DELETED);
} /* Endif */
#endif
_QUEUE_REMOVE(&sem_ptr->WAITING_TASKS, sem_connection_ptr);
if (td_ptr->INFO != SEM_AVAILABLE)
{
td_ptr->INFO = 0;
_INT_ENABLE();
return(SEM_WAIT_TIMEOUT);
} /* Endif */
}
else
{
_task_block();
#if MQX_COMPONENT_DESTRUCTION
if (sem_ptr->VALID != SEM_VALID)
{
_int_enable();
return(SEM_SEMAPHORE_DELETED);
} /* Endif */
#endif
_QUEUE_REMOVE(&sem_ptr->WAITING_TASKS, sem_connection_ptr);
#if MQX_COMPONENT_DESTRUCTION
if (td_ptr->INFO != SEM_AVAILABLE)
{
td_ptr->INFO = 0;
_INT_ENABLE();
return(SEM_SEMAPHORE_DELETED);
} /* Endif */
#endif
} /* Endif */
}
else
{
--sem_ptr->COUNT;
} /* Endif */
if (sem_ptr->POLICY & SEM_STRICT)
{
if (sem_connection_ptr->POST_STATE == 0)
{
_QUEUE_ENQUEUE(&sem_ptr->OWNING_TASKS, sem_connection_ptr);
} /* Endif */
sem_connection_ptr->POST_STATE++; /* # of posts allowed to do */
} /* Endif */
_INT_ENABLE();
return(MQX_OK);
} /* Endbody */
/*!
* \brief Wait for the semaphore for the specified number of milliseconds.
*
* If the task cannot get the semaphore, MQX queues the task according to the
* semaphore's queuing policy, which is set when the semaphore is created.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
* \param[in] timeout One of the following:
* \li Maximum number of milliseconds to wait.
* \li 0 (Unlimited wait.)
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_EDEADLK (Function was aborted to prevent deadlock: the task has
* all the semaphore locks and, since the semaphore is strict, the task cannot
* post to "wake" itself.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Sem_handle was obtained by another task.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle is for a semaphore that is no longer
* valid.)
* \return SEM_SEMAPHORE_DELETED (MQX is in the process of destroying the semaphore.)
* \return SEM_WAIT_TIMEOUT (Timeout expired before the task can get the semaphore.)
*
* \warning Might block the calling task.
* \warning Cannot be called from an ISR.
*
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_wait_until
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_get_wait_count
* \see _sem_get_value
* \see _sem_create
* \see _sem_create_fast
* \see MQX_TICK_STRUCT
*/
_mqx_uint _sem_wait
(
pointer users_sem_ptr,
uint_32 timeout
)
{ /* Body */
/* TIME_STRUCT time; */
MQX_TICK_STRUCT ticks;
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_mqx_uint result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE3(KLOG_sem_wait, users_sem_ptr, timeout);
if (timeout)
{
/* Convert milliseconds to ticks */
/* time.MILLISECONDS = timeout % 1000; */
/* time.SECONDS = timeout / 1000; */
/* */
/* PSP_TIME_TO_TICKS(&time, &ticks); */
PSP_MILLISECONDS_TO_TICKS_QUICK(timeout, &ticks);
result = _sem_wait_internal(users_sem_ptr, &ticks, FALSE);
}
else
{
result = _sem_wait_internal(users_sem_ptr, NULL, FALSE);
} /* Endif */
_KLOGX2(KLOG_sem_wait, result);
return(result);
} /* Endbody */
/*!
* \brief Wait for the semaphore for the specified number of ticks (in tick time).
*
* If the task cannot get the semaphore, MQX queues the task according to the
* semaphore's queuing policy, which is set when the semaphore is created.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
* \param[in] tick_ptr One of the following:
* \li Pointer to the maximum number of ticks to wait.
* \li NULL (Unlimited wait.)
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_EDEADLK (Function was aborted to prevent deadlock: the task has
* all the semaphore locks and, since the semaphore is strict, the task cannot
* post to "wake" itself.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Sem_handle was obtained by another task.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle is for a semaphore that is no longer
* valid.)
* \return SEM_SEMAPHORE_DELETED (MQX is in the process of destroying the semaphore.)
* \return SEM_WAIT_TIMEOUT (Timeout expired before the task can get the semaphore.)
*
* \warning Might block the calling task.
* \warning Cannot be called from an ISR.
*
* \see _sem_wait
* \see _sem_wait_ticks
* \see _sem_wait_until
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_get_wait_count
* \see _sem_get_value
* \see _sem_create
* \see _sem_create_fast
* \see MQX_TICK_STRUCT
*/
_mqx_uint _sem_wait_for
(
pointer users_sem_ptr,
MQX_TICK_STRUCT_PTR tick_ptr
)
{ /* Body */
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_mqx_uint result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE3(KLOG_sem_wait_for, users_sem_ptr, tick_ptr);
result = _sem_wait_internal(users_sem_ptr, tick_ptr, FALSE);
_KLOGX2(KLOG_sem_wait_for, result);
return(result);
} /* Endbody */
/*!
* \brief Wait for the semaphore for the specified number of ticks.
*
* If the task cannot get the semaphore, MQX queues the task according to the
* semaphore's queuing policy, which is set when the semaphore is created.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
* \param[in] timeout_in_ticks One of the following:
* \li Maximum number of ticks to wait.
* \li 0 (Unlimited wait.)
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_EDEADLK (Function was aborted to prevent deadlock: the task has
* all the semaphore locks and, since the semaphore is strict, the task cannot
* post to "wake" itself.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Sem_handle was obtained by another task.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle is for a semaphore that is no longer
* valid.)
* \return SEM_SEMAPHORE_DELETED (MQX is in the process of destroying the semaphore.)
* \return SEM_WAIT_TIMEOUT (Timeout expired before the task can get the semaphore.)
*
* \warning Might block the calling task.
* \warning Cannot be called from an ISR.
*
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_until
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_get_wait_count
* \see _sem_get_value
* \see _sem_create
* \see _sem_create_fast
* \see MQX_TICK_STRUCT
*/
_mqx_uint _sem_wait_ticks
(
pointer users_sem_ptr,
_mqx_uint timeout_in_ticks
)
{ /* Body */
MQX_TICK_STRUCT ticks;
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_mqx_uint result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE3(KLOG_sem_wait_ticks, users_sem_ptr, timeout_in_ticks);
if (timeout_in_ticks)
{
ticks = _mqx_zero_tick_struct;
PSP_GET_ELEMENT_FROM_TICK_STRUCT(&ticks, 0) = timeout_in_ticks;
result = _sem_wait_internal(users_sem_ptr, &ticks, FALSE);
}
else
{
result = _sem_wait_internal(users_sem_ptr, NULL, FALSE);
} /* Endif */
_KLOGX2(KLOG_sem_wait_ticks, result);
return(result);
} /* Endbody */
/*!
* \brief Wait for the semaphore until the specified time (in tick time).
*
* If the task cannot get the semaphore, MQX queues the task according to the
* semaphore's queuing policy, which is set when the semaphore is created.
*
* \param[in] users_sem_ptr Semaphore handle from _sem_open() or _sem_open_fast().
* \param[in] tick_ptr One of the following:
* \li Pointer to the time (in tick time) until which to wait.
* \li NULL (Unlimited wait.)
*
* \return MQX_OK
* \return MQX_CANNOT_CALL_FUNCTION_FROM_ISR (Function cannot be called from an ISR.)
* \return MQX_EDEADLK (Function was aborted to prevent deadlock: the task has
* all the semaphore locks and, since the semaphore is strict, the task cannot
* post to "wake" itself.)
* \return SEM_INVALID_SEMAPHORE_HANDLE (One of the following:
* \li Sem_handle is not a valid semaphore handle.
* \li Sem_handle was obtained by another task.)
* \return SEM_INVALID_SEMAPHORE (Sem_handle is for a semaphore that is no longer
* valid.)
* \return SEM_SEMAPHORE_DELETED (MQX is in the process of destroying the semaphore.)
* \return SEM_WAIT_TIMEOUT (Timeout expired before the task can get the semaphore.)
*
* \warning Might block the calling task.
* \warning Cannot be called from an ISR.
*
* \see _sem_wait
* \see _sem_wait_for
* \see _sem_wait_ticks
* \see _sem_open
* \see _sem_open_fast
* \see _sem_post
* \see _sem_get_wait_count
* \see _sem_get_value
* \see _sem_create
* \see _sem_create_fast
* \see MQX_TICK_STRUCT
*/
_mqx_uint _sem_wait_until
(
pointer users_sem_ptr,
MQX_TICK_STRUCT_PTR tick_ptr
)
{ /* Body */
_KLOGM(KERNEL_DATA_STRUCT_PTR kernel_data;)
_mqx_uint result;
_KLOGM(_GET_KERNEL_DATA(kernel_data);)
_KLOGE3(KLOG_sem_wait_until, users_sem_ptr, tick_ptr);
result = _sem_wait_internal(users_sem_ptr, tick_ptr, TRUE);
_KLOGX2(KLOG_sem_wait_until, result);
return(result);
} /* Endbody */
#endif /* MQX_USE_SEMAPHORES */
/* EOF */