version 1.14, 2009/08/21 16:48:03 |
version 1.15, 2009/09/27 11:51:20 |
|
|
#include "aproc.h" |
#include "aproc.h" |
#include "conf.h" |
#include "conf.h" |
|
|
#ifdef DEBUG |
|
void |
|
abuf_dprn(int n, struct abuf *buf, char *fmt, ...) |
|
{ |
|
va_list ap; |
|
|
|
if (debug_level < n) |
|
return; |
|
fprintf(stderr, "%s->%s: ", |
|
buf->wproc ? buf->wproc->name : "none", |
|
buf->rproc ? buf->rproc->name : "none"); |
|
va_start(ap, fmt); |
|
vfprintf(stderr, fmt, ap); |
|
va_end(ap); |
|
} |
|
#define ABUF_DPRN(n, buf, ...) abuf_dprn((n), (buf), __VA_ARGS__) |
|
#define ABUF_DPR(buf, ...) abuf_dprn(1, (buf), __VA_ARGS__) |
|
#else |
|
#define ABUF_DPRN(n, buf, ...) do {} while (0) |
|
#define ABUF_DPR(buf, ...) do {} while (0) |
|
#endif |
|
|
|
struct abuf * |
struct abuf * |
abuf_new(unsigned nfr, struct aparams *par) |
abuf_new(unsigned nfr, struct aparams *par) |
{ |
{ |
|
|
len = nfr * bpf; |
len = nfr * bpf; |
buf = malloc(sizeof(struct abuf) + len); |
buf = malloc(sizeof(struct abuf) + len); |
if (buf == NULL) { |
if (buf == NULL) { |
fprintf(stderr, "abuf_new: out of mem: %u * %u\n", nfr, bpf); |
err(1, "malloc"); |
abort(); |
|
} |
} |
buf->bpf = bpf; |
buf->bpf = bpf; |
buf->cmin = par->cmin; |
buf->cmin = par->cmin; |
|
|
{ |
{ |
if (buf->duplex) |
if (buf->duplex) |
buf->duplex->duplex = NULL; |
buf->duplex->duplex = NULL; |
#ifdef DEBUG |
|
if (buf->rproc || buf->wproc || ABUF_ROK(buf)) { |
|
/* |
|
* XXX : we should call abort(), here. |
|
* However, poll() doesn't seem to return POLLHUP, |
|
* so the reader is never destroyed; instead it appears |
|
* as blocked. Fix file_poll(), if fixable, and add |
|
* a call to abord() here. |
|
*/ |
|
#if 0 |
|
ABUF_DPRN(0, buf, "abuf_del: used = %u\n", buf->used); |
|
abort(); |
|
#endif |
|
} |
|
#endif |
|
free(buf); |
free(buf); |
} |
} |
|
|
|
|
void |
void |
abuf_clear(struct abuf *buf) |
abuf_clear(struct abuf *buf) |
{ |
{ |
ABUF_DPR(buf, "abuf_clear:\n"); |
|
buf->used = 0; |
buf->used = 0; |
buf->start = 0; |
buf->start = 0; |
buf->abspos = 0; |
buf->abspos = 0; |
|
|
used = buf->used - ofs; |
used = buf->used - ofs; |
if (start >= buf->len) |
if (start >= buf->len) |
start -= buf->len; |
start -= buf->len; |
#ifdef DEBUG |
|
if (start >= buf->len || used > buf->used) { |
|
ABUF_DPRN(0, buf, "abuf_rgetblk: " |
|
"bad ofs: start = %u used = %u/%u, ofs = %u\n", |
|
buf->start, buf->used, buf->len, ofs); |
|
abort(); |
|
} |
|
#endif |
|
count = buf->len - start; |
count = buf->len - start; |
if (count > used) |
if (count > used) |
count = used; |
count = used; |
|
|
void |
void |
abuf_rdiscard(struct abuf *buf, unsigned count) |
abuf_rdiscard(struct abuf *buf, unsigned count) |
{ |
{ |
#ifdef DEBUG |
|
if (count > buf->used) { |
|
ABUF_DPRN(0, buf, "abuf_rdiscard: bad count %u\n", count); |
|
abort(); |
|
} |
|
#endif |
|
buf->used -= count; |
buf->used -= count; |
buf->start += count; |
buf->start += count; |
if (buf->start >= buf->len) |
if (buf->start >= buf->len) |
|
|
void |
void |
abuf_wcommit(struct abuf *buf, unsigned count) |
abuf_wcommit(struct abuf *buf, unsigned count) |
{ |
{ |
#ifdef DEBUG |
|
if (count > (buf->len - buf->used)) { |
|
ABUF_DPR(buf, "abuf_wcommit: bad count\n"); |
|
abort(); |
|
} |
|
#endif |
|
buf->used += count; |
buf->used += count; |
} |
} |
|
|
|
|
end = buf->start + buf->used + ofs; |
end = buf->start + buf->used + ofs; |
if (end >= buf->len) |
if (end >= buf->len) |
end -= buf->len; |
end -= buf->len; |
#ifdef DEBUG |
|
if (end >= buf->len) { |
|
ABUF_DPR(buf, "abuf_wgetblk: %s -> %s: bad ofs, " |
|
"start = %u, used = %u, len = %u, ofs = %u\n", |
|
buf->wproc->name, buf->rproc->name, |
|
buf->start, buf->used, buf->len, ofs); |
|
abort(); |
|
} |
|
#endif |
|
avail = buf->len - (buf->used + ofs); |
avail = buf->len - (buf->used + ofs); |
count = buf->len - end; |
count = buf->len - end; |
if (count > avail) |
if (count > avail) |
|
|
if (count > buf->used) |
if (count > buf->used) |
count = buf->used; |
count = buf->used; |
if (count == 0) { |
if (count == 0) { |
ABUF_DPR(buf, "abuf_flush_do: no data to drop\n"); |
|
return 0; |
return 0; |
} |
} |
abuf_rdiscard(buf, count); |
abuf_rdiscard(buf, count); |
buf->drop -= count; |
buf->drop -= count; |
ABUF_DPR(buf, "abuf_flush_do: drop = %u\n", buf->drop); |
|
p = buf->rproc; |
|
} else { |
} else { |
ABUF_DPRN(4, buf, "abuf_flush_do: in ready\n"); |
|
p = buf->rproc; |
p = buf->rproc; |
if (!p || !p->ops->in(p, buf)) |
if (!p) |
return 0; |
return 0; |
|
if (!p->ops->in(p, buf)) |
|
return 0; |
} |
} |
return 1; |
return 1; |
} |
} |
|
|
if (count >= buf->silence) |
if (count >= buf->silence) |
count = buf->silence; |
count = buf->silence; |
if (count == 0) { |
if (count == 0) { |
ABUF_DPR(buf, "abuf_fill_do: no space for silence\n"); |
|
return 0; |
return 0; |
} |
} |
memset(data, 0, count); |
memset(data, 0, count); |
abuf_wcommit(buf, count); |
abuf_wcommit(buf, count); |
buf->silence -= count; |
buf->silence -= count; |
ABUF_DPR(buf, "abuf_fill_do: silence = %u\n", buf->silence); |
|
p = buf->wproc; |
p = buf->wproc; |
} else { |
} else { |
ABUF_DPRN(4, buf, "abuf_fill_do: out avail\n"); |
|
p = buf->wproc; |
p = buf->wproc; |
if (p == NULL || !p->ops->out(p, buf)) { |
if (!p) |
return 0; |
return 0; |
|
if (!p->ops->out(p, buf)) { |
|
return 0; |
} |
} |
} |
} |
return 1; |
return 1; |
|
|
|
|
p = buf->rproc; |
p = buf->rproc; |
if (p) { |
if (p) { |
ABUF_DPRN(2, buf, "abuf_eof_do: signaling reader\n"); |
|
buf->rproc = NULL; |
buf->rproc = NULL; |
LIST_REMOVE(buf, ient); |
LIST_REMOVE(buf, ient); |
buf->inuse++; |
buf->inuse++; |
p->ops->eof(p, buf); |
p->ops->eof(p, buf); |
buf->inuse--; |
buf->inuse--; |
} else |
} |
ABUF_DPR(buf, "abuf_eof_do: no reader, freeng buf\n"); |
|
abuf_del(buf); |
abuf_del(buf); |
} |
} |
|
|
|
|
struct aproc *p; |
struct aproc *p; |
|
|
if (ABUF_ROK(buf)) { |
if (ABUF_ROK(buf)) { |
ABUF_DPR(buf, "abuf_hup_do: lost %u bytes\n", buf->used); |
|
buf->used = 0; |
buf->used = 0; |
} |
} |
p = buf->wproc; |
p = buf->wproc; |
if (p != NULL) { |
if (p != NULL) { |
ABUF_DPRN(2, buf, "abuf_hup_do: signaling writer\n"); |
|
buf->wproc = NULL; |
buf->wproc = NULL; |
LIST_REMOVE(buf, oent); |
LIST_REMOVE(buf, oent); |
buf->inuse++; |
buf->inuse++; |
p->ops->hup(p, buf); |
p->ops->hup(p, buf); |
buf->inuse--; |
buf->inuse--; |
} else |
} |
ABUF_DPR(buf, "abuf_hup_do: no writer, freeng buf\n"); |
|
abuf_del(buf); |
abuf_del(buf); |
} |
} |
|
|
|
|
abuf_flush(struct abuf *buf) |
abuf_flush(struct abuf *buf) |
{ |
{ |
if (buf->inuse) { |
if (buf->inuse) { |
ABUF_DPRN(4, buf, "abuf_flush: blocked\n"); |
|
} else { |
} else { |
buf->inuse++; |
buf->inuse++; |
for (;;) { |
for (;;) { |
|
|
abuf_fill(struct abuf *buf) |
abuf_fill(struct abuf *buf) |
{ |
{ |
if (buf->inuse) { |
if (buf->inuse) { |
ABUF_DPRN(4, buf, "abuf_fill: blocked\n"); |
|
} else { |
} else { |
buf->inuse++; |
buf->inuse++; |
for (;;) { |
for (;;) { |
|
|
int canfill = 1, canflush = 1; |
int canfill = 1, canflush = 1; |
|
|
if (buf->inuse) { |
if (buf->inuse) { |
ABUF_DPRN(4, buf, "abuf_run: blocked\n"); |
|
return; |
return; |
} |
} |
buf->inuse++; |
buf->inuse++; |
|
|
void |
void |
abuf_eof(struct abuf *buf) |
abuf_eof(struct abuf *buf) |
{ |
{ |
#ifdef DEBUG |
|
if (buf->wproc == NULL) { |
|
ABUF_DPR(buf, "abuf_eof: no writer\n"); |
|
abort(); |
|
} |
|
#endif |
|
ABUF_DPRN(2, buf, "abuf_eof: requested\n"); |
|
LIST_REMOVE(buf, oent); |
LIST_REMOVE(buf, oent); |
buf->wproc = NULL; |
buf->wproc = NULL; |
if (buf->rproc != NULL) { |
if (buf->rproc != NULL) { |
|
|
* Could not flush everything, the reader will |
* Could not flush everything, the reader will |
* have a chance to delete the abuf later. |
* have a chance to delete the abuf later. |
*/ |
*/ |
ABUF_DPRN(2, buf, "abuf_eof: will drain later\n"); |
|
return; |
return; |
} |
} |
} |
} |
if (buf->inuse) { |
if (buf->inuse) { |
ABUF_DPRN(2, buf, "abuf_eof: signal blocked\n"); |
|
return; |
return; |
} |
} |
abuf_eof_do(buf); |
abuf_eof_do(buf); |
|
|
void |
void |
abuf_hup(struct abuf *buf) |
abuf_hup(struct abuf *buf) |
{ |
{ |
#ifdef DEBUG |
|
if (buf->rproc == NULL) { |
|
ABUF_DPR(buf, "abuf_hup: no reader\n"); |
|
abort(); |
|
} |
|
#endif |
|
ABUF_DPRN(2, buf, "abuf_hup: initiated\n"); |
|
|
|
buf->rproc = NULL; |
buf->rproc = NULL; |
LIST_REMOVE(buf, ient); |
LIST_REMOVE(buf, ient); |
if (buf->wproc != NULL) { |
if (buf->wproc != NULL) { |
if (buf->inuse) { |
if (buf->inuse) { |
ABUF_DPRN(2, buf, "abuf_hup: signal blocked\n"); |
|
return; |
return; |
} |
} |
} |
} |