Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix #293, Expand API for object queries #469

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 47 additions & 1 deletion src/os/inc/osapi-os-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,13 @@
/** @brief Upper limit for OSAL task priorities */
#define OS_MAX_TASK_PRIORITY 255

/**
* @brief Constant that may be passed to OS_ForEachObject()/OS_ForEachObjectOfType() to match any
* creator (i.e. get all objects)
*/
#define OS_OBJECT_CREATOR_ANY 0


/** @defgroup OSSemaphoreStates OSAL Semaphore State Defines
* @{
*/
Expand Down Expand Up @@ -278,6 +285,24 @@ void OS_ApplicationExit(int32 Status);
* @{
*/

/*-------------------------------------------------------------------------------------*/
/**
* @brief Obtain the name of an object given an arbitrary object ID
*
* All OSAL resources generally have a name associated with them. This
* allows application code to retrieve the name of any valid OSAL object ID.
*
* @param[in] object_id The object ID to operate on
* @param[out] buffer Buffer in which to store the name
* @param[in] buffer_size Size of the output storage buffer
*
* @returns #OS_SUCCESS if successful
* #OS_ERR_INVALID_ID if the passed-in ID is not a valid OSAL ID
* #OS_INVALID_POINTER if the passed-in buffer is invalid
* #OS_ERR_NAME_TOO_LONG if the name will not fit in the buffer provided
*/
int32 OS_GetResourceName(uint32 id, char *buffer, uint32 buffer_size);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Obtain the type of an object given an arbitrary object ID
Expand Down Expand Up @@ -315,12 +340,33 @@ int32 OS_ConvertToArrayIndex (uint32 object_id, uint32 *ArrayIndex);
/**
* @brief call the supplied callback function for all valid object IDs
*
* Loops through all defined OSAL objects and calls callback_ptr on each one
* Loops through all defined OSAL objects of all types and calls callback_ptr on each one
* If creator_id is nonzero then only objects with matching creator id are processed.
*
* @param[in] creator_id Filter objects to those created by a specific task
* This may be passed as OS_OBJECT_CREATOR_ANY to return all objects
* @param[in] callback_ptr Function to invoke for each matching object ID
* @param[in] callback_arg Opaque Argument to pass to callback function
*/
void OS_ForEachObject (uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg);
/**@}*/

/*-------------------------------------------------------------------------------------*/
/**
* @brief call the supplied callback function for valid object IDs of a specific type
*
* Loops through all defined OSAL objects of a specific type and calls callback_ptr on each one
* If creator_id is nonzero then only objects with matching creator id are processed.
*
* @param[in] objtype The type of objects to iterate
* @param[in] creator_id Filter objects to those created by a specific task
* This may be passed as OS_OBJECT_CREATOR_ANY to return all objects
* @param[in] callback_ptr Function to invoke for each matching object ID
* @param[in] callback_arg Opaque Argument to pass to callback function
*/
void OS_ForEachObjectOfType (uint32 objtype, uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg);


/** @defgroup OSAPITask OSAL Task APIs
* @{
*/
Expand Down
32 changes: 32 additions & 0 deletions src/os/shared/inc/os-shared-idmap.h
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,38 @@ int32 OS_Unlock_Global_Impl(uint32 idtype);
corresponding index within the local tables.
*/

/*----------------------------------------------------------------
Function: OS_ObjectIdToSerialNumber

Purpose: Obtain the serial number component of a generic OSAL Object ID
------------------------------------------------------------------*/
static inline uint32 OS_ObjectIdToSerialNumber_Impl(uint32 id)
{
return (id & OS_OBJECT_INDEX_MASK);
}

/*----------------------------------------------------------------
Function: OS_ObjectIdToType

Purpose: Obtain the object type component of a generic OSAL Object ID
------------------------------------------------------------------*/
static inline uint32 OS_ObjectIdToType_Impl(uint32 id)
{
return (id >> OS_OBJECT_TYPE_SHIFT);
}


/*----------------------------------------------------------------
Function: OS_ObjectIdCompose

Purpose: Convert an object serial number and resource type into an external 32-bit OSAL ID
------------------------------------------------------------------*/
static inline void OS_ObjectIdCompose_Impl(uint32 idtype, uint32 idserial, uint32 *result)
{
*result = (idtype << OS_OBJECT_TYPE_SHIFT) | idserial;
}


/*----------------------------------------------------------------
Function: OS_GetMaxForObjectType

Expand Down
220 changes: 135 additions & 85 deletions src/os/shared/src/osapi-idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -112,47 +112,6 @@ int32 OS_ObjectIdInit(void)
return OS_SUCCESS;
} /* end OS_ObjectIdInit */

/*----------------------------------------------------------------
*
* Function: OS_ObjectIdMap
*
* Purpose: Local helper routine, not part of OSAL API.
*
*-----------------------------------------------------------------*/
int32 OS_ObjectIdMap(uint32 idtype, uint32 idvalue, uint32 *result)
{
*result = (idtype << OS_OBJECT_TYPE_SHIFT) | idvalue;

if (idtype == OS_OBJECT_TYPE_UNDEFINED ||
(idvalue & ~OS_OBJECT_INDEX_MASK) != 0)
{
return OS_ERR_INVALID_ID;
}

return OS_SUCCESS;
} /* end OS_ObjectIdMap */


/*----------------------------------------------------------------
*
* Function: OS_ObjectIdUnMap
*
* Purpose: Local helper routine, not part of OSAL API.
*
*-----------------------------------------------------------------*/
int32 OS_ObjectIdUnMap(uint32 id, uint32 idtype, uint32 *idvalue)
{
*idvalue = id & OS_OBJECT_INDEX_MASK;

if ((id >> OS_OBJECT_TYPE_SHIFT) != idtype)
{
return OS_ERR_INVALID_ID;
}

return OS_SUCCESS;
} /* end OS_ObjectIdUnMap */


/*----------------------------------------------------------------
*
* Function: OS_GetMaxForObjectType
Expand Down Expand Up @@ -530,7 +489,7 @@ int32 OS_ObjectIdFindNext(uint32 idtype, uint32 *array_index, OS_common_record_t

if(return_code == OS_SUCCESS)
{
return_code = OS_ObjectIdMap(idtype, idvalue, &obj->active_id);
OS_ObjectIdCompose_Impl(idtype, idvalue, &obj->active_id);

/* Ensure any data in the record has been cleared */
obj->name_entry = NULL;
Expand Down Expand Up @@ -575,24 +534,43 @@ int32 OS_ObjectIdFindNext(uint32 idtype, uint32 *array_index, OS_common_record_t
* for use as an array index. The array index will be in the range of:
* 0 <= ArrayIndex < OS_MAX_<OBJTYPE>
*
* If the passed-in ID type is OS_OBJECT_TYPE_UNDEFINED, then any type
* is allowed.
*
* returns: If the passed-in ID is not of the proper type, OS_ERROR is returned
* Otherwise OS_SUCCESS is returned.
*
*-----------------------------------------------------------------*/
int32 OS_ObjectIdToArrayIndex(uint32 idtype, uint32 id, uint32 *ArrayIndex)
{
uint32 max_id;
uint32 obj_index;
uint32 actual_type;
int32 return_code;

max_id = OS_GetMaxForObjectType(idtype);
if (max_id == 0)
obj_index = OS_ObjectIdToSerialNumber_Impl(id);
actual_type = OS_ObjectIdToType_Impl(id);

/*
* If requested by the caller, enforce that the ID is of the correct type.
* If the caller passed OS_OBJECT_TYPE_UNDEFINED, then anything is allowed.
*/
if (idtype != OS_OBJECT_TYPE_UNDEFINED && actual_type != idtype)
{
return_code = OS_ERR_INVALID_ID;
return_code = OS_ERR_INVALID_ID;
}
else
{
return_code = OS_ObjectIdUnMap(id, idtype, &id);
*ArrayIndex = id % max_id;
max_id = OS_GetMaxForObjectType(actual_type);
if (max_id == 0)
{
return_code = OS_ERR_INVALID_ID;
}
else
{
return_code = OS_SUCCESS;
*ArrayIndex = obj_index % max_id;
}
}

return return_code;
Expand Down Expand Up @@ -962,21 +940,8 @@ int32 OS_ObjectIdAllocateNew(uint32 idtype, const char *name, uint32 *array_inde
*-----------------------------------------------------------------*/
int32 OS_ConvertToArrayIndex(uint32 object_id, uint32 *ArrayIndex)
{
uint32 max_id;
int32 return_code;

max_id = OS_GetMaxForObjectType(object_id >> OS_OBJECT_TYPE_SHIFT);
if (max_id == 0)
{
return_code = OS_ERR_INCORRECT_OBJ_TYPE;
}
else
{
*ArrayIndex = (object_id & OS_OBJECT_INDEX_MASK) % max_id;
return_code = OS_SUCCESS;
}

return return_code;
/* just pass to the generic internal conversion routine */
return OS_ObjectIdToArrayIndex(OS_OBJECT_TYPE_UNDEFINED, object_id, ArrayIndex);
} /* end OS_ConvertToArrayIndex */


Expand All @@ -989,40 +954,73 @@ int32 OS_ConvertToArrayIndex(uint32 object_id, uint32 *ArrayIndex)
*
*-----------------------------------------------------------------*/
void OS_ForEachObject (uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg)
{
uint32 idtype;

for (idtype = 0; idtype < OS_OBJECT_TYPE_USER; ++idtype)
{
OS_ForEachObjectOfType(idtype, creator_id, callback_ptr, callback_arg);
}
} /* end OS_ForEachObject */

/*-----------------------------------------------------------------
*
* Function: OS_ForEachObjectOfType
*
* Purpose: Implemented per public OSAL API
* See description in API and header file for detail
*
*-----------------------------------------------------------------*/
void OS_ForEachObjectOfType (uint32 idtype, uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg)
{
uint32 obj_index;
uint32 obj_max;
uint32 obj_id;
uint32 idtype;

for (idtype = 0; idtype < OS_OBJECT_TYPE_USER; ++idtype)
obj_max = OS_GetMaxForObjectType(idtype);
if (obj_max > 0)
{
obj_max = OS_GetMaxForObjectType(idtype);
if (obj_max > 0)
obj_index = OS_GetBaseForObjectType(idtype);
OS_Lock_Global_Impl(idtype);
while (obj_max > 0)
{
OS_Lock_Global_Impl(idtype);
obj_index = OS_GetBaseForObjectType(idtype);
while (obj_max > 0)
/*
* Check if the obj_id is both valid and matches
* the specified creator_id
*/
obj_id = OS_common_table[obj_index].active_id;
if (obj_id != 0 && creator_id != OS_OBJECT_CREATOR_ANY &&
OS_common_table[obj_index].creator != creator_id)
{
obj_id = OS_common_table[obj_index].active_id;
if (obj_id != 0 && (creator_id == 0 || OS_common_table[obj_index].creator == creator_id))
{
/*
* Handle the object - Note that we must UN-lock before callback.
* The callback function might lock again in a different manner.
*/
OS_Unlock_Global_Impl(idtype);
(*callback_ptr)(obj_id, callback_arg);
OS_Lock_Global_Impl(idtype);
/* valid object but not a creator match -
* skip the callback for this object */
obj_id = 0;
}

}
++obj_index;
--obj_max;
if (obj_id != 0)
{
/*
* Invoke Callback for the object, which must be done
* while the global table is unlocked.
*
* Note this means by the time the callback is done,
* the object could have been deleted by another task.
*
* But this must not invoke a callback with a locked table,
* as the callback function might call other OSAL functions,
* which could deadlock.
*/
OS_Unlock_Global_Impl(idtype);
(*callback_ptr)(obj_id, callback_arg);
OS_Lock_Global_Impl(idtype);
}
OS_Unlock_Global_Impl(idtype);

++obj_index;
--obj_max;
}
OS_Unlock_Global_Impl(idtype);
}
} /* end OS_ForEachObject */
} /* end OS_ForEachObjectOfType */

/*----------------------------------------------------------------
*
Expand All @@ -1034,6 +1032,58 @@ void OS_ForEachObject (uint32 creator_id, OS_ArgCallback_t callback_ptr, void *c
*-----------------------------------------------------------------*/
uint32 OS_IdentifyObject (uint32 object_id)
{
return (object_id >> OS_OBJECT_TYPE_SHIFT);
return OS_ObjectIdToType_Impl(object_id);
} /* end OS_IdentifyObject */

/*----------------------------------------------------------------
*
* Function: OS_GetResourceName
*
* Purpose: Implemented per public OSAL API
* See description in API and header file for detail
*
*-----------------------------------------------------------------*/
int32 OS_GetResourceName(uint32 id, char *buffer, uint32 buffer_size)
{
uint32 idtype;
OS_common_record_t *record;
int32 return_code;
uint32 name_len;
uint32 local_id;

/* sanity check the passed-in buffer and size */
if (buffer == NULL || buffer_size == 0)
{
return OS_INVALID_POINTER;
}

/*
* Initially set the output string to empty.
* This avoids undefined behavior in case the function fails
* and the caller does not check the return code.
*/
buffer[0] = 0;

idtype = OS_ObjectIdToType_Impl(id);
return_code = OS_ObjectIdGetById(OS_LOCK_MODE_GLOBAL, idtype, id, &local_id, &record);
if (return_code == OS_SUCCESS)
{
if (record->name_entry != NULL)
{
name_len = strlen(record->name_entry);
if (buffer_size <= name_len)
{
/* indicates the name does not fit into supplied buffer */
return_code = OS_ERR_NAME_TOO_LONG;
name_len = buffer_size - 1;
}
memcpy(buffer, record->name_entry, name_len);
buffer[name_len] = 0;
}
OS_Unlock_Global_Impl(idtype);
}

return return_code;
} /* end OS_GetResourceName */


Loading