Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 20 Nov 1997 08:25:48 -0800 (PST)
From:      "Jamil J. Weatherbee" <jamil@trojanhorse.ml.org>
To:        Joerg Wunsch <joerg_wunsch@uriah.heep.sax.de>
Cc:        hackers@freebsd.org
Subject:   Re: vnode.h and IO_NDELAY (help!!)
Message-ID:  <Pine.BSF.3.96.971120080600.1289B-100000@trojanhorse.ml.org>
In-Reply-To: <19971120090611.FW37911@uriah.heep.sax.de>

next in thread | previous in thread | raw e-mail | index | archive | help

global, does not even show there being an rtcread on my system (maybye
because it is -stable), there is an rtc.h though.
Are you saying I should support the FIONBIO ioctl()?  Where do I find the
definition of that?  Do you have an example?

I had some problems with returning an error (EWOULDBLOCK) if I broke out
because the I/O was going to block.  Doesn't returing an error from your
read routine make the users call to read(2) return -1 and errno set to
your error?  Anyway I thought that a non-blocking data source should just
simply return 0 when it was no data, not an error.  Because thats how I've
seen read(2) used with select, basically select() catch a descriptor that 
is ready and exhaust that data source until it reads 0.  -1 is really an
error.  

Also according to the tsleep manpage, why do you only catch ERESTART and
not EINTR, I found that that catching EINTR was important for me because
if the user threw a huge buffer at me and the acquisition rate was down at
64  bytes/sec, It might take a while after pressing ctrl-C for the program
to exit.  So I catch anything non-zero and break out, without returning an
error (except for timeout).  The thing is that the uio structure might
already contain some data, and I don't want to loose that normally.
Unless there is something really wrong (timeout).  I am afraid if I return
an error than the user will not be able to get at whatever partial data
was there.   For instance they might want to have a signal catcher that
catches SIGINT and shuts some things down.  Once that exits I assume they
would end up at the instruction after the read call and they could still
get that final data from the interrupted read right?

Anyway can you take a look at this and tell me how it should be?
Also about how I implement (and why) the FIONBIO call?


Here is my code fragment:

--------------------------------------------------------

/* how to read from the board */
static int alog_read (dev_t dev, struct uio *uio, int ioflag)
{
  int unit = UNIT(dev);
  int chan = CHANNEL(dev);
  talog_unit *info = alog_unit[unit];
  int s, oldtrig, terr, toread, err = 0;

  s = spltty();
      
  oldtrig = info->chan[chan].fifotrig; /* save official trigger value */   
  while (uio->uio_resid >= sizeof(u_short)) /* while uio has space */
   {
     if (!info->chan[chan].fifosize) /* if we have an empty fifo */
      {
        if (ioflag & IO_NDELAY) break; /* exit if we are non-blocking */
        /* Start filling fifo on first blocking read */
	if (info->chan[chan].status == STATUS_INIT)
	     info->chan[chan].status = STATUS_INUSE;	 
        /* temporarily adjust the fifo trigger to be optimal size */
	info->chan[chan].fifotrig = 
	  min (READMAXTRIG, uio->uio_resid / sizeof(u_short));
	/* lets sleep until we have some io available or timeout */
        terr = tsleep (&(info->chan[chan].fifo), READPRI | PCATCH, READMSG,
			 info->chan[chan].fifotrig*READTIMO);
	if (terr == EWOULDBLOCK)
	 {    printf (DEVFORMAT ": read timeout\n", unit,
	 	       'a'+EMUX(chan), IMUX(chan));	    
           err = ETIMEDOUT;
	   break; /* were outta here */	
	 }
        if (terr) break; /* if caught a signal then just break out */
      }
	 
     /* ok, now if we got here there is something to read from the fifo */
     
     /* calculate how many entries we can read out from the fifostart
      * pointer */ 
     toread = min (uio->uio_resid / sizeof(u_short), 
		   min (info->chan[chan].fifosize, 
		         FIFOSIZE - info->chan[chan].fifostart));
     /* perform the move, if there is an error then exit */
     if (err = uiomove((caddr_t)
			&(info->chan[chan].fifo[info->chan[chan].fifostart]), 
	                   toread * sizeof(u_short), uio)) break;
     info->chan[chan].fifosize -= toread; /* fifo this much smaller */ 
     info->chan[chan].fifostart += toread; /* we got this many more */
     if (info->chan[chan].fifostart == FIFOSIZE)
       info->chan[chan].fifostart = 0; /* wrap around fifostart */
      
   }
  info->chan[chan].fifotrig = oldtrig; /* restore trigger changes */
  splx(s);		       
  return err;
}




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.3.96.971120080600.1289B-100000>