Skip to content

Commit

Permalink
Fix #293, Expand API for object queries
Browse files Browse the repository at this point in the history
Implement OS_GetResourceName, OS_ForEachObjectByType
  • Loading branch information
jphickey committed May 18, 2020
1 parent c2bcebb commit 36ae153
Show file tree
Hide file tree
Showing 7 changed files with 415 additions and 138 deletions.
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

0 comments on commit 36ae153

Please sign in to comment.