Files
epics-base/src/ca/bsd_depen.c
1997-04-10 19:26:27 +00:00

223 lines
5.6 KiB
C
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/*
* $Id$
* Author: Jeffrey O. Hill
* hill@luke.lanl.gov
* (505) 665 1831
* Date: 9-93
*
* Experimental Physics and Industrial Control System (EPICS)
*
* Copyright 1991, the Regents of the University of California,
* and the University of Chicago Board of Governors.
*
* This software was produced under U.S. Government contracts:
* (W-7405-ENG-36) at the Los Alamos National Laboratory,
* and (W-31-109-ENG-38) at Argonne National Laboratory.
*
* Initial development by:
* The Controls and Automation Group (AT-8)
* Ground Test Accelerator
* Accelerator Technology Division
* Los Alamos National Laboratory
*
* Co-developed with
* The Controls and Computing Group
* Accelerator Systems Division
* Advanced Photon Source
* Argonne National Laboratory
*
* Modification Log:
* -----------------
*
*/
#include "iocinf.h"
/*
* cac_select_io()
*
* NOTE: on multithreaded systems this assumes that the
* local implementation of select is reentrant
*/
int cac_select_io(struct timeval *ptimeout, int flags)
{
/*
* Use auto timeout so there is no chance of
* recursive reuse of ptimeout
*/
struct timeval autoTimeOut = *ptimeout;
long status;
IIU *piiu;
unsigned long freespace;
SOCKET maxfd;
caFDInfo *pfdi;
LOCK;
pfdi = (caFDInfo *) ellGet(&ca_static->fdInfoFreeList);
if (!pfdi) {
pfdi = (caFDInfo *) calloc (1, sizeof(*pfdi));
if (!pfdi) {
ca_printf("CAC: no mem for select ctx?\n");
UNLOCK;
return -1;
}
}
ellAdd (&ca_static->fdInfoList, &pfdi->node);
FD_ZERO (&pfdi->readMask);
FD_ZERO (&pfdi->writeMask);
maxfd = 0;
for( piiu = (IIU *) iiuList.node.next;
piiu;
piiu = (IIU *) piiu->node.next) {
if (piiu->state==iiu_disconnected) {
continue;
}
#ifdef WIN32
/* Under WIN32, FD_SETSIZE is the number of sockets,
* not the max. file descriptor value that you may select() !
*
* Of course it's not allowed to look into fd_count,
* but what shall we do? -kuk-
*/
if (pfdi->readMask.fd_count >= FD_SETSIZE)
{
ca_printf(
"%s.%d: no room for fd %d in fd_set (FD_SETSIZE=%d)\n",
__FILE__, __LINE__, piiu->sock_chan, FD_SETSIZE);
continue;
}
#else
if (piiu->sock_chan>=FD_SETSIZE)
{
ca_printf(
"%s.%d: file number %d > FD_SETSIZE=%d ignored\n",
__FILE__, __LINE__, piiu->sock_chan, FD_SETSIZE);
continue;
}
#endif
/*
* Dont bother receiving if we have insufficient
* space for the maximum UDP message, or space
* for one TCP byte.
*/
if (flags&CA_DO_RECVS) {
freespace = cacRingBufferWriteSize (&piiu->recv, TRUE);
if (freespace>=piiu->minfreespace) {
maxfd = max (maxfd,piiu->sock_chan);
FD_SET (piiu->sock_chan, &pfdi->readMask);
piiu->recvPending = TRUE;
}
else {
piiu->recvPending = FALSE;
}
}
else {
piiu->recvPending = FALSE;
}
if (flags&CA_DO_SENDS) {
if (piiu->state==iiu_connecting) {
FD_SET (piiu->sock_chan, &pfdi->writeMask);
}
else {
if (cacRingBufferReadSize(&piiu->send, FALSE)>0) {
maxfd = max (maxfd,piiu->sock_chan);
FD_SET (piiu->sock_chan, &pfdi->writeMask);
}
}
}
}
UNLOCK;
# if defined(__hpux)
status = select(
maxfd+1,
(int *)&pfdi->readMask,
(int *)&pfdi->writeMask,
(int *)NULL,
&autoTimeOut);
# else
status = select(
maxfd+1,
&pfdi->readMask,
&pfdi->writeMask,
NULL,
&autoTimeOut);
# endif
/*
* get a new time stamp if we have been waiting
* for any significant length of time
*/
if (ptimeout->tv_sec || ptimeout->tv_usec) {
cac_gettimeval (&ca_static->currentTime);
}
if (status<0) {
if (SOCKERRNO == EINTR) {
}
else if (SOCKERRNO == EWOULDBLOCK) {
ca_printf("CAC: blocked at select ?\n");
}
else if (SOCKERRNO == ESRCH) {
}
else {
ca_printf (
"CAC: unexpected select fail: %s\n",
strerror(SOCKERRNO));
}
}
LOCK;
if (status>0) {
for ( piiu = (IIU *) iiuList.node.next;
piiu;
piiu = (IIU *) piiu->node.next) {
if (piiu->state==iiu_disconnected) {
continue;
}
if (FD_ISSET(piiu->sock_chan,&pfdi->readMask)) {
(*piiu->recvBytes)(piiu);
/*
* if we were not waiting and there is a
* message present then start to suspect that
* we are getting behind
*/
if (ptimeout->tv_sec==0 || ptimeout->tv_usec==0) {
flow_control_on(piiu);
}
}
else if (piiu->recvPending) {
/*
* if we are looking for incoming messages
* and there are none then we are certain that
* we are not getting behind
*/
flow_control_off(piiu);
}
if (FD_ISSET(piiu->sock_chan,&pfdi->writeMask)) {
(*piiu->sendBytes)(piiu);
}
}
}
ellDelete (&ca_static->fdInfoList, &pfdi->node);
ellAdd (&ca_static->fdInfoFreeList, &pfdi->node);
UNLOCK;
return status;
}