version 1.13, 2009/07/25 10:52:19 |
version 1.14, 2009/09/27 11:51:20 |
|
|
unsigned val; |
unsigned val; |
int diff; |
int diff; |
|
|
#ifdef DEBUG |
|
if (o->set) { |
|
fprintf(stderr, "timo_set: already set\n"); |
|
abort(); |
|
} |
|
if (delta == 0) { |
|
fprintf(stderr, "timo_set: zero timeout is evil\n"); |
|
abort(); |
|
} |
|
#endif |
|
val = timo_abstime + delta; |
val = timo_abstime + delta; |
for (i = &timo_queue; *i != NULL; i = &(*i)->next) { |
for (i = &timo_queue; *i != NULL; i = &(*i)->next) { |
diff = (*i)->val - val; |
diff = (*i)->val - val; |
|
|
return; |
return; |
} |
} |
} |
} |
DPRINTF("timo_del: not found\n"); |
|
} |
} |
|
|
/* |
/* |
|
|
void |
void |
timo_done(void) |
timo_done(void) |
{ |
{ |
if (timo_queue != NULL) { |
|
fprintf(stderr, "timo_done: timo_queue not empty!\n"); |
|
abort(); |
|
} |
|
timo_queue = (struct timo *)0xdeadbeef; |
timo_queue = (struct timo *)0xdeadbeef; |
} |
} |
|
|
void |
|
file_dprint(int n, struct file *f) |
|
{ |
|
#ifdef DEBUG |
|
if (debug_level < n) |
|
return; |
|
fprintf(stderr, "%s:%s <", f->ops->name, f->name); |
|
if (f->state & FILE_ROK) |
|
fprintf(stderr, "ROK"); |
|
if (f->state & FILE_WOK) |
|
fprintf(stderr, "WOK"); |
|
if (f->state & FILE_EOF) |
|
fprintf(stderr, "EOF"); |
|
if (f->state & FILE_HUP) |
|
fprintf(stderr, "HUP"); |
|
fprintf(stderr, ">"); |
|
#endif |
|
} |
|
|
|
struct file * |
struct file * |
file_new(struct fileops *ops, char *name, unsigned nfds) |
file_new(struct fileops *ops, char *name, unsigned nfds) |
|
|
LIST_FOREACH(f, &file_list, entry) |
LIST_FOREACH(f, &file_list, entry) |
nfds += f->ops->nfds(f); |
nfds += f->ops->nfds(f); |
if (nfds > MAXFDS) { |
if (nfds > MAXFDS) { |
DPRINTF("file_new: %s: too many polled files\n", name); |
|
return NULL; |
return NULL; |
} |
} |
f = malloc(ops->size); |
f = malloc(ops->size); |
|
|
f->rproc = NULL; |
f->rproc = NULL; |
f->wproc = NULL; |
f->wproc = NULL; |
LIST_INSERT_HEAD(&file_list, f, entry); |
LIST_INSERT_HEAD(&file_list, f, entry); |
DPRINTF("file_new: %s:%s\n", ops->name, f->name); |
|
return f; |
return f; |
} |
} |
|
|
void |
void |
file_del(struct file *f) |
file_del(struct file *f) |
{ |
{ |
DPRINTF("file_del: "); |
|
file_dprint(1, f); |
|
if (f->state & (FILE_RINUSE | FILE_WINUSE)) { |
if (f->state & (FILE_RINUSE | FILE_WINUSE)) { |
DPRINTF(": delayed\n"); |
|
f->state |= FILE_ZOMB; |
f->state |= FILE_ZOMB; |
return; |
|
} else { |
} else { |
DPRINTF(": immediate\n"); |
|
LIST_REMOVE(f, entry); |
LIST_REMOVE(f, entry); |
f->ops->close(f); |
f->ops->close(f); |
free(f); |
free(f); |
|
|
* Fill the pfds[] array with files that are blocked on reading |
* Fill the pfds[] array with files that are blocked on reading |
* and/or writing, skipping those that are just waiting. |
* and/or writing, skipping those that are just waiting. |
*/ |
*/ |
DPRINTFN(4, "file_poll:"); |
|
nfds = 0; |
nfds = 0; |
LIST_FOREACH(f, &file_list, entry) { |
LIST_FOREACH(f, &file_list, entry) { |
events = 0; |
events = 0; |
|
|
events |= POLLIN; |
events |= POLLIN; |
if (f->wproc && !(f->state & FILE_WOK)) |
if (f->wproc && !(f->state & FILE_WOK)) |
events |= POLLOUT; |
events |= POLLOUT; |
DPRINTFN(4, " %s(%x)", f->name, events); |
|
n = f->ops->pollfd(f, pfds + nfds, events); |
n = f->ops->pollfd(f, pfds + nfds, events); |
if (n == 0) { |
if (n == 0) { |
f->pfd = NULL; |
f->pfd = NULL; |
|
|
f->pfd = pfds + nfds; |
f->pfd = pfds + nfds; |
nfds += n; |
nfds += n; |
} |
} |
DPRINTFN(4, "\n"); |
|
if (debug_level >= 4) { |
|
DPRINTF("file_poll: pfds[] ="); |
|
for (n = 0; n < nfds; n++) |
|
DPRINTF(" %x", pfds[n].events); |
|
DPRINTF("\n"); |
|
} |
|
if (LIST_EMPTY(&file_list)) { |
if (LIST_EMPTY(&file_list)) { |
DPRINTF("file_poll: nothing to do...\n"); |
|
return 0; |
return 0; |
} |
} |
if (nfds > 0) { |
if (nfds > 0) { |
|
|
if (!(f->state & FILE_ZOMB) && (revents & POLLIN)) { |
if (!(f->state & FILE_ZOMB) && (revents & POLLIN)) { |
revents &= ~POLLIN; |
revents &= ~POLLIN; |
f->state |= FILE_ROK; |
f->state |= FILE_ROK; |
DPRINTFN(3, "file_poll: %s rok\n", f->name); |
|
f->state |= FILE_RINUSE; |
f->state |= FILE_RINUSE; |
for (;;) { |
for (;;) { |
p = f->rproc; |
p = f->rproc; |
if (!p || !p->ops->in(p, NULL)) |
if (!p) |
break; |
break; |
|
if (!p->ops->in(p, NULL)) |
|
break; |
} |
} |
f->state &= ~FILE_RINUSE; |
f->state &= ~FILE_RINUSE; |
} |
} |
if (!(f->state & FILE_ZOMB) && (revents & POLLOUT)) { |
if (!(f->state & FILE_ZOMB) && (revents & POLLOUT)) { |
revents &= ~POLLOUT; |
revents &= ~POLLOUT; |
f->state |= FILE_WOK; |
f->state |= FILE_WOK; |
DPRINTFN(3, "file_poll: %s wok\n", f->name); |
|
f->state |= FILE_WINUSE; |
f->state |= FILE_WINUSE; |
for (;;) { |
for (;;) { |
p = f->wproc; |
p = f->wproc; |
if (!p || !p->ops->out(p, NULL)) |
if (!p) |
break; |
break; |
|
if (!p->ops->out(p, NULL)) |
|
break; |
} |
} |
f->state &= ~FILE_WINUSE; |
f->state &= ~FILE_WINUSE; |
} |
} |
if (!(f->state & FILE_ZOMB) && (revents & POLLHUP)) { |
if (!(f->state & FILE_ZOMB) && (revents & POLLHUP)) { |
DPRINTFN(2, "file_poll: %s: disconnected\n", f->name); |
|
f->state |= (FILE_EOF | FILE_HUP); |
f->state |= (FILE_EOF | FILE_HUP); |
} |
} |
if (!(f->state & FILE_ZOMB) && (f->state & FILE_EOF)) { |
if (!(f->state & FILE_ZOMB) && (f->state & FILE_EOF)) { |
DPRINTFN(2, "file_poll: %s: eof\n", f->name); |
|
p = f->rproc; |
p = f->rproc; |
if (p) { |
if (p) { |
f->state |= FILE_RINUSE; |
f->state |= FILE_RINUSE; |
|
|
f->state &= ~FILE_EOF; |
f->state &= ~FILE_EOF; |
} |
} |
if (!(f->state & FILE_ZOMB) && (f->state & FILE_HUP)) { |
if (!(f->state & FILE_ZOMB) && (f->state & FILE_HUP)) { |
DPRINTFN(2, "file_poll: %s hup\n", f->name); |
|
p = f->wproc; |
p = f->wproc; |
if (p) { |
if (p) { |
f->state |= FILE_WINUSE; |
f->state |= FILE_WINUSE; |
|
|
f = fnext; |
f = fnext; |
} |
} |
if (LIST_EMPTY(&file_list)) { |
if (LIST_EMPTY(&file_list)) { |
DPRINTFN(2, "file_poll: terminated\n"); |
|
return 0; |
return 0; |
} |
} |
return 1; |
return 1; |
|
|
void |
void |
filelist_done(void) |
filelist_done(void) |
{ |
{ |
struct file *f; |
|
|
|
timo_done(); |
timo_done(); |
if (!LIST_EMPTY(&file_list)) { |
|
fprintf(stderr, "filelist_done: list not empty:\n"); |
|
LIST_FOREACH(f, &file_list, entry) { |
|
fprintf(stderr, "\t"); |
|
file_dprint(0, f); |
|
fprintf(stderr, "\n"); |
|
} |
|
abort(); |
|
} |
|
} |
} |
|
|
/* |
/* |
|
|
} |
} |
|
|
unsigned |
unsigned |
file_read(struct file *file, unsigned char *data, unsigned count) |
file_read(struct file *f, unsigned char *data, unsigned count) |
{ |
{ |
return file->ops->read(file, data, count); |
unsigned n; |
|
n = f->ops->read(f, data, count); |
|
return n; |
} |
} |
|
|
unsigned |
unsigned |
file_write(struct file *file, unsigned char *data, unsigned count) |
file_write(struct file *f, unsigned char *data, unsigned count) |
{ |
{ |
return file->ops->write(file, data, count); |
unsigned n; |
|
n = f->ops->write(f, data, count); |
|
return n; |
} |
} |
|
|
void |
void |
|
|
struct aproc *p; |
struct aproc *p; |
|
|
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
DPRINTFN(2, "file_eof: %s: immediate\n", f->name); |
|
p = f->rproc; |
p = f->rproc; |
if (p) { |
if (p) { |
f->state |= FILE_RINUSE; |
f->state |= FILE_RINUSE; |
|
|
if (f->state & FILE_ZOMB) |
if (f->state & FILE_ZOMB) |
file_del(f); |
file_del(f); |
} else { |
} else { |
DPRINTFN(2, "file_eof: %s: delayed\n", f->name); |
|
f->state &= ~FILE_ROK; |
f->state &= ~FILE_ROK; |
f->state |= FILE_EOF; |
f->state |= FILE_EOF; |
} |
} |
|
|
struct aproc *p; |
struct aproc *p; |
|
|
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
DPRINTFN(2, "file_hup: %s immediate\n", f->name); |
|
p = f->wproc; |
p = f->wproc; |
if (p) { |
if (p) { |
f->state |= FILE_WINUSE; |
f->state |= FILE_WINUSE; |
|
|
if (f->state & FILE_ZOMB) |
if (f->state & FILE_ZOMB) |
file_del(f); |
file_del(f); |
} else { |
} else { |
DPRINTFN(2, "file_hup: %s: delayed\n", f->name); |
|
f->state &= ~FILE_WOK; |
f->state &= ~FILE_WOK; |
f->state |= FILE_HUP; |
f->state |= FILE_HUP; |
} |
} |
|
|
struct aproc *p; |
struct aproc *p; |
|
|
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
if (!(f->state & (FILE_RINUSE | FILE_WINUSE))) { |
DPRINTFN(2, "file_close: %s: immediate\n", f->name); |
|
p = f->rproc; |
p = f->rproc; |
if (p) { |
if (p) { |
f->state |= FILE_RINUSE; |
f->state |= FILE_RINUSE; |
|
|
if (f->state & FILE_ZOMB) |
if (f->state & FILE_ZOMB) |
file_del(f); |
file_del(f); |
} else { |
} else { |
DPRINTFN(2, "file_close: %s: delayed\n", f->name); |
|
f->state &= ~(FILE_ROK | FILE_WOK); |
f->state &= ~(FILE_ROK | FILE_WOK); |
f->state |= (FILE_EOF | FILE_HUP); |
f->state |= (FILE_EOF | FILE_HUP); |
} |
} |