forked from gatsby/datalink_repo
rewrite schedule event pool.
This commit is contained in:
@@ -0,0 +1,385 @@
|
|||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* Description: Event scheduling implementation
|
||||||
|
*
|
||||||
|
* Date: 2023-12-21 13:32
|
||||||
|
* LastEditors: Fan Hao
|
||||||
|
* LastEditTime: 2023-12-21 13:32
|
||||||
|
* Revisions: Rev 0.0
|
||||||
|
* History:
|
||||||
|
* [2023-12-21]: Initial version.
|
||||||
|
*
|
||||||
|
* Copyright(c) 2021 Beijing Institute of Technology.
|
||||||
|
* Lab of Communication and Networking
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
|
||||||
|
/***************************** Include Files *********************************/
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "schdevent.h"
|
||||||
|
#include "linklayer814.h"
|
||||||
|
#include "linklayer814_types.h"
|
||||||
|
#include "../error.h"
|
||||||
|
#include "../util/list.h"
|
||||||
|
/***************** Macros (Inline Functions) Definitions *********************/
|
||||||
|
/**************************** Type Definitions *******************************/
|
||||||
|
/************************** Variable Definitions *****************************/
|
||||||
|
static L2_SCHD_EVENT util_schdevent;
|
||||||
|
/************************** Function Prototypes ******************************/
|
||||||
|
/**
|
||||||
|
* @brief helper function to free schedule events.
|
||||||
|
*/
|
||||||
|
static void schdevent_free(void* val){
|
||||||
|
if(val == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
free(((L2_SCHD_EVENT*)val)->l2Event.msg);
|
||||||
|
free(val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief helper function to match events by ids.
|
||||||
|
*/
|
||||||
|
static bool schdevent_match(void* a, void* b){
|
||||||
|
ASSERT(a == NULL);
|
||||||
|
ASSERT(b != NULL);
|
||||||
|
return (((L2_SCHD_EVENT*)a)->eventId
|
||||||
|
== ((L2_SCHD_EVENT*)b)->eventId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Creat a schedule event pool.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
*
|
||||||
|
* @return SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_CreateSchedEventPool(L2_SCHD_POOL** schdPool) {
|
||||||
|
(*schdPool) = malloc(sizeof(L2_SCHD_POOL));
|
||||||
|
if(*schdPool == NULL) {
|
||||||
|
DBG_ERROR("Failed to allocated memory for schdPool.\n");
|
||||||
|
return EALLOC;
|
||||||
|
}
|
||||||
|
(*schdPool)->schdList = list_new();
|
||||||
|
if((*schdPool)->schdList == NULL) {
|
||||||
|
DBG_ERROR("Failed to allocated memory for schdPool->schdList.\n");
|
||||||
|
free(*schdPool);
|
||||||
|
return EALLOC;
|
||||||
|
}
|
||||||
|
(*schdPool)->schdList->free = schdevent_free;
|
||||||
|
(*schdPool)->schdList->match = schdevent_match;
|
||||||
|
(*schdPool)->envCnt = 0;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Clear schedule event pool, delete all events in pool and
|
||||||
|
* free allocated memory.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
*
|
||||||
|
* @return SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void L2_ClearSchedEventPool(L2_SCHD_POOL* schdPool) {
|
||||||
|
ASSERT(schdPool != NULL);
|
||||||
|
list_clear(schdPool->schdList);
|
||||||
|
schdPool->envCnt = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Completely destroy schedule event pool.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
*
|
||||||
|
* @return SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void L2_DestroySchedEventPool(L2_SCHD_POOL* schdPool) {
|
||||||
|
if(schdPool == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
list_destroy(schdPool->schdList);
|
||||||
|
free(schdPool);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Creat a new schedule event, register event in schedule event pool.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
* @param event event type of the new schedule event.
|
||||||
|
* @param isVolatile event type of the new schedule event.
|
||||||
|
*
|
||||||
|
* @return NULL error occurred
|
||||||
|
* Pointer to schedule event.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
L2_SCHD_EVENT* L2_CreatNewSchdEvent(L2_SCHD_POOL* schdPool, L2_EVENT_TYPE event, bool isVolatile){
|
||||||
|
ASSERT(schdPool != NULL);
|
||||||
|
if(event < L2_EV_SCAN_PROC_DONE || event > L2_ROUTINE_UPDATE){
|
||||||
|
DBG_ERROR("Unknown event type: %d.\n", event);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
L2_SCHD_EVENT* schdEvent = (L2_SCHD_EVENT*)malloc(sizeof(L2_SCHD_EVENT));
|
||||||
|
if(schdEvent == NULL){
|
||||||
|
DBG_ERROR("Failed to allocate schedule event.\n");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
list_node_t *node = list_node_new(schdEvent);
|
||||||
|
if(node == NULL) {
|
||||||
|
DBG_ERROR("Failed to allocate schedule event list node.\n");
|
||||||
|
free(schdEvent);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
schdEvent->eventId = schdPool->envCnt++;
|
||||||
|
schdEvent->ocurrCnt = 0;
|
||||||
|
schdEvent->l2Event.event = event;
|
||||||
|
schdEvent->l2Event.msg = NULL;
|
||||||
|
schdEvent->isSchd = false;
|
||||||
|
schdEvent->isVolatile = isVolatile;
|
||||||
|
schdEvent->schdSlot = L2_SLOTNO_NONE;
|
||||||
|
schdEvent->schdFrame = L2_FRAMENO_NONE;
|
||||||
|
list_rpush(schdPool->schdList, node);
|
||||||
|
return schdEvent;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Get a schedule event by its id.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
* @param id ID of the event
|
||||||
|
*
|
||||||
|
* @return NULL
|
||||||
|
* Pointer to the schedule event.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
L2_SCHD_EVENT* L2_GetEventById(L2_SCHD_POOL* schdPool, uint32_t id) {
|
||||||
|
ASSERT(schdPool != NULL);
|
||||||
|
util_schdevent.eventId = id;
|
||||||
|
list_node_t* node = list_find(schdPool->schdList, &util_schdevent);
|
||||||
|
if(node != NULL) {
|
||||||
|
DBG_WARNING("Event with id=%d, dose not exist.\n", id);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return ((L2_SCHD_EVENT*) node->val);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Delete a schedule event, remove the event from event pool,
|
||||||
|
* release memory.
|
||||||
|
*
|
||||||
|
* @param schdPool a pointer to schedule pool instance.
|
||||||
|
* @param id ID of the event
|
||||||
|
*
|
||||||
|
* @return SUCCESS
|
||||||
|
* error code
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_DeleteSchdEventById(L2_SCHD_POOL* schdPool, uint32_t id) {
|
||||||
|
ASSERT(schdPool != NULL);
|
||||||
|
util_schdevent.eventId = id;
|
||||||
|
list_node_t* node = list_find(schdPool->schdList, &util_schdevent);
|
||||||
|
if(node != NULL) {
|
||||||
|
DBG_ERROR("Event with id=%d, dose not exist.\n", id);
|
||||||
|
return EIGNORE;
|
||||||
|
}
|
||||||
|
list_remove(schdPool->schdList, node);
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Schedule a event at a specific time(indexed by frame and slot number)
|
||||||
|
*
|
||||||
|
* @param instPtr a pointer to linklayer instance
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
* @param frameNum schedule frame number
|
||||||
|
* @param slotNum schedule slot number
|
||||||
|
*
|
||||||
|
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||||
|
* SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_ScheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNum, uint32_t slotNum){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
if(L2_isEventScheduled(schdEvent) == true){
|
||||||
|
DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
if(frameNum <= L2_GetCurrentFrameNum(instPtr) && slotNum < L2_GetCurrentSlotNum(instPtr)){
|
||||||
|
DBG_ERROR("Cannot schedule event %d to the past(current: [%u-%u], schedule: [%u-%u]).\n",
|
||||||
|
schdEvent->eventId, L2_GetCurrentFrameNum(instPtr), L2_GetCurrentSlotNum(instPtr), frameNum, slotNum);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
DBG_INFO("Schedule event (type:%d) [%u] at %u-%u.\n",
|
||||||
|
schdEvent->l2Event.event, schdEvent->eventId,
|
||||||
|
frameNum, slotNum);
|
||||||
|
schdEvent->isSchd = true;
|
||||||
|
schdEvent->schdFrame = frameNum;
|
||||||
|
schdEvent->schdSlot = slotNum;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Schedule a event after a specific time period.
|
||||||
|
*
|
||||||
|
* @param instPtr a pointer to linklayer instance
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
* @param numSlots how many slot later the event should be scheduled
|
||||||
|
*
|
||||||
|
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||||
|
* SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_ScheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
if(L2_isEventScheduled(schdEvent) == true){
|
||||||
|
DBG_ERROR("Event %d has already been scheduled.\n", schdEvent->eventId);
|
||||||
|
return FAILURE;
|
||||||
|
}
|
||||||
|
uint32_t frameNum = L2_GetCurrentFrameNum(instPtr) + (numSlots/L2_SLOTS_PER_FRAME);
|
||||||
|
uint32_t slotNum = L2_GetCurrentSlotNum(instPtr) + (numSlots%L2_SLOTS_PER_FRAME);
|
||||||
|
return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Reschedule a event at a specific time(indexed by frame and slot number)
|
||||||
|
*
|
||||||
|
* @param instPtr a pointer to linklayer instance
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
* @param frameNum schedule frame number
|
||||||
|
* @param slotNum schedule slot number
|
||||||
|
*
|
||||||
|
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||||
|
* SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_RescheduleEventAt(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t frameNum, uint32_t slotNum){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
if(schdEvent->isSchd == false){
|
||||||
|
DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId);
|
||||||
|
}
|
||||||
|
schdEvent->isSchd = false;
|
||||||
|
return L2_ScheduleEventAt(instPtr, schdEvent, frameNum, slotNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Reschedule a event after a specific time period.
|
||||||
|
*
|
||||||
|
* @param instPtr a pointer to linklayer instance
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
* @param numSlots how many slot later the event should be scheduled
|
||||||
|
*
|
||||||
|
* @return FAILURE, event has already been scheduled/schedule time not allowed.
|
||||||
|
* SUCCESS
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
int32_t L2_RescheduleEventAfter(L2_INST* instPtr, L2_SCHD_EVENT* schdEvent, uint32_t numSlots){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
if(schdEvent->isSchd == false){
|
||||||
|
DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId);
|
||||||
|
}
|
||||||
|
return L2_ScheduleEventAfter(instPtr, schdEvent, numSlots);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Check and excute schedule event in event pool illiterate.
|
||||||
|
*
|
||||||
|
* @param instPtr a pointer to linklayer instance
|
||||||
|
*
|
||||||
|
* @return NONE.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
void L2_EventPoolHandler(L2_INST* instPtr){
|
||||||
|
ASSERT(instPtr != NULL);
|
||||||
|
list_node_t* node;
|
||||||
|
L2_SCHD_EVENT* event;
|
||||||
|
L2_SCHD_POOL *pool = instPtr->schdEventPool;
|
||||||
|
list_iterator_t* iter = list_iterator_new(pool->schdList, LIST_HEAD);
|
||||||
|
if (iter == NULL)
|
||||||
|
{
|
||||||
|
DBG_ERROR("Failed to initialize schedule event pool iteration.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
while (iter->next != NULL)
|
||||||
|
{
|
||||||
|
node = list_iterator_next(iter);
|
||||||
|
event = (L2_SCHD_EVENT*)node->val;
|
||||||
|
if(L2_isEventScheduled(event)){
|
||||||
|
if(event->schdFrame == L2_GetCurrentFrameNum(instPtr)
|
||||||
|
&& event->schdSlot == L2_GetCurrentSlotNum(instPtr)){
|
||||||
|
DBG_INFO("Asserting scheduled event [%d].\n", event->eventId);
|
||||||
|
AssertL2Event(instPtr, &(event->l2Event));
|
||||||
|
if(event->isVolatile == true) {
|
||||||
|
DBG_INFO("Deleting scheduled event [%d], since it is volatile.\n", event->eventId);
|
||||||
|
list_remove(pool->schdList, node);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
event->ocurrCnt++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_iterator_destroy(iter);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Append extra message content to specific schedule event.
|
||||||
|
*
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
* msg pointer to the append content.
|
||||||
|
*
|
||||||
|
* @return SUCCESS.
|
||||||
|
* error code.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
inline void L2_SchdEventAppendMsg(L2_SCHD_EVENT* schdEvent, void* msg){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
schdEvent->l2Event.msg = msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Cancel a scheduled event.
|
||||||
|
*
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
*
|
||||||
|
* @return SUCCESS.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
inline int32_t L2_CancelEvent(L2_SCHD_EVENT* schdEvent){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
if(schdEvent->isSchd == false){
|
||||||
|
DBG_WARNING("Event %d has not been scheduled yet.\n", schdEvent->eventId);
|
||||||
|
}
|
||||||
|
schdEvent->isSchd = false;
|
||||||
|
return SUCCESS;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
/**
|
||||||
|
* @brief Check if the event was scheduled.
|
||||||
|
*
|
||||||
|
* @param schdEvent pointer to the schedule event.
|
||||||
|
*
|
||||||
|
* @return true.
|
||||||
|
* false.
|
||||||
|
*
|
||||||
|
******************************************************************************/
|
||||||
|
inline bool L2_isEventScheduled(const L2_SCHD_EVENT* schdEvent){
|
||||||
|
ASSERT(schdEvent != NULL);
|
||||||
|
return schdEvent->isSchd;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user