Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 4 Dec 1995 21:58:03 +1100
From:      Bruce Evans <bde@zeta.org.au>
To:        bde@zeta.org.au, witr@rwwa.com
Cc:        freebsd-hackers@freebsd.org
Subject:   Re: Proper way to determine non-blocking status...
Message-ID:  <199512041058.VAA03902@godzilla.zeta.org.au>

next in thread | raw e-mail | index | archive | help
>Do you mind if I pepper you with some more questions?

Perhaps these should be added to the NFAQ :-).

>1) Is there any guidance on what priority pass to tsleep?

It doesn't matter much.  Normally use something between
PZERO and PUSER, and OR in PCATCH for interruptible
sleeps.

>2) Would I be correct in assuming that IPL will be the
>same *after* tsleep returns as it was *before*.  (I'm
>already pretty sure of that, reading the code.  It makes
>sense anyway.)

Yes.

>3) Is there anyway short of using timeout() to hook
>into the clock interrupt (like xxpoll() in SYSV)?

No.  Restart the timeout when the timeout handler gets
called (or when it returns).

>4) I'm porting a streams driver to FreeBSD.  It isn't
>a network style device, so I need to use the character
>dev model.  The backend (and parts of the frontend)
>construct and enqueue messages to pass to the user
>when he eventually does a read.  I need to alloc
>memory for each of these messages (which have random
>sizes, from dozens of bytes up to 1024 bytes).  I'm curently
>using malloc(size,M_DEVBUF,waitflag).  Is there better
>way to do this?

Not unless you can use mbufs.  Don't depend on mallocing more
than a page or two (1024 bytes is OK).  Don't call malloc()
from interrupt handlers except for network drivers.  Be
careful about using the M_WAITOK flag - it allows malloc()
to sleep, so you probably wouldn't want to use it while 
spl'ed.  Don't manage a large pool of free buffers yourself.
One or two might be good.

>5) Are there any ipl restrictions on calling wakeup()?

No.

>6) Where does device ipl come from?  I don't see it in the
>config file?  How do I know what ipl my device interrupts
>at?

It is tty_imask for ttys etc, where ttys are the things
specified by the keyword `tty' in the config file and the
mask is the OR of the hardware masks for each tty device
together with a few software masks.  This will change.

>7) xxintr(int unit).  Which unit?  How computed?  I'm used
>to xxintr(int vec).

unit = intr_unit[vec].  intr_unit[] is initialized by
register_intr(), normally to the unit numbers specified in
the config file.  This will change to xxintr(void *cookie)
where cookie is normally (void *)&xxdriverstuff[unit].

>8) I see that people often avoid having xxread/xxwrite routines
>for this situation.  I did the opposite: I have xxread/xxwrite
>routines and require the stuff sent to be protocol packets.
>Is there any major drawback to this besides the possiblity
>of having some butthead do ``cat /etc/passwd /dev/mcc''?

No.

>Actual routine is:

>int mccread(dev_t dev, struct uio *uio, int ioflag)
>{
>  mcc_t *mcc = MCC_DEV(dev);		/* Private data for this channel */
>  mcc_mblk_t *mp;
>  int oldspl;

>  /* Send first accumulated message, or wait if possible */
> again:
>  oldspl = SPLINT();			/* Lock */
>  mp = l_remove_head(&mcc->mcc_done);	/* Get anything there */
>  if (mp) {				/* Return it */
>    mc_primitives_union_t *mcp = MCC_MBLK_DATA(mp);
>    if (mcp->header.mc_length > uio->uio_resid) {
>      /* 
>	 We refuse to copy less than a complete message,
>         so we requeue this one!
>      */
>      l_add_head(&mcc->mcc_done,mp);	/* Return it to head of list */
>      splx(oldspl);			/* Unlock */
>      return EINVAL;
>    } else {
>      splx(oldspl);			/* Unlock */
>      uiomove(mcp, mcp->header.mc_length, uio);
       ^^^^^^^ check the return code - it can be EFAULT...
>      free(mp,M_DEVBUF);
>      return 0;
>    }
>  } else if (ioflag & IO_NDELAY) {	/* Can't block, sorry */
>    splx(oldspl);			/* Unlock */
>    return EWOULDBLOCK;
>  } else {				/* Otherwise try again */
>    int error;
>    mcc->mcc_blocked = 1;		/* Mark ourselves blocked */
>    error = tsleep(&mcc->mcc_done, PZERO | PCATCH, "mccin", 0);
>    mcc->mcc_blocked = 0;		/* Mark ourselves unblocked */
>    splx(oldspl);			/* Unlock */
>    if (error && (error != ERESTART)) return error;
>    goto again;
>  }
>}



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199512041058.VAA03902>