|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Copyright (c) 1998,1999,2000
|
|
Packit |
23ab03 |
* Traakan, Inc., Los Altos, CA
|
|
Packit |
23ab03 |
* All rights reserved.
|
|
Packit |
23ab03 |
*
|
|
Packit |
23ab03 |
* Redistribution and use in source and binary forms, with or without
|
|
Packit |
23ab03 |
* modification, are permitted provided that the following conditions
|
|
Packit |
23ab03 |
* are met:
|
|
Packit |
23ab03 |
* 1. Redistributions of source code must retain the above copyright
|
|
Packit |
23ab03 |
* notice unmodified, this list of conditions, and the following
|
|
Packit |
23ab03 |
* disclaimer.
|
|
Packit |
23ab03 |
* 2. Redistributions in binary form must reproduce the above copyright
|
|
Packit |
23ab03 |
* notice, this list of conditions and the following disclaimer in the
|
|
Packit |
23ab03 |
* documentation and/or other materials provided with the distribution.
|
|
Packit |
23ab03 |
*
|
|
Packit |
23ab03 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
|
Packit |
23ab03 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
Packit |
23ab03 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
Packit |
23ab03 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
|
Packit |
23ab03 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
Packit |
23ab03 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
Packit |
23ab03 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
Packit |
23ab03 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
|
Packit |
23ab03 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
|
Packit |
23ab03 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
|
Packit |
23ab03 |
* SUCH DAMAGE.
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Project: NDMJOB
|
|
Packit |
23ab03 |
* Ident: $Id: $
|
|
Packit |
23ab03 |
*
|
|
Packit |
23ab03 |
* Description:
|
|
Packit |
23ab03 |
*
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
#include "ndmlib.h"
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Initialize a channel. Make sure it won't be confused for active.
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_initialize (struct ndmchan *ch, char *name)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
NDMOS_MACRO_ZEROFILL(ch);
|
|
Packit |
23ab03 |
ch->name = name ? name : "???";
|
|
Packit |
23ab03 |
ch->fd = -1;
|
|
Packit |
23ab03 |
ch->mode = NDMCHAN_MODE_IDLE;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Set the data buffer
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_setbuf (struct ndmchan *ch, char *data, unsigned data_size)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
ch->data = data;
|
|
Packit |
23ab03 |
ch->data_size = data_size;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
ch->beg_ix = 0;
|
|
Packit |
23ab03 |
ch->end_ix = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return 0;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Interfaces for starting a channel in various modes.
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_mode (struct ndmchan *ch, int fd, int chan_mode)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
ch->fd = fd;
|
|
Packit |
23ab03 |
ch->mode = chan_mode;
|
|
Packit |
23ab03 |
return 0;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_read (struct ndmchan *ch, int fd)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_READ);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_write (struct ndmchan *ch, int fd)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_WRITE);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_readchk (struct ndmchan *ch, int fd)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_READCHK);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_listen (struct ndmchan *ch, int fd)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_LISTEN);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_resident (struct ndmchan *ch)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, -1, NDMCHAN_MODE_RESIDENT);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_start_pending (struct ndmchan *ch, int fd)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_start_mode (ch, fd, NDMCHAN_MODE_PENDING);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Change a PENDING channel to an active (READ/WRITE) channel
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_pending_to_mode (struct ndmchan *ch, int chan_mode)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
ch->mode = chan_mode;
|
|
Packit |
23ab03 |
return 0;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_pending_to_read (struct ndmchan *ch)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_pending_to_mode (ch, NDMCHAN_MODE_READ);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_pending_to_write (struct ndmchan *ch)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
return ndmchan_pending_to_mode (ch, NDMCHAN_MODE_WRITE);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Interfaces for stopping (close()ing) a channel.
|
|
Packit |
23ab03 |
* This is a bit of a hodge-podge. Could probably be cleaner.
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_set_eof (struct ndmchan *ch)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
ch->eof = 1;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_close_set_errno (struct ndmchan *ch, int err_no)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
ch->eof = 1;
|
|
Packit |
23ab03 |
if (ch->fd >= 0) {
|
|
Packit |
23ab03 |
close (ch->fd);
|
|
Packit |
23ab03 |
ch->fd = -1;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
ch->mode = NDMCHAN_MODE_CLOSED;
|
|
Packit |
23ab03 |
ch->saved_errno = err_no;
|
|
Packit |
23ab03 |
ch->beg_ix = ch->end_ix = 0;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_close (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
ndmchan_close_set_errno (ch, 0);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_abort (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
ndmchan_close_set_errno (ch,
|
|
Packit |
23ab03 |
ch->saved_errno == 0 ? EINTR : ch->saved_errno);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_close_as_is (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
ndmchan_close_set_errno (ch, ch->saved_errno);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_cleanup (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
if (ch->mode != NDMCHAN_MODE_IDLE) {
|
|
Packit |
23ab03 |
ndmchan_close_as_is (ch);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* CPU Quantum for a set of channels. There are three
|
|
Packit |
23ab03 |
* phases:
|
|
Packit |
23ab03 |
* 1) Identify the channels to check for ready to do I/O.
|
|
Packit |
23ab03 |
* For example, a READ channel with no buffer space
|
|
Packit |
23ab03 |
* need not be checked.
|
|
Packit |
23ab03 |
* 2) Call the OS dependent function that performs the
|
|
Packit |
23ab03 |
* actual select()/poll()/whatever.
|
|
Packit |
23ab03 |
* 3) Based on the results, perform actual read()/write().
|
|
Packit |
23ab03 |
* EOF and errors are detected.
|
|
Packit |
23ab03 |
*
|
|
Packit |
23ab03 |
* This is constructed so that applications which can not use
|
|
Packit |
23ab03 |
* ndmchan_quantum() directly have access to the helper functions
|
|
Packit |
23ab03 |
* ndmchan_pre_poll() and ndmchan_post_poll().
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_quantum (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
int rc;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
ndmchan_pre_poll (chtab, n_chtab);
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
rc = ndmos_chan_poll (chtab, n_chtab, milli_timo);
|
|
Packit |
23ab03 |
if (rc <= 0)
|
|
Packit |
23ab03 |
return rc;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
rc = ndmchan_post_poll (chtab, n_chtab);
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return rc;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_pre_poll (struct ndmchan *chtab[], unsigned n_chtab)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
struct ndmchan * ch;
|
|
Packit |
23ab03 |
unsigned int i, n_check;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_check = 0;
|
|
Packit |
23ab03 |
for (i = 0; i < n_chtab; i++) {
|
|
Packit |
23ab03 |
ch = chtab[i];
|
|
Packit |
23ab03 |
ch->ready = 0;
|
|
Packit |
23ab03 |
ch->check = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->error)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
default:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_IDLE:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_PENDING:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_RESIDENT:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_CLOSED:
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_LISTEN:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READCHK:
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ:
|
|
Packit |
23ab03 |
if (ch->eof)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
if (ndmchan_n_avail (ch) == 0)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE:
|
|
Packit |
23ab03 |
if (ndmchan_n_ready (ch) == 0)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
ch->check = 1;
|
|
Packit |
23ab03 |
n_check++;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return n_check;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_post_poll (struct ndmchan *chtab[], unsigned n_chtab)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
struct ndmchan * ch;
|
|
Packit |
23ab03 |
unsigned int i;
|
|
Packit |
23ab03 |
int rc, len, n_ready;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_ready = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
for (i = 0; i < n_chtab; i++) {
|
|
Packit |
23ab03 |
ch = chtab[i];
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (!ch->ready)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ:
|
|
Packit |
23ab03 |
len = ndmchan_n_avail (ch);
|
|
Packit |
23ab03 |
if (len <= 0) continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_ready++;
|
|
Packit |
23ab03 |
rc = read (ch->fd, &ch->data[ch->end_ix], len);
|
|
Packit |
23ab03 |
if (rc < 0) {
|
|
Packit |
23ab03 |
if (errno != NDMOS_CONST_EWOULDBLOCK) {
|
|
Packit |
23ab03 |
ch->error = ch->eof = 1;
|
|
Packit |
23ab03 |
ch->saved_errno = errno;
|
|
Packit |
23ab03 |
if (!ch->saved_errno)
|
|
Packit |
23ab03 |
ch->saved_errno = -1;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
/* no bytes read */
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
} else if (rc == 0) {
|
|
Packit |
23ab03 |
ch->eof = 1;
|
|
Packit |
23ab03 |
ch->error = 0;
|
|
Packit |
23ab03 |
ch->saved_errno = 0;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
ch->end_ix += rc;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE:
|
|
Packit |
23ab03 |
len = ndmchan_n_ready (ch);
|
|
Packit |
23ab03 |
if (len <= 0) continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_ready++;
|
|
Packit |
23ab03 |
rc = write (ch->fd, &ch->data[ch->beg_ix], len);
|
|
Packit |
23ab03 |
if (rc < 0) {
|
|
Packit |
23ab03 |
if (errno != NDMOS_CONST_EWOULDBLOCK) {
|
|
Packit |
23ab03 |
ch->eof = 1;
|
|
Packit |
23ab03 |
ch->error = 1;
|
|
Packit |
23ab03 |
ch->saved_errno = errno;
|
|
Packit |
23ab03 |
if (!ch->saved_errno)
|
|
Packit |
23ab03 |
ch->saved_errno = -1;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
/* no bytes written */
|
|
Packit |
23ab03 |
/* EWOULDBLOCK but ready? */
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
} else if (rc == 0) {
|
|
Packit |
23ab03 |
/* NDMOS_CONST_EWOULDBLOCK? */
|
|
Packit |
23ab03 |
ch->eof = 1;
|
|
Packit |
23ab03 |
ch->error = 1;
|
|
Packit |
23ab03 |
ch->saved_errno = 0;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
ch->beg_ix += rc;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return n_ready;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Channel data buffer space manipulation.
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_compress (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
unsigned len = ch->end_ix - ch->beg_ix;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->beg_ix > 0 && len > 0) {
|
|
Packit |
23ab03 |
bcopy (&ch->data[ch->beg_ix], ch->data, len);
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
if (len > ch->data_size)
|
|
Packit |
23ab03 |
len = 0;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
ch->beg_ix = 0;
|
|
Packit |
23ab03 |
ch->end_ix = len;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_n_avail (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
if (ch->end_ix == ch->beg_ix)
|
|
Packit |
23ab03 |
ch->end_ix = ch->beg_ix = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->end_ix >= ch->data_size) {
|
|
Packit |
23ab03 |
ndmchan_compress (ch);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
return ch->data_size - ch->end_ix;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_n_avail_record (struct ndmchan *ch, unsigned long size) {
|
|
Packit |
23ab03 |
if (ch->end_ix == ch->beg_ix)
|
|
Packit |
23ab03 |
ch->end_ix = ch->beg_ix = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->end_ix >= ch->data_size - size) {
|
|
Packit |
23ab03 |
ndmchan_compress (ch);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
return ch->data_size - ch->end_ix;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_n_avail_total (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
if (ch->end_ix == ch->beg_ix)
|
|
Packit |
23ab03 |
ch->end_ix = ch->beg_ix = 0;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->end_ix >= ch->data_size) {
|
|
Packit |
23ab03 |
ndmchan_compress (ch);
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
return ch->data_size - ch->end_ix + ch->beg_ix;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmchan_n_ready (struct ndmchan *ch) {
|
|
Packit |
23ab03 |
return ch->end_ix - ch->beg_ix;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Interfaces for interpreting channel state, obtaining pointers, lengths
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
enum ndmchan_read_interpretation
|
|
Packit |
23ab03 |
ndmchan_read_interpret (struct ndmchan *ch, char **data_p,
|
|
Packit |
23ab03 |
unsigned *n_ready_p)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
unsigned n_ready;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_ready = *n_ready_p = ndmchan_n_ready (ch);
|
|
Packit |
23ab03 |
*data_p = &ch->data[ch->beg_ix];
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->error) {
|
|
Packit |
23ab03 |
if (n_ready == 0) {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_DONE_ERROR;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_DRAIN_ERROR;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->eof) {
|
|
Packit |
23ab03 |
if (n_ready == 0) {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_DONE_EOF;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_DRAIN_EOF;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (n_ready == 0) {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_EMPTY;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (n_ready == ch->data_size) {
|
|
Packit |
23ab03 |
return NDMCHAN_RI_READY_FULL;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return NDMCHAN_RI_READY;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
enum ndmchan_write_interpretation
|
|
Packit |
23ab03 |
ndmchan_write_interpret (struct ndmchan *ch, char **data_p,
|
|
Packit |
23ab03 |
unsigned *n_avail_p)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
unsigned n_avail;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
n_avail = *n_avail_p = ndmchan_n_avail (ch);
|
|
Packit |
23ab03 |
*data_p = &ch->data[ch->end_ix];
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->error) {
|
|
Packit |
23ab03 |
/* We don't use WI_DRAIN_ERROR. If it's kaput, it's kaput */
|
|
Packit |
23ab03 |
return NDMCHAN_WI_DONE_ERROR;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->eof) {
|
|
Packit |
23ab03 |
if (n_avail == ch->data_size) {
|
|
Packit |
23ab03 |
return NDMCHAN_WI_DONE_EOF;
|
|
Packit |
23ab03 |
} else {
|
|
Packit |
23ab03 |
return NDMCHAN_WI_DRAIN_EOF;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (n_avail == 0) {
|
|
Packit |
23ab03 |
return NDMCHAN_WI_FULL;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (n_avail == ch->data_size) {
|
|
Packit |
23ab03 |
return NDMCHAN_WI_AVAIL_EMPTY;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return NDMCHAN_WI_AVAIL;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Pretty printer
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
void
|
|
Packit |
23ab03 |
ndmchan_pp (struct ndmchan *ch, char *buf)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
int show_ra = 0;
|
|
Packit |
23ab03 |
char * bp = buf;
|
|
Packit |
23ab03 |
char * p;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
sprintf (bp, "name=%s", ch->name); while (*bp) bp++;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_IDLE: p = "idle"; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_RESIDENT: p = "resident"; show_ra = 1; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ: p = "read"; show_ra = 1; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE: p = "write"; show_ra = 1; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READCHK: p = "readchk"; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_LISTEN: p = "listen"; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_PENDING: p = "pending"; break;
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_CLOSED: p = "closed"; break;
|
|
Packit |
23ab03 |
default: p = "mode=???"; break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
sprintf (bp, " %s ", p);
|
|
Packit |
23ab03 |
while (*bp) bp++;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (show_ra) {
|
|
Packit |
23ab03 |
sprintf (bp, "ready=%d avail=%d ",
|
|
Packit |
23ab03 |
ndmchan_n_ready(ch), ndmchan_n_avail(ch));
|
|
Packit |
23ab03 |
while (*bp) bp++;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
if (ch->ready) strcat (bp, "-rdy");
|
|
Packit |
23ab03 |
if (ch->check) strcat (bp, "-chk");
|
|
Packit |
23ab03 |
if (ch->eof) strcat (bp, "-eof");
|
|
Packit |
23ab03 |
if (ch->error) strcat (bp, "-err");
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
#ifdef NDMOS_OPTION_USE_SELECT_FOR_CHAN_POLL
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Here because it is almost always used
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmos_chan_poll (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
struct ndmchan * ch;
|
|
Packit |
23ab03 |
fd_set rfds, wfds;
|
|
Packit |
23ab03 |
int nfd = 0, rc;
|
|
Packit |
23ab03 |
unsigned i;
|
|
Packit |
23ab03 |
struct timeval timo;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
FD_ZERO(&rfds);
|
|
Packit |
23ab03 |
FD_ZERO(&wfds);
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
timo.tv_sec = milli_timo / 1000;
|
|
Packit |
23ab03 |
timo.tv_usec = (milli_timo%1000) * 1000;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
for (i = 0; i < n_chtab; i++) {
|
|
Packit |
23ab03 |
ch = chtab[i];
|
|
Packit |
23ab03 |
if (!ch->check)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_LISTEN:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READCHK:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ:
|
|
Packit |
23ab03 |
FD_SET (ch->fd, &rfds);
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE:
|
|
Packit |
23ab03 |
FD_SET (ch->fd, &wfds);
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
if (nfd < ch->fd+1)
|
|
Packit |
23ab03 |
nfd = ch->fd+1;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
rc = select (nfd, &rfds, &wfds, (void*)0, &timo;;
|
|
Packit |
23ab03 |
if (rc <= 0)
|
|
Packit |
23ab03 |
return rc;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
for (i = 0; i < n_chtab; i++) {
|
|
Packit |
23ab03 |
ch = chtab[i];
|
|
Packit |
23ab03 |
if (!ch->check)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_LISTEN:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READCHK:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ:
|
|
Packit |
23ab03 |
if (FD_ISSET (ch->fd, &rfds))
|
|
Packit |
23ab03 |
ch->ready = 1;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE:
|
|
Packit |
23ab03 |
if (FD_ISSET (ch->fd, &wfds))
|
|
Packit |
23ab03 |
ch->ready = 1;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return rc;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
#endif /* NDMOS_OPTION_USE_SELECT_FOR_CHAN_POLL */
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
#ifdef NDMOS_OPTION_USE_POLL_FOR_CHAN_POLL
|
|
Packit |
23ab03 |
/*
|
|
Packit |
23ab03 |
* Here because it is common, and because poll(2) is
|
|
Packit |
23ab03 |
* INFINITELY SUPERIOR to select(2).
|
|
Packit |
23ab03 |
*/
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
int
|
|
Packit |
23ab03 |
ndmos_chan_poll (struct ndmchan *chtab[], unsigned n_chtab, int milli_timo)
|
|
Packit |
23ab03 |
{
|
|
Packit |
23ab03 |
struct ndmchan * ch;
|
|
Packit |
23ab03 |
struct pollfd pfdtab[20];
|
|
Packit |
23ab03 |
int n_pfdtab = 0;
|
|
Packit |
23ab03 |
int rc, i;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
NDMOS_MACRO_ZEROFILL (pfdtab);
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
for (i = 0; i < n_chtab; i++) {
|
|
Packit |
23ab03 |
ch = chtab[i];
|
|
Packit |
23ab03 |
if (!ch->check)
|
|
Packit |
23ab03 |
continue;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
switch (ch->mode) {
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_LISTEN:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READCHK:
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_READ:
|
|
Packit |
23ab03 |
pfdtab[n_pfdtab].fd = ch->fd;
|
|
Packit |
23ab03 |
pfdtab[n_pfdtab].events = POLLIN;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
case NDMCHAN_MODE_WRITE:
|
|
Packit |
23ab03 |
pfdtab[n_pfdtab].fd = ch->fd;
|
|
Packit |
23ab03 |
pfdtab[n_pfdtab].events = POLLOUT;
|
|
Packit |
23ab03 |
break;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
n_pfdtab++;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
rc = poll (pfdtab, n_pfdtab, milli_timo);
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
@@@ TODO: post them back. Not easy @@@
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
return rc;
|
|
Packit |
23ab03 |
}
|
|
Packit |
23ab03 |
|
|
Packit |
23ab03 |
#endif /* NDMOS_OPTION_USE_POLL_FOR_CHAN_POLL */
|
|
Packit |
23ab03 |
|