1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
|
#include "tra.h"
struct Fdmsg
{
void *a;
int n;
Fdmsg *next;
};
void
_fdbufwatch(Fdbuf *b)
{
Fdmsg *m;
void *a;
int n;
Thread *t;
a = emalloc(IOCHUNK);
while((n = read(b->fd, a, IOCHUNK)) > 0){
m = emalloc(sizeof(Fdmsg)+n);
m->a = &m[1];
m->n = n;
memmove(m->a, a, n);
lock(&b->lk);
if(b->m == nil)
b->em = &b->m;
*b->em = m;
b->em = &m->next;
t = b->t;
b->t = nil;
unlock(&b->lk);
if(t)
threadready(t);
}
lock(&b->lk);
t = b->t;
b->dead = 1;
unlock(&b->lk);
if(t)
threadready(t);
}
void
closefdbuf(Fdbuf *b)
{
Fdmsg *m, *mnext;
lock(&b->lk);
while(!b->dead){
b->t = curthread;
unlock(&b->lk);
close(b->fd);
threadsleep();
lock(&b->lk);
}
for(m=b->m; m; m=mnext){
mnext = m->next;
free(m);
}
b->m = nil;
free(b);
}
int
readfdbuf(Fdbuf *b, void *a, int n)
{
Fdmsg *m;
lock(&b->lk);
while(b->m == nil){
if(b->dead){
unlock(&b->lk);
werrstr("connection closed");
return -1;
}
b->t = curthread;
unlock(&b->lk);
threadsleep();
lock(&b->lk);
}
m = b->m;
if(n > m->n)
n = m->n;
memmove(a, m->a, n);
m->a = (uchar*)m->a + n;
m->n -= n;
if(m->n == 0){
b->m = m->next;
free(m);
}
unlock(&b->lk);
return n;
}
int
readnfdbuf(Fdbuf *b, void *a, int n)
{
int m;
uchar *p;
p = a;
while(n > 0){
m = readfdbuf(b, p, n);
if(m <= 0){
if(p==a)
return m;
break;
}
p += m;
n -= m;
}
if(n != 0)
abort();
return p-(uchar*)a;
}
|