📄 equeue.c
字号:
/**************************************************************************
*
* Copyright (c) 1993 - 2001 Accelerated Technology, Inc.
*
* PROPRIETARY RIGHTS of Accelerated Technology are involved in the subject
* matter of this material. All manufacturing, reproduction, use and sales
* rights pertaining to this subject matter are governed by the license
* agreement. The recipient of this software implicity accepts the terms
* of the license.
*
****************************************************************************/
/****************************************************************************
*
* FILENAME VERSION
*
* equeue.c 4.4
*
* DESCRIPTION
*
* Event queue manager
*
* DATA STRUCTURES
*
*
* FUNCTIONS
*
* NU_EventsDispatcher
* EQ_Clear_Matching_Timer
*
* DEPENDENCIES
*
* No other file dependencies
*
******************************************************************************/
#include "plus/nucleus.h"
#include "net/target.h"
#include "net/inc/netevent.h"
#include "net/inc/mem_defs.h"
#include "net/inc/net.h"
#include "net/inc/arp.h"
#include "net/inc/externs.h"
#include "net/inc/ip.h"
#include "net/inc/tcp.h"
#include "net/inc/igmp.h"
#include "net/inc/icmp.h"
#include "net/inc/nerrs.h"
#include "net/inc/udp.h"
#include "net/inc/net_extr.h"
#if (INCLUDE_NAT == NU_TRUE)
#include "nat/inc/nat_extr.h"
#endif
#if (INCLUDE_DHCP == NU_TRUE)
#include "net/inc/dhcp.h"
#endif
/*
* Define the timerlist control pointers. These are globally used to
* maintain the system timer list that is used for retry timeouts and
* the like.
*/
struct tqhdr EQ_Event_List, EQ_Event_Freelist;
/*************************************************************************
*
* FUNCTION
*
* NU_Events_Dispatcher
*
* DESCRIPTION
*
* This function is responsible for dispatching events from the
* event queue to the appropriate handling routines.
*
* INPUTS
*
* None.
*
* OUTPUTS
*
* None.
*
*************************************************************************/
VOID NU_EventsDispatcher(UNSIGNED argc, VOID *argv)
{
#if (INCLUDE_TCP == NU_TRUE)
TCP_PORT *prt;
NET_BUFFER *buf_ptr;
#endif
struct sock_struct *sock_ptr; /* Socket pointer. */
DV_DEVICE_ENTRY *dev_ptr;
ICMP_ECHO_LIST_ENTRY *echo_entry;
STATUS status;
UNSIGNED waittime;
UNSIGNED current_time;
INT16 tmoflag;
UNSIGNED event = 0,
dat = 0;
tqe_t *duptqe,
*tqe_wait; /* Timer queue entry */
/*******************************************************************
Receive_Message points to a single occurence in the event queue.
The index 3 signals that the structure is 3 words (or 6 bytes)
long and is formatted as follows:
struct
{
8 bits: the msg_class
8 bits: the event
16 bits: pointer to the next event on the queue
16 bits: the data field
}
*******************************************************************/
UNSIGNED Receive_Message[3] = {0, 0, 0};
UNSIGNED actual_size;
NU_SUPERV_USER_VARIABLES
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
tqe_wait = (tqe_t *)0;
/* Remove compilation warnings for unused parameters. */
UNUSED_PARAMETER(argc);
UNUSED_PARAMETER(argv);
for (;;)
{
/* Retrieve a message from the event queue. Note that if the source
queue is empty this task suspends until something becomes
available. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* If someone is waiting on the timer list, then we need to
calculate the next hit time for that timer. */
if (!tqe_wait)
tqe_wait = EQ_Event_List.flink;
if (tqe_wait)
{
current_time = NU_Retrieve_Clock();
/* Account for the wrapping of the clock. */
if (tqe_wait->duetime > current_time)
waittime = ((UNSIGNED) tqe_wait->duetime - current_time);
else
{
if( ( current_time - tqe_wait->duetime ) > 0x80000000UL )
waittime = 0xFFFFFFFFUL - tqe_wait->duetime + current_time + 1;
else
waittime = NU_NO_SUSPEND;
}
}
else
{
tqe_wait = (tqe_t *)0;
waittime = NU_SUSPEND;
}
/* If waittime is not NU_SUSPEND then there is a timeout value. */
if (waittime != NU_NO_SUSPEND)
{
NU_Release_Semaphore(&TCP_Resource);
status = NU_Receive_From_Queue(&eQueue, &Receive_Message[0],
(UNSIGNED)3, &actual_size, waittime);
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
}
else
{
NU_Release_Semaphore (&TCP_Resource);
NU_Relinquish();
if (tqe_wait == EQ_Event_List.flink)
{
NU_Obtain_Semaphore (&TCP_Resource, NU_SUSPEND);
status = NU_TIMEOUT;
}
else
{
tqe_wait = (tqe_t *)0;
continue;
}
}
/* Determine if the message was received successfully. */
if (status == NU_TIMEOUT)
{
if (tqe_wait == EQ_Event_List.flink)
{
/* Take off the head of the list. */
DLL_Dequeue(&EQ_Event_List);
/* Place any duplicate entries on to the timer list. */
duptqe = (tqe_t *)DLL_Dequeue(&tqe_wait->duplist);
while (duptqe)
{
tqpost((tqe_t *) &EQ_Event_List, duptqe);
duptqe = (tqe_t *)DLL_Dequeue(&tqe_wait->duplist);
}
/* Place the dequeued entry on the free list. */
DLL_Enqueue(&EQ_Event_Freelist, tqe_wait);
tmoflag = 1;
#if (INCLUDE_TCP == NU_TRUE)
/* Take care of event TCPRETRANS here...other events are
handled by the CASE statement below... */
if (tqe_wait->tqe_event == TCPRETRANS)
{
/* Get a pointer to the porlist entry. */
prt = TCP_Ports[tqe_wait->tqe_data];
TCP_Retransmit (prt, tqe_wait->tqe_ext_data);
tqe_wait = (tqe_t *)0;
NU_Release_Semaphore(&TCP_Resource);
continue;
}
else
#endif /* INCLUDE_TCP == NU_TRUE */
{
event = tqe_wait->tqe_event;
dat = tqe_wait->tqe_data;
tqe_wait = (tqe_t *)0;
status = NU_SUCCESS;
}
}
else
{
tqe_wait = (tqe_t *)0;
NU_Release_Semaphore(&TCP_Resource);
continue;
}
} /* end if status == NU_TIMEOUT */
else
{
tmoflag = 0;
tqe_wait = (tqe_t *)NU_NULL;
}
/* Determine if the message was received successfully. */
if (status == NU_SUCCESS)
{
if (!tmoflag)
{
event = Receive_Message[0];
dat = Receive_Message[2];
}
/* switch on the msg_class/event combination */
switch (event)
{
default:
break;
case CONNULL:
break;
/*********** CONNECTION CLASS **********************/
#if (INCLUDE_TCP == NU_TRUE)
case CONFAIL: /* connection attempt failed */
case CONOPEN: /* successful connect attempt */
/* Make sure the socket is not NULL, this is possible if a
TCP connection is made and immediately RESET by the
foreign host. */
if ((sock_ptr = SCK_Sockets[dat]) != NU_NULL)
{
/* return control to the waiting task */
if (sock_ptr->s_TXTask != NU_NULL)
NU_Resume_Task(sock_ptr->s_TXTask);
}
break;
case TCPACK:
/* An ack needs to be sent. */
/* Get a pointer to the port. */
prt = TCP_Ports[dat];
/* Clear the ACK timer flag in the port. */
prt->portFlags &= (~ACK_TIMER_SET);
/* Send the ack. */
TCP_ACK_It(prt, 1);
break;
case CONTX:
/* get a pointer into the port list table at the
entry pointed to by dat in the event queue */
prt = TCP_Ports[dat];
if ( (prt->xmitFlag == NU_SET) &&
(prt->out.nextPacket != NU_NULL) )
{
prt->out.tcp_flags |= TPUSH;
/* Save a pointer to the next packet to send. Then move
the next pointer forward. nextPacket should always
be NULL after these steps. */
buf_ptr = prt->out.nextPacket;
prt->out.nextPacket = prt->out.nextPacket->next;
/* Clear the event flag. */
prt->xmitFlag = NU_CLEAR;
/* Send the buffer. */
TCP_Xmit(prt, buf_ptr);
}
break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -