Skip to content

Commit

Permalink
Fix #540, add OSAL event framework
Browse files Browse the repository at this point in the history
Define an interface to allow an app/PSP to be notified when state changes
or other events occur at the OS level.  Initially defined events are resource
creation/deletion and task startup.

The interface is easily extendable with more events as needed.

This can be used to add platform-specific/nonstandard functions by putting
the code inside the event handler at the PSP level.
  • Loading branch information
jphickey committed Aug 18, 2020
1 parent 89e1dbb commit 51ac344
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 1 deletion.
90 changes: 89 additions & 1 deletion src/os/inc/osapi-os-core.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,75 @@ typedef enum
OS_STREAM_STATE_WRITABLE = 0x08, /**< @brief whether the stream is writable */
} OS_StreamState_t;

/**
* @brief A set of events that can be used with event callback routines
*/
typedef enum
{
OS_EVENT_RESERVED = 0, /**< no-op/reserved event id value */

/**
* resource/id has been newly allocated but not yet created.
*
* This event is invoked from WITHIN the locked region, in
* the context of the task which is allocating the resource.
*
* If the handler returns non-success, the error will be returned
* to the caller and the creation process is aborted.
*/
OS_EVENT_RESOURCE_ALLOCATED,

/**
* resource/id has been fully created/finalized.
*
* Invoked outside locked region, in the context
* of the task which created the resource.
*
* Data object is not used, passed as NULL.
*
* Return value is ignored - this is for information purposes only.
*/
OS_EVENT_RESOURCE_CREATED,

/**
* resource/id has been deleted.
*
* Invoked outside locked region, in the context
* of the task which deleted the resource.
*
* Data object is not used, passed as NULL.
*
* Return value is ignored - this is for information purposes only.
*/
OS_EVENT_RESOURCE_DELETED,

/**
* New task is starting.
*
* Invoked outside locked region, in the context
* of the task which is currently starting, before
* the entry point is called.
*
* Data object is not used, passed as NULL.
*
* If the handler returns non-success, task startup is aborted
* and the entry point is not called.
*/
OS_EVENT_TASK_STARTUP,

OS_EVENT_MAX /**< placeholder for end of enum, not used */
} OS_Event_t;

/**
* @brief A callback routine for event handling.
*
* @param[in] event The event that occurred
* @param[in] object_id The associated object_id, or 0 if not associated with an object
* @param[inout] data An abstract data/context object associated with the event, or NULL.
* @return status Execution status, see @ref OSReturnCodes.
*/
typedef int32 (*OS_EventHandler_t)(OS_Event_t event, uint32 object_id, void *data);

/**
* @brief For the @ref OS_GetErrorName() function, to ensure
* everyone is making an array of the same length.
Expand Down Expand Up @@ -360,7 +429,6 @@ int32 OS_ConvertToArrayIndex (uint32 object_id, uint32 *ArrayIndex);
* @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);
/**@}*/

/*-------------------------------------------------------------------------------------*/
/**
Expand All @@ -377,6 +445,26 @@ void OS_ForEachObject (uint32 creator_id, OS_ArgCallback_t callback_pt
*/
void OS_ForEachObjectOfType (uint32 objtype, uint32 creator_id, OS_ArgCallback_t callback_ptr, void *callback_arg);

/*-------------------------------------------------------------------------------------*/
/**
* @brief Callback routine registration
*
* This hook enables the application code to perform extra platform-specific
* operations on various system events such as resource creation/deletion.
*
* @note Some events are invoked while the resource is "locked" and therefore
* application-defined handlers for these events should not block or attempt
* to access other OSAL resources.
*
* @param[in] handler The application-provided event handler
* @return Execution status, see @ref OSReturnCodes.
* @retval #OS_SUCCESS @copybrief OS_SUCCESS
* @retval #OS_ERROR @copybrief OS_ERROR
*/
int32 OS_RegisterEventHandler (OS_EventHandler_t handler);

/**@}*/


/** @defgroup OSAPITask OSAL Task APIs
* @{
Expand Down
16 changes: 16 additions & 0 deletions src/os/shared/inc/os-shared-common.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ struct OS_shared_global_vars
int32 MicroSecPerTick;
int32 TicksPerSecond;

/*
* The event handler is an application-defined callback
* that gets invoked as resources are created/configured/deleted.
*/
OS_EventHandler_t EventHandler;

#ifdef OSAL_CONFIG_DEBUG_PRINTF
uint8 DebugLevel;
#endif
Expand All @@ -69,6 +75,16 @@ struct OS_shared_global_vars
*/
extern OS_SharedGlobalVars_t OS_SharedGlobalVars;

/*---------------------------------------------------------------------------------------
Name: OS_NotifyEvent
Purpose: Notify the user application of a change in the state of an OSAL resource
returns: OS_SUCCESS on success, or relevant error code
---------------------------------------------------------------------------------------*/
int32 OS_NotifyEvent(OS_Event_t event, uint32 object_id, void *data);


/*---------------------------------------------------------------------------------------
Name: OS_API_Impl_Init
Expand Down
43 changes: 43 additions & 0 deletions src/os/shared/src/osapi-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,36 @@ OS_SharedGlobalVars_t OS_SharedGlobalVars =
.ShutdownFlag = 0,
.MicroSecPerTick = 0, /* invalid, _must_ be set by implementation init */
.TicksPerSecond = 0, /* invalid, _must_ be set by implementation init */
.EventHandler = NULL,
#if defined(OSAL_CONFIG_DEBUG_PRINTF)
.DebugLevel = 1,
#endif
};


/*----------------------------------------------------------------
*
* Function: OS_NotifyEvent
*
* Purpose: Helper function to invoke the user-defined event handler
*
*-----------------------------------------------------------------*/
int32 OS_NotifyEvent(OS_Event_t event, uint32 object_id, void *data)
{
int32 status;

if (OS_SharedGlobalVars.EventHandler != NULL)
{
status = OS_SharedGlobalVars.EventHandler(event, object_id, data);
}
else
{
status = OS_SUCCESS;
}

return status;
}

/*
*********************************************************************************
* PUBLIC API (application-callable functions)
Expand Down Expand Up @@ -199,6 +224,24 @@ int32 OS_API_Init(void)
return(return_code);
} /* end OS_API_Init */

/*----------------------------------------------------------------
*
* Function: OS_RegisterEventHandler
*
* Purpose: Implemented per public OSAL API
* See description in API and header file for detail
*
*-----------------------------------------------------------------*/
int32 OS_RegisterEventHandler (OS_EventHandler_t handler)
{
if (handler == NULL)
{
return OS_INVALID_POINTER;
}

OS_SharedGlobalVars.EventHandler = handler;
return OS_SUCCESS;
}

/*----------------------------------------------------------------
*
Expand Down
27 changes: 27 additions & 0 deletions src/os/shared/src/osapi-idmap.c
Original file line number Diff line number Diff line change
Expand Up @@ -733,6 +733,7 @@ int32 OS_ObjectIdToArrayIndex(uint32 idtype, uint32 id, uint32 *ArrayIndex)
int32 OS_ObjectIdFinalizeNew(int32 operation_status, OS_common_record_t *record, uint32 *outid)
{
uint32 idtype = record->active_id >> OS_OBJECT_TYPE_SHIFT;
uint32 callback_id;

/* if operation was unsuccessful, then clear
* the active_id field within the record, so
Expand All @@ -744,17 +745,20 @@ int32 OS_ObjectIdFinalizeNew(int32 operation_status, OS_common_record_t *record,
if (operation_status != OS_SUCCESS)
{
record->active_id = 0;
callback_id = 0;
}
else if (idtype == 0 || idtype >= OS_OBJECT_TYPE_USER)
{
/* should never happen - indicates a bug. */
operation_status = OS_ERR_INVALID_ID;
record->active_id = 0;
callback_id = 0;
}
else
{
/* success */
OS_objtype_state[idtype].last_id_issued = record->active_id;
callback_id = record->active_id;
}

if (outid != NULL)
Expand All @@ -766,6 +770,12 @@ int32 OS_ObjectIdFinalizeNew(int32 operation_status, OS_common_record_t *record,
/* Either way we must unlock the object type */
OS_Unlock_Global(idtype);

/* Give event callback to the application */
if (callback_id != 0)
{
OS_NotifyEvent(OS_EVENT_RESOURCE_CREATED, callback_id, NULL);
}

return operation_status;
} /* end OS_ObjectIdFinalizeNew */

Expand All @@ -778,16 +788,28 @@ int32 OS_ObjectIdFinalizeNew(int32 operation_status, OS_common_record_t *record,
int32 OS_ObjectIdFinalizeDelete(int32 operation_status, OS_common_record_t *record)
{
uint32 idtype = OS_ObjectIdToType_Impl(record->active_id);
uint32 callback_id;

/* Clear the OSAL ID if successful - this returns the record to the pool */
if (operation_status == OS_SUCCESS)
{
callback_id = record->active_id;
record->active_id = 0;
}
else
{
callback_id = 0;
}

/* Either way we must unlock the object type */
OS_Unlock_Global(idtype);

/* Give event callback to the application */
if (callback_id != 0)
{
OS_NotifyEvent(OS_EVENT_RESOURCE_DELETED, callback_id, NULL);
}

return operation_status;
}

Expand Down Expand Up @@ -1072,6 +1094,11 @@ int32 OS_ObjectIdAllocateNew(uint32 idtype, const char *name, uint32 *array_inde
return_code = OS_ObjectIdFindNext(idtype, array_index, record);
}

if (return_code == OS_SUCCESS)
{
return_code = OS_NotifyEvent(OS_EVENT_RESOURCE_ALLOCATED, (*record)->active_id, NULL);
}

/* If allocation failed for any reason, unlock the global.
* otherwise the global should stay locked so remaining initialization can be done */
if (return_code != OS_SUCCESS)
Expand Down
6 changes: 6 additions & 0 deletions src/os/shared/src/osapi-task.c
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,12 @@ static int32 OS_TaskPrepare(uint32 task_id, osal_task_entry *entrypt)
return_code = OS_TaskRegister_Impl(task_id);
}

if (return_code == OS_SUCCESS)
{
/* Give event callback to the application */
return_code = OS_NotifyEvent(OS_EVENT_TASK_STARTUP, task_id, NULL);
}

if (return_code != OS_SUCCESS)
{
*entrypt = NULL;
Expand Down
28 changes: 28 additions & 0 deletions src/ut-stubs/osapi-utstub-common.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,34 @@ int32 OS_API_Init(void)
return status;
}

/*****************************************************************************
*
* Stub function for OS_NotifyEvent()
*
*****************************************************************************/
int32 OS_NotifyEvent(OS_Event_t event, uint32 object_id, void *data)
{
int32 status;

status = UT_DEFAULT_IMPL(OS_NotifyEvent);

return status;
}

/*****************************************************************************
*
* Stub function for OS_RegisterEventHandler()
*
*****************************************************************************/
int32 OS_RegisterEventHandler (OS_EventHandler_t handler)
{
int32 status;

status = UT_DEFAULT_IMPL(OS_RegisterEventHandler);

return status;
}


/*****************************************************************************
*
Expand Down

0 comments on commit 51ac344

Please sign in to comment.