#include <u.h>#include <libc.h>#include <thread.h>#include "dat.h"#include "fns.h" Dev *devs; voiddevwork(void *v){ Dev *d; Buf *b; Channel *r; uchar buf[BLOCK]; d = v; for(;;){ qlock(&d->workl); while(d->work.wnext == &d->work) rsleep(&d->workr); b = d->work.wnext; b->wnext->wprev = b->wprev; b->wprev->wnext = b->wnext; b->wnext = b->wprev = nil; qunlock(&d->workl); if(b->d == nil) /* this is a sync request */ goto reply; if(b->off >= d->size){ b->error = Einval; goto reply; } b->error = nil; if(b->op & BWRITE){ memset(buf, 0, sizeof(buf)); pack(b, buf); if(pwrite(d->fd, buf, BLOCK, b->off*BLOCK) < BLOCK){ dprint("write: %r\n"); b->error = Eio; } }else{ int n, m; for(n = 0; n < BLOCK; n += m){ m = pread(d->fd, buf+n, BLOCK-n, b->off*BLOCK+n); if(m < 0) dprint("read: %r\n"); if(m <= 0) break; } if(n < BLOCK) b->error = Eio; else unpack(b, buf); } reply: r = b->resp; b->resp = nil; if(r != nil) send(r, &b); }} Dev *newdev(char *file){ Dev *d, **e; Dir *dir; Buf *b; d = emalloc(sizeof(*d)); d->fd = open(file, ORDWR); if(d->fd < 0){ free(d); return nil; } dir = dirfstat(d->fd); if(dir == nil){ error: close(d->fd); free(d); return nil; } d->size = dir->length / BLOCK; free(dir); if(d->size == 0){ werrstr("device file too short"); goto error; } d->name = estrdup(file); for(b = d->buf; b < d->buf + BUFHASH + 1; b++) b->dnext = b->dprev = b; d->workr.l = &d->workl; d->work.wnext = d->work.wprev = &d->work; proccreate(devwork, d, mainstacksize); for(e = &devs; *e != nil; e = &(*e)->next) ; *e = d; return d;}
#include <u.h>
#include <libc.h>
#include <thread.h>
#include "dat.h"
#include "fns.h"
Dev *devs;
void
devwork(void *v)
{
Dev *d;
Buf *b;
Channel *r;
uchar buf[BLOCK];
d = v;
for(;;){
qlock(&d->workl);
while(d->work.wnext == &d->work)
rsleep(&d->workr);
b = d->work.wnext;
b->wnext->wprev = b->wprev;
b->wprev->wnext = b->wnext;
b->wnext = b->wprev = nil;
qunlock(&d->workl);
if(b->d == nil) /* this is a sync request */
goto reply;
if(b->off >= d->size){
b->error = Einval;
goto reply;
}
b->error = nil;
if(b->op & BWRITE){
memset(buf, 0, sizeof(buf));
pack(b, buf);
if(pwrite(d->fd, buf, BLOCK, b->off*BLOCK) < BLOCK){
dprint("write: %r\n");
b->error = Eio;
}
}else{
int n, m;
for(n = 0; n < BLOCK; n += m){
m = pread(d->fd, buf+n, BLOCK-n, b->off*BLOCK+n);
if(m < 0)
dprint("read: %r\n");
if(m <= 0)
break;
}
if(n < BLOCK)
b->error = Eio;
else
unpack(b, buf);
}
reply:
r = b->resp;
b->resp = nil;
if(r != nil)
send(r, &b);
}
}
Dev *
newdev(char *file)
{
Dev *d, **e;
Dir *dir;
Buf *b;
d = emalloc(sizeof(*d));
d->fd = open(file, ORDWR);
if(d->fd < 0){
free(d);
return nil;
}
dir = dirfstat(d->fd);
if(dir == nil){
error:
close(d->fd);
free(d);
return nil;
}
d->size = dir->length / BLOCK;
free(dir);
if(d->size == 0){
werrstr("device file too short");
goto error;
}
d->name = estrdup(file);
for(b = d->buf; b < d->buf + BUFHASH + 1; b++)
b->dnext = b->dprev = b;
d->workr.l = &d->workl;
d->work.wnext = d->work.wprev = &d->work;
proccreate(devwork, d, mainstacksize);
for(e = &devs; *e != nil; e = &(*e)->next)
;
*e = d;
return d;
}