How does the Event Handler in Nucleus NET work?

Discussion created by dan_schiro on Aug 6, 2012

The Events Dispatcher


Events are used throughout Nucleus NET for various  tasks: window probes, retransmissions, DHCP, ARP requests, and keeping  connections alive to name a few. Many events are required at the same  time. These events must be executed in an orderly fashion so that no  event is lost.


The Events Dispatcher schedules and handles events  within Nucleus NET. The Events Dispatcher is a task that removes events  from the Event List and the Event Queue, deciphers the event, and  processes it accordingly. Events are placed on the Event List by the  Timer task. Events are placed on the Event Queue by different networking  processes.







connection has opened, CONCLASS


the other side has closed its side of the connection


connection open attempt has failed


This used to be CONRX, but this has been removed


Just a null event... Used to wake up the  dispatcher from a indefinite sleep should a timer queue entry be  posted...could be used for other purposes also.


UDP data has arrived on listening port, USERCLASS


TCP segment retransmission event


Window Probe event


TCP ACK transmission event


buffer needs to be sent


TCP Select timeout event


ARP event


A RARP request event


Send an IGMP Group Report


Timeout the reassembly of an IPv4 datagram


Timeout the reassembly of an IPv6 datagram


Timeout waiting for a ping reply


IP data has arrived


Timeout the closing of a connection



NAT specific event


NAT specific event


NAT specific event


NAT specific event


NAT specific event


Resume a task suspended on memory allocation






Setting Timers


Timer events are set by the network processes on events  that should not be executed immediately, but rather after some interval  of time. The network processes do this by calling TQ_Timerset() which  sets a timer for an event. This event is then placed on the Event List  (EQ_Event_List).


The Event List is kept in due time order. This certifies  the next event to expire will be at the front of the list. Since it is  possible for multiple events to be due at the same time, it is necessary  to organize the list to prevent it from becoming too long. Each event  on the Event List has a duplist. The duplist is a list of duplicate  events (events who have duplicate due times). This shorter list reduces  the time to insert new events onto the Event List.


It is possible that before the timer interval finishes, a  network process determines that the event is unnecessary. A process can  cancel a timer event using the routine TQ_Timerunset(). This function  will then remove the event from the Event List.







*   FUNCTION                                                             
*       TQ_Timerset
*   DESCRIPTION                                                          
*       Set an async timer, and when time elapses sticks an event in the
*       network event queue.                                            
*       Class, event, dat is what gets posted when howlong times out.   
*   INPUTS                                                               
*       event                   The event to attach to the timer                                                           
*       dat                     Data or pointer attached to the event                                                      
*       howlong                 How long for the timer                                                      
*       extra                   An extra parameter for data.                                                     
*   OUTPUTS                                                              
*       OS_SUCCESS                                                      
*       -1                                                              
STATUS TQ_Timerset(TQ_EVENT event, UNSIGNED dat, UNSIGNED howlong,
                    UNSIGNED extra)
     tqe_t       *tqe;
     STATUS      status;
     tqe_t       *return_ptr = OS_NULL;


    /* Get an entry from the freelist.  */
     tqe = (tqe_t *) DLL_Dequeue (&EQ_Event_Freelist);


    /* Check to see if an entry was found.  If one was not found, need
        to allocate a new one. */
     if (!tqe)
         /* Get some memory for the new entry. */


         status = OS_Allocate_Memory(MEM_Cached, (void **) &return_ptr,
         /* Assign memory to the TQ entry */
         if(No_of_Entry != NET_MAX_TQ_ENTRIES )
             return_ptr = &NET_TQ_Entry_Memory[No_of_Entry++];
             status = OS_SUCCESS;
             status = OS_NO_MEMORY;


        /* check status of memory allocation */
         if (status == OS_SUCCESS)
             return_ptr = (tqe_t *)TLS_Normalize_Ptr(return_ptr);
             tqe = return_ptr;
             NLOG_Error_Log ("Unable to alloc memory for timer entry", NERR_RECOVERABLE,
                                 __FILE__, __LINE__);
             return (-1);


    /* Set up the new entry. */
     tqe->tqe_event = event;
     tqe->tqe_data = dat;
     tqe->tqe_ext_data = extra;
     tqe->duetime = OS_Retrieve_Clock() + (UNSIGNED) howlong;
     tqe->tqe_id = EQ_ID_VALUE;


    /* Clear out the new entry's duplist. */
     tqe->duplist.flink = (tqe_t *)OS_NULL;
     tqe->duplist.blink = (tqe_t *)OS_NULL;


    /* Place the new entry on the timerlist. */
     TQ_Post ((tqe_t *) &EQ_Event_List, tqe);


    /* Check to see if the current task is the  events dispatcher.  If it
        is we do not want to place an item onto the event queue.  If the queue
        is full the events dispatcher will suspend on the queue, and since
        the events dispatcher is the only task that removes items from the
        queue, deadlock will occur. */
     if (OS_MATCH_CURRENT_TASK(OS_Current_Task_Pointer(),
         return (OS_SUCCESS);


    /* Wake up the event dispatcher from an indefinite wait
        if this is the first entry on the timer list. */
     if (EQ_Event_List.flink == tqe)
         EQ_Put_Event(CONNULL, dat, 0);


    return (OS_SUCCESS);


} /* TQ_Timerset */






Setting Events


The setting of an event adds that event to the Event  Queue (eQueue), which causes the event to be handled by the Events  Dispatcher after all expired timer events have been processed.






The event to attach to the timer


Data or pointer attached to the event


An extra parameter for data








Registering Events


As networking processes are executed, it may be  necessary to dynamically add to the list of possible events. This can be  done by registering a new event. To register a new event, the event  handler is passed to the registration function, and the macro value  associated with that event is passed back. Whenever an event is set with  the system, the macro value returned must be used to refer to the  registered event.




STATUS EQ_Register_Event(EQ_Handler handler, TQ_EVENT *newevt)





The event handler function that will be responsible for handling the newly registered event when it expires.


The new macro value will be returned through this parameter.








Handling Events


The handling of events is a continuous loop the Event  Dispatcher must follow. It begins with checking the Event List. Recall  that the Event List is populated by TQ_Timerset(). If events exist  within the Event List, the Events Dispatcher must check the due times of  these events. If an event is due, the variable waittime is set to  NU_NO_SUSPEND. If an event is not due, waittime is set to the earliest  due time. If an event does not exist, waittime is set to NU_SUSPEND.


At this point it is required that the Events Dispatcher  relinquish control to the system to prevent system starvation. If an  event is due, the dispatcher will call NU_Relinquish(). If waittime is  anything either than NU_NO_SUSPEND, an event is not ready to be  processed, and the dispatcher will suspend on the Event Queue for the  amount of time specified by waittime , or until an event is received.


If an event exists, the dispatcher will begin processing  it. Many timer events can expire at the same time, however, the  dispatcher can only address them one at a time. To handle each of these  events, the dispatcher will check the duplist. If events are present on  the duplist, each one will be placed on the Event Queue, to be handled  after the current event has been processed.


Now, the Events Dispatcher will determine what type of  event has been set, and call the appropriate event handler. With the  event handler completed, the Events Dispatcher is ready to process the  next event, if one exists.