- Use select() to sleep when idle as opposed to busy waiting.

- Introduce com_busyWait cvar to go back to old behaviour
This commit is contained in:
Thilo Schulz 2011-02-02 16:46:23 +00:00
parent fa8201c9b6
commit e5dbce839a
7 changed files with 206 additions and 183 deletions

View file

@ -107,6 +107,8 @@ static cvar_t *net_port6;
static cvar_t *net_mcast6addr;
static cvar_t *net_mcast6iface;
static cvar_t *net_dropsim;
static struct sockaddr socksRelayAddr;
static SOCKET ip_socket = INVALID_SOCKET;
@ -201,7 +203,7 @@ char *NET_ErrorString( void ) {
default: return "NO ERROR";
}
#else
return strerror (errno);
return strerror(socketError);
#endif
}
@ -524,16 +526,17 @@ qboolean NET_IsLocalAddress( netadr_t adr ) {
/*
==================
Sys_GetPacket
NET_GetPacket
Never called by the game logic, just the system event queing
Receive one packet
==================
*/
#ifdef _DEBUG
int recvfromCount;
#endif
qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
qboolean NET_GetPacket(netadr_t *net_from, msg_t *net_message, fd_set *fdr)
{
int ret;
struct sockaddr_storage from;
socklen_t fromlen;
@ -543,7 +546,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
recvfromCount++; // performance check
#endif
if(ip_socket != INVALID_SOCKET)
if(ip_socket != INVALID_SOCKET && FD_ISSET(ip_socket, fdr))
{
fromlen = sizeof(from);
ret = recvfrom( ip_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen );
@ -577,7 +580,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
net_message->readcount = 0;
}
if( ret == net_message->maxsize ) {
if( ret >= net_message->maxsize ) {
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse;
}
@ -587,7 +590,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
}
}
if(ip6_socket != INVALID_SOCKET)
if(ip6_socket != INVALID_SOCKET && FD_ISSET(ip6_socket, fdr))
{
fromlen = sizeof(from);
ret = recvfrom(ip6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
@ -604,7 +607,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
SockadrToNetadr((struct sockaddr *) &from, net_from);
net_message->readcount = 0;
if(ret == net_message->maxsize)
if(ret >= net_message->maxsize)
{
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse;
@ -615,7 +618,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
}
}
if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket)
if(multicast6_socket != INVALID_SOCKET && multicast6_socket != ip6_socket && FD_ISSET(multicast6_socket, fdr))
{
fromlen = sizeof(from);
ret = recvfrom(multicast6_socket, (void *)net_message->data, net_message->maxsize, 0, (struct sockaddr *) &from, &fromlen);
@ -632,7 +635,7 @@ qboolean Sys_GetPacket( netadr_t *net_from, msg_t *net_message ) {
SockadrToNetadr((struct sockaddr *) &from, net_from);
net_message->readcount = 0;
if(ret == net_message->maxsize)
if(ret >= net_message->maxsize)
{
Com_Printf( "Oversize packet from %s\n", NET_AdrToString (*net_from) );
return qfalse;
@ -1499,6 +1502,8 @@ static qboolean NET_GetCvars( void ) {
modified += net_socksPassword->modified;
net_socksPassword->modified = qfalse;
net_dropsim = Cvar_Get("net_dropsim", "", CVAR_TEMP);
return modified ? qtrue : qfalse;
}
@ -1627,6 +1632,42 @@ void NET_Shutdown( void ) {
#endif
}
/*
====================
NET_Event
Called from NET_Sleep which uses select() to determine which sockets have seen action.
====================
*/
void NET_Event(fd_set *fdr)
{
byte bufData[MAX_MSGLEN + 1];
netadr_t from;
msg_t netmsg;
while(1)
{
MSG_Init(&netmsg, bufData, sizeof(bufData));
if(NET_GetPacket(&from, &netmsg, fdr))
{
if(net_dropsim->value > 0.0f && net_dropsim->value <= 100.0f)
{
// com_dropsim->value percent of incoming packets get dropped.
if(rand() < (int) (((double) RAND_MAX) / 100.0 * (double) net_dropsim->value))
continue; // drop this packet
}
if(com_sv_running->integer)
Com_RunAndTimeServerPacket(&from, &netmsg);
else
CL_PacketEvent(from, &netmsg);
}
else
break;
}
}
/*
====================
@ -1635,31 +1676,23 @@ NET_Sleep
Sleeps msec or until something happens on the network
====================
*/
void NET_Sleep( int msec ) {
void NET_Sleep(int msec)
{
struct timeval timeout;
fd_set fdset;
int highestfd = -1;
fd_set fdr;
int highestfd = -1, retval;
if (!com_dedicated->integer)
return; // we're not a server, just run full speed
if (ip_socket == INVALID_SOCKET && ip6_socket == INVALID_SOCKET)
return;
if (msec < 0 )
return;
FD_ZERO(&fdset);
FD_ZERO(&fdr);
if(ip_socket != INVALID_SOCKET)
{
FD_SET(ip_socket, &fdset);
FD_SET(ip_socket, &fdr);
highestfd = ip_socket;
}
if(ip6_socket != INVALID_SOCKET)
{
FD_SET(ip6_socket, &fdset);
FD_SET(ip6_socket, &fdr);
if(ip6_socket > highestfd)
highestfd = ip6_socket;
@ -1667,9 +1700,32 @@ void NET_Sleep( int msec ) {
timeout.tv_sec = msec/1000;
timeout.tv_usec = (msec%1000)*1000;
select(highestfd + 1, &fdset, NULL, NULL, &timeout);
}
#ifdef _WIN32
if(highestfd < 0)
{
// windows ain't happy when select is called without valid FDs
if(msec > 0)
msec--;
SleepEx(msec, 0);
return;
}
#define TVW32_BIAS 999
// windows adds a whole millisecond of latency, otherwise granularity seems to be fine.
if(timeout.tv_usec > TVW32_BIAS)
timeout.tv_usec -= TVW32_BIAS;
#endif
retval = select(highestfd + 1, &fdr, NULL, NULL, &timeout);
if(retval < 0)
Com_Printf("Warning: select() syscall failed: %s\n", NET_ErrorString());
else if(retval > 0)
NET_Event(&fdr);
}
/*
====================