diff --git a/src/os/inc/osapi-os-core.h b/src/os/inc/osapi-os-core.h index 760fe35ce..8afd6e923 100644 --- a/src/os/inc/osapi-os-core.h +++ b/src/os/inc/osapi-os-core.h @@ -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 * @{ */ @@ -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 @@ -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 * @{ */ diff --git a/src/os/shared/inc/os-shared-idmap.h b/src/os/shared/inc/os-shared-idmap.h index 402cf0a46..085c718a0 100644 --- a/src/os/shared/inc/os-shared-idmap.h +++ b/src/os/shared/inc/os-shared-idmap.h @@ -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 diff --git a/src/os/shared/src/osapi-idmap.c b/src/os/shared/src/osapi-idmap.c index 7f2ea0097..53398d477 100644 --- a/src/os/shared/src/osapi-idmap.c +++ b/src/os/shared/src/osapi-idmap.c @@ -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 @@ -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; @@ -575,6 +534,9 @@ 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_ * + * 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. * @@ -582,17 +544,33 @@ int32 OS_ObjectIdFindNext(uint32 idtype, uint32 *array_index, OS_common_record_t 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; @@ -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 */ @@ -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 */ /*---------------------------------------------------------------- * @@ -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 */ + + diff --git a/src/os/shared/src/osapi-time.c b/src/os/shared/src/osapi-time.c index 4089e5a4c..67598bf26 100644 --- a/src/os/shared/src/osapi-time.c +++ b/src/os/shared/src/osapi-time.c @@ -436,7 +436,7 @@ int32 OS_TimerDelete(uint32 timer_id) { if (local->next_ref != local_id) { - OS_ObjectIdMap(OS_OBJECT_TYPE_OS_TIMEBASE, local->next_ref, &OS_timebase_table[local->timebase_ref].first_cb); + OS_ObjectIdCompose_Impl(OS_OBJECT_TYPE_OS_TIMEBASE, local->next_ref, &OS_timebase_table[local->timebase_ref].first_cb); } else { diff --git a/src/tests/osal-core-test/osal-core-test.c b/src/tests/osal-core-test/osal-core-test.c index a1d0d8ac8..df079abb0 100644 --- a/src/tests/osal-core-test/osal-core-test.c +++ b/src/tests/osal-core-test/osal-core-test.c @@ -13,6 +13,14 @@ #define UT_EXIT_LOOP_MAX 100 /* Used to limit wait for self-exiting task to exit */ /* OS Constructs */ +#define OSAL_UT_MAX_CALLBACKS 5 +typedef struct +{ + uint32 NumInvocations; + uint32 ObjList[OSAL_UT_MAX_CALLBACKS]; +} TestCallbackState_t; + + void TestTasks (void); void InitializeTaskIds (void); @@ -23,6 +31,20 @@ void TestQueues(void); void TestBinaries(void); void TestMutexes(void); void TestGetInfos(void); +void TestGenericQueries(void); + +/* helper function for "OS_ForEachObject" test cases */ +static void TestForEachCallback(uint32 object_id, void *arg) +{ + TestCallbackState_t *State = (TestCallbackState_t*)arg; + if (State->NumInvocations < OSAL_UT_MAX_CALLBACKS) + { + State->ObjList[State->NumInvocations] = object_id; + } + ++State->NumInvocations; +} + + /* *************************************** MAIN ************************************** */ void UtTest_Setup(void) @@ -37,6 +59,7 @@ void UtTest_Setup(void) UtTest_Add(TestBinaries, NULL, NULL, "BSEM"); UtTest_Add(TestMutexes, NULL, NULL, "MSEM"); UtTest_Add(TestGetInfos, NULL, NULL, "INFO"); + UtTest_Add(TestGenericQueries, NULL, NULL, "QUERIES"); } /* end OS_Application Startup */ @@ -592,3 +615,74 @@ void TestGetInfos(void) UtAssert_True(status == OS_SUCCESS, "OS_MutSemDelete"); } +/* + * Validate generic query functions such as OS_ForEachObject, OS_GetResourceName, + * and any other function that operates on any generic/unspecified object type. + */ +void TestGenericQueries(void) +{ + int status; + TestCallbackState_t State; + char ResourceName[OS_MAX_API_NAME]; + + status = OS_TaskCreate( &task_0_id, "Task 0", task_0, task_0_stack, + TASK_0_STACK_SIZE, TASK_0_PRIORITY, 0); + UtAssert_True(status == OS_SUCCESS, "OS_TaskCreate (%ld) == OS_SUCCESS", (long)status); + + status = OS_QueueCreate( &msgq_0, "q 0", MSGQ_DEPTH, MSGQ_SIZE, 0); + UtAssert_True(status == OS_SUCCESS, "OS_QueueCreate (%ld) == OS_SUCCESS", (long)status); + + status = OS_BinSemCreate( &bin_0,"Bin 0",1,0); + UtAssert_True(status == OS_SUCCESS, "OS_BinSemCreate (%ld) == OS_SUCCESS", (long)status); + + status = OS_MutSemCreate( &mut_0,"Mut 0",0); + UtAssert_True(status == OS_SUCCESS, "OS_MutSemCreate (%ld) == OS_SUCCESS", (long)status); + + /* The "OS_ForEachObjectOfType()" should callback for only a specific object type - + * spot check for Tasks and Bin Sem */ + memset(&State, 0, sizeof(State)); + OS_ForEachObjectOfType(OS_OBJECT_TYPE_OS_TASK, OS_OBJECT_CREATOR_ANY, TestForEachCallback, &State); + UtAssert_True(State.NumInvocations == 1, "Task NumInvocations (%lu) == 1", (unsigned long)State.NumInvocations); + UtAssert_True(State.ObjList[0] == task_0_id, "Task ObjList[0] (%lx) == %lx", + (unsigned long)State.ObjList[0], (unsigned long)task_0_id); + + memset(&State, 0, sizeof(State)); + OS_ForEachObjectOfType(OS_OBJECT_TYPE_OS_BINSEM, OS_OBJECT_CREATOR_ANY, TestForEachCallback, &State); + UtAssert_True(State.NumInvocations == 1, "BinSem NumInvocations (%lu) == 1", (unsigned long)State.NumInvocations); + UtAssert_True(State.ObjList[0] == bin_0, "BinSem ObjList[0] (%lx) == %lx", + (unsigned long)State.ObjList[0], (unsigned long)bin_0); + + memset(&State, 0, sizeof(State)); + OS_ForEachObjectOfType(OS_OBJECT_TYPE_OS_COUNTSEM, OS_OBJECT_CREATOR_ANY, TestForEachCallback, &State); + UtAssert_True(State.NumInvocations == 0, "CountSem NumInvocations (%lu) == 0", (unsigned long)State.NumInvocations); + + /* + * The generic "OS_ForEachObject()" should callback for all object types. + * + * Note there are internally-generated object IDs that also may get returned here, + * in addition to the ones which are explicitly created within this test. Therefore + * it is only verified that the callback was invoked for _at least_ the resources + * created here, but OK if it is more than that. + */ + memset(&State, 0, sizeof(State)); + OS_ForEachObject(OS_OBJECT_CREATOR_ANY, TestForEachCallback, &State); + UtAssert_True(State.NumInvocations >= 4, "State.NumInvocations (%lu) >= 4", (unsigned long)State.NumInvocations); + + /* Test the OS_GetResourceName() API function */ + status = OS_GetResourceName(mut_0, ResourceName, 0); + UtAssert_True(status == OS_INVALID_POINTER, "OS_GetResourceName (%lx,%ld) == OS_INVALID_POINTER", (unsigned long)mut_0, (long)status); + + status = OS_GetResourceName(msgq_0, ResourceName, sizeof(ResourceName)); + UtAssert_True(status == OS_SUCCESS, "OS_GetResourceName (%lx,%ld) == OS_SUCCESS", (unsigned long)msgq_0, (long)status); + UtAssert_StrCmp(ResourceName, "q 0", "Output value correct"); + + status = OS_GetResourceName(0, ResourceName, sizeof(ResourceName)); + UtAssert_True(status == OS_ERR_INVALID_ID, "OS_GetResourceName (%lx,%ld) == OS_ERR_INVALID_ID", (unsigned long)msgq_0, (long)status); + + status = OS_GetResourceName(bin_0, ResourceName, 1); + UtAssert_True(status == OS_ERR_NAME_TOO_LONG, "OS_GetResourceName (%lx,%ld) == OS_ERR_NAME_TOO_LONG", (unsigned long)bin_0, (long)status); + + /* The OS_DeleteAllObjects() should clean up every object created here. */ + OS_DeleteAllObjects(); +} + diff --git a/src/unit-test-coverage/shared/src/coveragetest-idmap.c b/src/unit-test-coverage/shared/src/coveragetest-idmap.c index bc7d2170c..78efe727b 100644 --- a/src/unit-test-coverage/shared/src/coveragetest-idmap.c +++ b/src/unit-test-coverage/shared/src/coveragetest-idmap.c @@ -72,52 +72,6 @@ void Test_OS_ObjectIdInit(void) UtAssert_True(actual == expected, "OS_ObjectIdInit() (%ld) == %ld", (long)actual, (long)expected); } -void Test_OS_ObjectIdMapUnmap(void) -{ - /* - * Test Case For: - * int32 OS_Id_Map(uint32 idtype, uint32 idvalue, uint32 *result); - */ - uint32 objid = 0xFFFFFFFF; - int32 expected = OS_SUCCESS; - int32 actual = OS_SUCCESS; - uint32 idtype = 0; - uint32 idvalue_out = 0; - - for (idtype = 0; idtype < OS_OBJECT_TYPE_USER; ++idtype) - { - if (idtype == OS_OBJECT_TYPE_UNDEFINED) - { - expected = OS_ERR_INVALID_ID; - } - else - { - expected = OS_SUCCESS; - } - - idvalue_out = 0; - objid = 0; - actual = OS_ObjectIdMap(idtype, 1, &objid); - - /* Verify Outputs */ - UtAssert_True(actual == expected, "OS_Id_Map() (%ld) == %ld", (long)actual, (long)expected); - UtAssert_True(objid != 0, "objid (%lu) != 0", (unsigned long)objid); - - if (idtype == OS_OBJECT_TYPE_UNDEFINED) - { - objid = 0xFFFFFFFF; - } - - actual = OS_ObjectIdUnMap(objid, idtype, &idvalue_out); - - UtAssert_True(actual == expected, "OS_Id_UnMap() (%ld) == %ld", (long)actual, (long)expected); - if (expected == OS_SUCCESS) - { - UtAssert_True(idvalue_out == 1, "idvalue_out (%lu) == 1", (unsigned long)idvalue_out); - } - } -} - void Test_OS_ObjectIdConvertLock(void) { /* @@ -280,7 +234,7 @@ void Test_OS_ObjectIdToArrayIndex(void) int32 actual = ~OS_SUCCESS; /* need to get a "valid" objid for the nominal case */ - OS_ObjectIdMap(OS_OBJECT_TYPE_OS_TASK, 1, &objid); + OS_ObjectIdCompose_Impl(OS_OBJECT_TYPE_OS_TASK, 1, &objid); actual = OS_ObjectIdToArrayIndex(OS_OBJECT_TYPE_OS_TASK, objid, &local_idx); /* Verify Outputs */ @@ -365,7 +319,7 @@ void Test_OS_ObjectIdGetById(void) /* set "true" for the remainder of tests */ OS_SharedGlobalVars.Initialized = true; - OS_ObjectIdMap(OS_OBJECT_TYPE_OS_TASK, 1, &refobjid); + OS_ObjectIdCompose_Impl(OS_OBJECT_TYPE_OS_TASK, 1, &refobjid); OS_ObjectIdToArrayIndex(OS_OBJECT_TYPE_OS_TASK, refobjid, &local_idx); OS_global_task_table[local_idx].active_id = refobjid; expected = OS_SUCCESS; @@ -606,9 +560,9 @@ void Test_OS_ConvertToArrayIndex(void) UtAssert_True(local_idx1 == local_idx2, "local_idx1 (%lu) == local_idx2 (%lu)", (unsigned long)local_idx1, (unsigned long)local_idx2); - expected = OS_ERR_INCORRECT_OBJ_TYPE; + expected = OS_ERR_INVALID_ID; actual = OS_ConvertToArrayIndex(0, &local_idx2); - UtAssert_True(actual == expected, "OS_ConvertToArrayIndex() (%ld) == OS_ERR_INCORRECT_OBJ_TYPE", (long)actual); + UtAssert_True(actual == expected, "OS_ConvertToArrayIndex() (%ld) == OS_ERR_INVALID_ID", (long)actual); } void Test_OS_ForEachObject(void) @@ -620,8 +574,11 @@ void Test_OS_ForEachObject(void) uint32 objtype = OS_OBJECT_TYPE_UNDEFINED; OS_common_record_t *rptr = NULL; uint32 local_idx = 0xFFFFFFFF; + uint32 self_id; Test_OS_ObjTypeCount_t Count; + self_id = OS_TaskGetId(); + memset(&Count, 0, sizeof(Count)); while (objtype < OS_OBJECT_TYPE_USER) @@ -638,6 +595,47 @@ void Test_OS_ForEachObject(void) UtAssert_True(Count.MutexCount == 1, "OS_ForEachObject() MutexCount (%lu) == 1", (unsigned long)Count.MutexCount); UtAssert_True(Count.OtherCount == 9, "OS_ForEachObject() OtherCount (%lu) == 9", (unsigned long)Count.OtherCount); + OS_ForEachObjectOfType(OS_OBJECT_TYPE_OS_QUEUE, self_id, ObjTypeCounter, &Count); + UtAssert_True(Count.TaskCount == 1, "OS_ForEachObjectOfType(), creator %08lx TaskCount (%lu) == 1", (unsigned long)self_id, (unsigned long)Count.TaskCount); + UtAssert_True(Count.QueueCount == 2, "OS_ForEachObjectOfType() QueueCount (%lu) == 2", (unsigned long)Count.QueueCount); + UtAssert_True(Count.MutexCount == 1, "OS_ForEachObjectOfType() MutexCount (%lu) == 1", (unsigned long)Count.MutexCount); + + OS_ForEachObjectOfType(OS_OBJECT_TYPE_OS_QUEUE, self_id ^ 1, ObjTypeCounter, &Count); + UtAssert_True(Count.TaskCount == 1, "OS_ForEachObjectOfType(), non-matching creator TaskCount (%lu) == 1", (unsigned long)Count.TaskCount); + UtAssert_True(Count.QueueCount == 2, "OS_ForEachObjectOfType() QueueCount (%lu) == 2", (unsigned long)Count.QueueCount); + UtAssert_True(Count.MutexCount == 1, "OS_ForEachObjectOfType() MutexCount (%lu) == 1", (unsigned long)Count.MutexCount); +} + +void Test_OS_GetResourceName(void) +{ + /* + * Test Case For: + * int32 OS_GetResourceName(uint32 id, char *buffer, uint32 buffer_size) + */ + uint32 local_idx = 0xFFFFFFFF; + OS_common_record_t *rptr = NULL; + char NameBuffer[OS_MAX_API_NAME]; + int32 expected; + int32 actual; + + /* + * Set up for the OS_GetResourceName function to return success + */ + /* Need a valid ID to work with */ + OS_ObjectIdFindNext(OS_OBJECT_TYPE_OS_TASK, &local_idx, &rptr); + rptr->name_entry = "UTTask"; + expected = OS_SUCCESS; + actual = OS_GetResourceName(rptr->active_id, NameBuffer, sizeof(NameBuffer)); + UtAssert_True(actual == expected, "OS_GetResourceName() (%ld) == OS_SUCCESS", (long)actual); + UtAssert_True(strcmp(NameBuffer, "UTTask") == 0, "NameBuffer (%s) == UTTask", NameBuffer); + + expected = OS_ERR_NAME_TOO_LONG; + actual = OS_GetResourceName(rptr->active_id, NameBuffer, 2); + UtAssert_True(actual == expected, "OS_GetResourceName() (%ld) == OS_ERR_NAME_TOO_LONG", (long)actual); + + expected = OS_INVALID_POINTER; + actual = OS_GetResourceName(rptr->active_id, NULL, 0); + UtAssert_True(actual == expected, "OS_GetResourceName() (%ld) == OS_INVALID_POINTER", (long)actual); } /* Osapi_Test_Setup @@ -677,7 +675,6 @@ void Osapi_Test_Teardown(void) void UtTest_Setup(void) { ADD_TEST(OS_ObjectIdInit); - ADD_TEST(OS_ObjectIdMapUnmap); ADD_TEST(OS_ObjectIdFindNext); ADD_TEST(OS_ObjectIdToArrayIndex); ADD_TEST(OS_ObjectIdFindByName); @@ -689,6 +686,7 @@ void UtTest_Setup(void) ADD_TEST(OS_ForEachObject); ADD_TEST(OS_GetMaxForObjectType); ADD_TEST(OS_GetBaseForObjectType); + ADD_TEST(OS_GetResourceName); } diff --git a/src/ut-stubs/osapi-utstub-idmap.c b/src/ut-stubs/osapi-utstub-idmap.c index d24a66308..4c4a8c958 100644 --- a/src/ut-stubs/osapi-utstub-idmap.c +++ b/src/ut-stubs/osapi-utstub-idmap.c @@ -391,6 +391,33 @@ int32 OS_ObjectIdAllocateNew(uint32 idtype, const char *name, uint32 *array_inde return Status; } +/*-------------------------------------------------------------------------------------- + Name: OS_GetResourceName + + Purpose: Stub function for OS_GetResourceName, returns either the test-supplied string + or an empty string. + + returns: status +---------------------------------------------------------------------------------------*/ +int32 OS_GetResourceName(uint32 id, char *buffer, uint32 buffer_size) +{ + int32 return_code; + + return_code = UT_DEFAULT_IMPL(OS_GetResourceName); + + if (return_code == OS_SUCCESS) + { + if (buffer_size > 0 && + UT_Stub_CopyToLocal(UT_KEY(OS_GetResourceName), buffer, buffer_size) == 0) + { + /* return an empty string by default */ + buffer[0] = 0; + } + } + + return return_code; +} + /*-------------------------------------------------------------------------------------- Name: OS_ConvertToArrayIndex @@ -429,6 +456,36 @@ int32 OS_ConvertToArrayIndex(uint32 object_id, uint32 *ArrayIndex) return return_code; } /* end OS_ConvertToArrayIndex */ +/*-------------------------------------------------------------------------------------- + Name: OS_ForEachObjectOfType + + Purpose: Stub function for OS_ForEachObjectOfType + + returns: None +---------------------------------------------------------------------------------------*/ +void OS_ForEachObjectOfType (uint32 objtype, uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg) +{ + uint32 NextId; + uint32 IdSize; + OS_U32ValueWrapper_t wrapper; + + wrapper.arg_callback_func = callback_ptr; + + /* Although this is "void", Invoke the default impl to log it and invoke any hooks */ + UT_Stub_RegisterContext(UT_KEY(OS_ForEachObjectOfType), wrapper.opaque_arg); + UT_Stub_RegisterContext(UT_KEY(OS_ForEachObjectOfType), callback_arg); + UT_DEFAULT_IMPL(OS_ForEachObjectOfType); + + while (1) + { + IdSize = UT_Stub_CopyToLocal(UT_KEY(OS_ForEachObjectOfType), &NextId, sizeof(NextId)); + if (IdSize < sizeof(NextId)) + { + break; + } + (*callback_ptr)(NextId, callback_arg); + } +} /*-------------------------------------------------------------------------------------- Name: OS_ForEachOject