📄 select.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
*
* select.c 4.4
*
* DESCRIPTION
*
* This file contains those functions associated with the NU_Select
* service.
*
* DATA STRUCTURES
*
* None
*
* FUNCTIONS
*
* NU_Select
* NU_FD_Check
* NU_FD_Set
* NU_FD_Init
* NU_FD_Reset
* SEL_Check_Recv
* SEL_Setup_Recv_Ports
*
* DEPENDENCIES
*
* nucleus.h
* target.h
* externs.h
* ip.h
* tcp.h
* udp.h
* socketd.h
* netevent.h
* ipraw.h
*
*************************************************************************/
#include "plus/nucleus.h"
#include "net/target.h"
#include "net/inc/externs.h"
#include "net/inc/ip.h"
#include "net/inc/tcp.h"
#include "net/inc/udp.h"
#include "net/inc/socketd.h"
#include "net/inc/netevent.h"
#include "net/inc/ipraw.h"
/*************************************************************************
*
* FUNCTION
*
* NU_Select
*
* DESCRIPTION
*
* This fuction allows an application to check for data on multiple
* sockets. Alternatively multiple server sockets (those that are
* listening for connections) can be checked for established
* conections. The calling application can choose to return
* immediately, suspend, or specify a timeout.
*
* INPUTS
*
* max_sockets Maximum socket to check.
* *readfs A bit field indicating which sockets
* to check for data.
* *writefs Not currently used.
* *exceptfs A bit field indicating which sockets
* to check for conections.
* timeout Indicates the timeout desired. Either
* NU_SUSPEND, NU_NO_SUSPEND, or a
* timeout value.
*
* OUTPUTS
*
* NU_SUCCESS Indicates successfull completion
* NU_NO_SOCKETS
* NU_INVALID_SOCKET
*
*************************************************************************/
STATUS NU_Select(INT max_sockets, FD_SET *readfs, FD_SET *writefs,
FD_SET *exceptfs, UNSIGNED timeout)
{
INT16 read_flag = 0;
INT16 i, j = 0;
STATUS return_status;
NU_TASK *Task_ID;
OPTION old_preempt;
NU_SUPERV_USER_VARIABLES
/* Clean up warnings. This parameter is used for socket compatibility
but we are currently not making any use of it. */
UNUSED_PARAMETER(writefs);
UNUSED_PARAMETER(exceptfs);
if((max_sockets == 0) || (max_sockets > NSOCKETS))
return(NU_NO_SOCKETS);
if ( readfs == NU_NULL )
return(NU_NO_SOCKETS);
/* Make sure that at least one bit is set. */
for(i=0; (i < FD_ELEMENTS) && (!read_flag); i++)
{
if ((UINT32)readfs && ((UINT32)readfs->words[i] != 0))
{
read_flag = 1;
}
}
/* Was at least one bit found to be set in the read group. */
if ( !read_flag )
return(NU_NO_SOCKETS);
/* Switch to supervisor mode. */
NU_SUPERVISOR_MODE();
for (;;)
{
/* Don't let anyone else in until we are through. */
NU_Obtain_Semaphore(&TCP_Resource, NU_SUSPEND);
/* Check to see if any of the sockets are data ready. If so readfs will
be returned with only the bits associated with the ready sockets set.
Else readfs will be returned with no bits changed.
*/
return_status = SEL_Check_Recv(max_sockets, readfs);
/* If at least one socket was data ready then break out of this while
loop and return. Break also if suspension was not desired, or if j =
1. Note that j is only set to one if a timeout is desired but not
unconditional suspension. If unconditional suspension was specified
then we will only return when a data ready socket is found, even if
this task is some how inadvertantly woken up. We will also break out
if there were no valid sockets to select on.
*/
if ( (return_status == NU_SUCCESS) || (timeout == NU_NO_SUSPEND) ||
j || (return_status == NU_INVALID_SOCKET))
break;
/* Go ahead and retrieve the current task pointer once. It is used in
several places below. */
Task_ID = NU_Current_Task_Pointer();
return_status = -1;
if(read_flag)
return_status = SEL_Setup_Recv_Ports(max_sockets, readfs, Task_ID);
/* If we did not successfully setup a recv port then get out.
There is no point in continuing. */
if ( return_status != NU_SUCCESS )
break;
if (timeout != NU_SUSPEND)
{
/* Set up the timer to wake us up if the event never occurs. */
UTL_Timerset(SELECT, (UNSIGNED)Task_ID, timeout, 0);
j = 1;
}
/* Let others in while we are waiting for the connection. */
old_preempt = NU_Change_Preemption(NU_NO_PREEMPT);
NU_Release_Semaphore(&TCP_Resource);
/* suspend the current task until data ready */
NU_Suspend_Task(Task_ID);
NU_Change_Preemption(old_preempt);
if (timeout != NU_SUSPEND)
{
/* At this point there is no way to tell if we were resumed because
of a timeout or because the event we are waitting on ocurred. In
the former case the event will already be cleared. Try to clear
it here anyway. */
UTL_Timerunset(SELECT, (UNSIGNED)Task_ID, (INT32)1);
}
/* We need to clean these s_RXTask's after waking up */
if (read_flag)
SEL_Setup_Recv_Ports(max_sockets, readfs, NU_NULL);
} /* while(1) */
/* Let others in while we are waiting for the connection. */
NU_Release_Semaphore(&TCP_Resource);
/* Switch back to user mode. */
NU_USER_MODE();
return (return_status);
} /* end of NU_Select */
/*************************************************************************
*
* FUNCTION
*
* NU_FD_Check
*
* DESCRIPTION
*
* This fuction will check to see if a particular bit has been
* set in a bit map.
*
* INPUTS
*
* socket
* *fd
*
* OUTPUTS
*
* INT NU_TRUE or NU_FALSE
*
*************************************************************************/
INT NU_FD_Check(INT socket, FD_SET *fd)
{
if (fd->words[socket/FD_BITS] & ((UINT32)NU_TRUE<<((UINT32)socket%(UINT32)FD_BITS)))
return(NU_TRUE);
else
return(NU_FALSE);
}
/*************************************************************************
*
* FUNCTION
*
* NU_FD_Set
*
* DESCRIPTION
*
* Sets a bit in a bit map.
*
* INPUTS
*
* socket
* *fd
*
* OUTPUTS
*
* None
*
*************************************************************************/
VOID NU_FD_Set(INT socket, FD_SET *fd)
{
fd->words[socket/FD_BITS] |= (UINT32)NU_TRUE<<((UINT32)socket%(UINT32)FD_BITS);
}
/*************************************************************************
*
* FUNCTION
*
* NU_FD_Init
*
* DESCRIPTION
*
* Sets all bits in a bit map to 0.
*
* INPUTS
*
* *fd
*
* OUTPUTS
*
* None
*
*************************************************************************/
VOID NU_FD_Init(FD_SET *fd)
{
INT i;
for (i=0; i<FD_ELEMENTS; fd->words[i++]=0L);
}
/*************************************************************************
*
* FUNCTION
*
* NU_FD_Reset
*
* DESCRIPTION
*
* Resets a bit in a bit map.
*
* INPUTS
*
* socket
* *fd
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -