Unified · Split
| @@ -5,7 +5,6 @@ LIB=libkern.a · 4 unmodified lines | |||
| 5 | OFILES=\ | 5 | OFILES=\ |
| 6 | alloc.$O\ | 6 | alloc.$O\ |
| 7 | allocb.$O\ | 7 | allocb.$O\ |
| 8 | cache.$O\ | ||
| 9 | chan.$O\ | 8 | chan.$O\ |
| 10 | data.$O\ | 9 | data.$O\ |
| 11 | dev.$O\ | 10 | dev.$O\ |
| @@ -7,27 +7,23 @@ · 6 unmodified lines | |||
| 7 | enum | 7 | enum |
| 8 | { | 8 | { |
| 9 | Hdrspc = 64, /* leave room for high-level headers */ | 9 | Hdrspc = 64, /* leave room for high-level headers */ |
| 10 | Tlrspc = 16, /* extra room at the end for pad/crc/mac */ | ||
| 10 | Bdead = 0x51494F42, /* "QIOB" */ | 11 | Bdead = 0x51494F42, /* "QIOB" */ |
| 11 | }; | 12 | }; |
| 12 | 13 | ||
| 13 | struct | ||
| 14 | { | ||
| 15 | Lock lk; | ||
| 16 | ulong bytes; | ||
| 17 | } ialloc; | ||
| 18 | |||
| 19 | static Block* | 14 | static Block* |
| 20 | _allocb(int size) | 15 | _allocb(int size) |
| 21 | { | 16 | { |
| 22 | Block *b; | 17 | Block *b; |
| 23 | uintptr addr; | 18 | uintptr addr; |
| 24 | 19 | ||
| 20 | size += Tlrspc; | ||
| 25 | if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil) | 21 | if((b = mallocz(sizeof(Block)+size+Hdrspc, 0)) == nil) |
| 26 | return nil; | 22 | return nil; |
| 27 | 23 | ||
| 28 | b->next = nil; | 24 | b->next = nil; |
| 29 | b->list = nil; | 25 | b->list = nil; |
| 30 | b->free = 0; | 26 | b->free = nil; |
| 31 | b->flag = 0; | 27 | b->flag = 0; |
| 32 | 28 | ||
| 33 | /* align start of data portion by rounding up */ | 29 | /* align start of data portion by rounding up */ |
| @@ -36,9 +32,9 @@ _allocb(int size) · 2 unmodified lines | |||
| 36 | b->base = (uchar*)addr; | 32 | b->base = (uchar*)addr; |
| 37 | 33 | ||
| 38 | /* align end of data portion by rounding down */ | 34 | /* align end of data portion by rounding down */ |
| 39 | b->lim = ((uchar*)b) + sizeof(Block)+size+Hdrspc; | 35 | b->lim = (uchar*)b + sizeof(Block)+size+Hdrspc; |
| 40 | addr = (uintptr)(b->lim); | 36 | addr = (uintptr)b->lim; |
| 41 | addr = addr & ~(BLOCKALIGN-1); | 37 | addr &= ~(BLOCKALIGN-1); |
| 42 | b->lim = (uchar*)addr; | 38 | b->lim = (uchar*)addr; |
| 43 | 39 | ||
| 44 | /* leave sluff at beginning for added headers */ | 40 | /* leave sluff at beginning for added headers */ |
| @@ -57,13 +53,11 @@ allocb(int size) · 12 unmodified lines | |||
| 57 | 53 | ||
| 58 | /* | 54 | /* |
| 59 | * Check in a process and wait until successful. | 55 | * Check in a process and wait until successful. |
| 60 | * Can still error out of here, though. | ||
| 61 | */ | 56 | */ |
| 62 | if(up == nil) | 57 | if(up == nil) |
| 63 | panic("allocb without up: %p\n", getcallerpc(&size)); | 58 | panic("allocb without up: %#p", getcallerpc(&size)); |
| 64 | if((b = _allocb(size)) == nil){ | 59 | if((b = _allocb(size)) == nil) |
| 65 | panic("allocb: no memory for %d bytes\n", size); | 60 | panic("allocb: no memory for %d bytes", size); |
| 66 | } | ||
| 67 | setmalloctag(b, getcallerpc(&size)); | 61 | setmalloctag(b, getcallerpc(&size)); |
| 68 | 62 | ||
| 69 | return b; | 63 | return b; |
| @@ -73,28 +67,12 @@ Block* · 3 unmodified lines | |||
| 73 | iallocb(int size) | 67 | iallocb(int size) |
| 74 | { | 68 | { |
| 75 | Block *b; | 69 | Block *b; |
| 76 | static int m1, m2; | ||
| 77 | 70 | ||
| 78 | if(ialloc.bytes > conf.ialloc){ | 71 | if((b = _allocb(size)) == nil) |
| 79 | if((m1++%10000)==0) | 72 | panic("iallocb: no memory for %d bytes", size); |
| 80 | print("iallocb: limited %lud/%lud\n", | ||
| 81 | ialloc.bytes, conf.ialloc); | ||
| 82 | return 0; | ||
| 83 | } | ||
| 84 | |||
| 85 | if((b = _allocb(size)) == nil){ | ||
| 86 | if((m2++%10000)==0) | ||
| 87 | print("iallocb: no memory %lud/%lud\n", | ||
| 88 | ialloc.bytes, conf.ialloc); | ||
| 89 | return nil; | ||
| 90 | } | ||
| 91 | setmalloctag(b, getcallerpc(&size)); | 73 | setmalloctag(b, getcallerpc(&size)); |
| 92 | b->flag = BINTR; | 74 | b->flag = BINTR; |
| 93 | 75 | ||
| 94 | ilock(&ialloc.lk); | ||
| 95 | ialloc.bytes += b->lim - b->base; | ||
| 96 | iunlock(&ialloc.lk); | ||
| 97 | |||
| 98 | return b; | 76 | return b; |
| 99 | } | 77 | } |
| 100 | 78 | ||
| @@ -110,15 +88,10 @@ freeb(Block *b) · 9 unmodified lines | |||
| 110 | * drivers which perform non cache coherent DMA manage their own buffer | 88 | * drivers which perform non cache coherent DMA manage their own buffer |
| 111 | * pool of uncached buffers and provide their own free routine. | 89 | * pool of uncached buffers and provide their own free routine. |
| 112 | */ | 90 | */ |
| 113 | if(b->free) { | 91 | if(b->free != nil) { |
| 114 | b->free(b); | 92 | b->free(b); |
| 115 | return; | 93 | return; |
| 116 | } | 94 | } |
| 117 | if(b->flag & BINTR) { | ||
| 118 | ilock(&ialloc.lk); | ||
| 119 | ialloc.bytes -= b->lim - b->base; | ||
| 120 | iunlock(&ialloc.lk); | ||
| 121 | } | ||
| 122 | 95 | ||
| 123 | /* poison the block in case someone is still holding onto it */ | 96 | /* poison the block in case someone is still holding onto it */ |
| 124 | b->next = dead; | 97 | b->next = dead; |
| @@ -136,30 +109,23 @@ checkb(Block *b, char *msg) · 11 unmodified lines | |||
| 136 | void *dead = (void*)Bdead; | 109 | void *dead = (void*)Bdead; |
| 137 | 110 | ||
| 138 | if(b == dead) | 111 | if(b == dead) |
| 139 | panic("checkb b %s %lux", msg, b); | 112 | panic("checkb b %s %#p", msg, b); |
| 140 | if(b->base == dead || b->lim == dead || b->next == dead | 113 | if(b->base == dead || b->lim == dead || b->next == dead |
| 141 | || b->rp == dead || b->wp == dead){ | 114 | || b->rp == dead || b->wp == dead){ |
| 142 | print("checkb: base 0x%8.8luX lim 0x%8.8luX next 0x%8.8luX\n", | 115 | print("checkb: base %#p lim %#p next %#p\n", |
| 143 | b->base, b->lim, b->next); | 116 | b->base, b->lim, b->next); |
| 144 | print("checkb: rp 0x%8.8luX wp 0x%8.8luX\n", b->rp, b->wp); | 117 | print("checkb: rp %#p wp %#p\n", b->rp, b->wp); |
| 145 | panic("checkb dead: %s\n", msg); | 118 | panic("checkb dead: %s", msg); |
| 146 | } | 119 | } |
| 147 | 120 | ||
| 148 | if(b->base > b->lim) | 121 | if(b->base > b->lim) |
| 149 | panic("checkb 0 %s %lux %lux", msg, b->base, b->lim); | 122 | panic("checkb 0 %s %#p %#p", msg, b->base, b->lim); |
| 150 | if(b->rp < b->base) | 123 | if(b->rp < b->base) |
| 151 | panic("checkb 1 %s %lux %lux", msg, b->base, b->rp); | 124 | panic("checkb 1 %s %#p %#p", msg, b->base, b->rp); |
| 152 | if(b->wp < b->base) | 125 | if(b->wp < b->base) |
| 153 | panic("checkb 2 %s %lux %lux", msg, b->base, b->wp); | 126 | panic("checkb 2 %s %#p %#p", msg, b->base, b->wp); |
| 154 | if(b->rp > b->lim) | 127 | if(b->rp > b->lim) |
| 155 | panic("checkb 3 %s %lux %lux", msg, b->rp, b->lim); | 128 | panic("checkb 3 %s %#p %#p", msg, b->rp, b->lim); |
| 156 | if(b->wp > b->lim) | 129 | if(b->wp > b->lim) |
| 157 | panic("checkb 4 %s %lux %lux", msg, b->wp, b->lim); | 130 | panic("checkb 4 %s %#p %#p", msg, b->wp, b->lim); |
| 158 | |||
| 159 | } | ||
| 160 | |||
| 161 | void | ||
| 162 | iallocsummary(void) | ||
| 163 | { | ||
| 164 | print("ialloc %lud/%lud\n", ialloc.bytes, conf.ialloc); | ||
| 165 | } | 131 | } |
| @@ -1,46 +0,0 @@ | |||
| 1 | #include "u.h" | ||
| 2 | #include "lib.h" | ||
| 3 | #include "dat.h" | ||
| 4 | #include "fns.h" | ||
| 5 | #include "error.h" | ||
| 6 | |||
| 7 | |||
| 8 | void | ||
| 9 | cinit(void) | ||
| 10 | { | ||
| 11 | } | ||
| 12 | |||
| 13 | void | ||
| 14 | copen(Chan *c) | ||
| 15 | { | ||
| 16 | USED(c); | ||
| 17 | } | ||
| 18 | |||
| 19 | int | ||
| 20 | cread(Chan *c, uchar *buf, int len, vlong off) | ||
| 21 | { | ||
| 22 | USED(c); | ||
| 23 | USED(buf); | ||
| 24 | USED(len); | ||
| 25 | USED(off); | ||
| 26 | |||
| 27 | return 0; | ||
| 28 | } | ||
| 29 | |||
| 30 | void | ||
| 31 | cupdate(Chan *c, uchar *buf, int len, vlong off) | ||
| 32 | { | ||
| 33 | USED(c); | ||
| 34 | USED(buf); | ||
| 35 | USED(len); | ||
| 36 | USED(off); | ||
| 37 | } | ||
| 38 | |||
| 39 | void | ||
| 40 | cwrite(Chan* c, uchar *buf, int len, vlong off) | ||
| 41 | { | ||
| 42 | USED(c); | ||
| 43 | USED(buf); | ||
| 44 | USED(len); | ||
| 45 | USED(off); | ||
| 46 | } | ||
| @@ -24,15 +24,10 @@ struct Mntrpc · 23 unmodified lines | |||
| 24 | Fcall request; /* Outgoing file system protocol message */ | 24 | Fcall request; /* Outgoing file system protocol message */ |
| 25 | Fcall reply; /* Incoming reply */ | 25 | Fcall reply; /* Incoming reply */ |
| 26 | Mnt* m; /* Mount device during rpc */ | 26 | Mnt* m; /* Mount device during rpc */ |
| 27 | Rendez r; /* Place to hang out */ | 27 | Rendez* z; /* Place to hang out */ |
| 28 | uchar* rpc; /* I/O Data buffer */ | 28 | Block* b; /* reply blocks */ |
| 29 | uint rpclen; /* len of buffer */ | ||
| 30 | Block *b; /* reply blocks */ | ||
| 31 | char done; /* Rpc completed */ | ||
| 32 | uvlong stime; /* start time for mnt statistics */ | ||
| 33 | ulong reqlen; /* request length for mnt statistics */ | ||
| 34 | ulong replen; /* reply length for mnt statistics */ | ||
| 35 | Mntrpc* flushed; /* message this one flushes */ | 29 | Mntrpc* flushed; /* message this one flushes */ |
| 30 | char done; /* Rpc completed */ | ||
| 36 | }; | 31 | }; |
| 37 | 32 | ||
| 38 | enum | 33 | enum |
| @@ -42,42 +37,38 @@ enum · 3 unmodified lines | |||
| 42 | NMASK = (64*1024)>>TAGSHIFT, | 37 | NMASK = (64*1024)>>TAGSHIFT, |
| 43 | }; | 38 | }; |
| 44 | 39 | ||
| 45 | struct Mntalloc | 40 | static struct Mntalloc |
| 46 | { | 41 | { |
| 47 | Lock lk; | 42 | Lock lk; |
| 48 | Mnt* list; /* Mount devices in use */ | 43 | Mnt* list; /* Mount devices in use */ |
| 49 | Mnt* mntfree; /* Free list */ | 44 | Mnt* mntfree; /* Free list */ |
| 50 | Mntrpc* rpcfree; | 45 | Mntrpc* rpcfree; |
| 51 | int nrpcfree; | 46 | ulong nrpcfree; |
| 52 | int nrpcused; | 47 | ulong nrpcused; |
| 53 | ulong id; | 48 | ulong id; |
| 54 | ulong tagmask[NMASK]; | 49 | ulong tagmask[NMASK]; |
| 55 | }mntalloc; | 50 | } mntalloc; |
| 56 | 51 | ||
| 57 | void mattach(Mnt*, Chan*, char*); | 52 | static Chan* mntchan(void); |
| 58 | Mnt* mntchk(Chan*); | 53 | static Mnt* mntchk(Chan*); |
| 59 | void mntdirfix(uchar*, Chan*); | 54 | static void mntdirfix(uchar*, Chan*); |
| 60 | Mntrpc* mntflushalloc(Mntrpc*, ulong); | 55 | static Mntrpc* mntflushalloc(Mntrpc*); |
| 61 | void mntflushfree(Mnt*, Mntrpc*); | 56 | static Mntrpc* mntflushfree(Mnt*, Mntrpc*); |
| 62 | void mntfree(Mntrpc*); | 57 | static void mntfree(Mntrpc*); |
| 63 | void mntgate(Mnt*); | 58 | static void mntgate(Mnt*); |
| 64 | void mntpntfree(Mnt*); | 59 | static void mntqrm(Mnt*, Mntrpc*); |
| 65 | void mntqrm(Mnt*, Mntrpc*); | 60 | static Mntrpc* mntralloc(Chan*); |
| 66 | Mntrpc* mntralloc(Chan*, ulong); | 61 | static long mntrdwr(int, Chan*, void*, long, vlong); |
| 67 | long mntrdwr(int, Chan*, void*, long, vlong); | 62 | static int mntrpcread(Mnt*, Mntrpc*); |
| 68 | int mntrpcread(Mnt*, Mntrpc*); | 63 | static void mountio(Mnt*, Mntrpc*); |
| 69 | void mountio(Mnt*, Mntrpc*); | 64 | static void mountmux(Mnt*, Mntrpc*); |
| 70 | void mountmux(Mnt*, Mntrpc*); | 65 | static void mountrpc(Mnt*, Mntrpc*); |
| 71 | void mountrpc(Mnt*, Mntrpc*); | 66 | static int rpcattn(void*); |
| 72 | int rpcattn(void*); | ||
| 73 | Chan* mntchan(void); | ||
| 74 | 67 | ||
| 75 | char Esbadstat[] = "invalid directory entry received from server"; | 68 | char Esbadstat[] = "invalid directory entry received from server"; |
| 76 | char Enoversion[] = "version not established for mount channel"; | 69 | char Enoversion[] = "version not established for mount channel"; |
| 77 | 70 | ||
| 78 | 71 | ||
| 79 | void (*mntstats)(int, Chan*, uvlong, ulong); | ||
| 80 | |||
| 81 | static void | 72 | static void |
| 82 | mntreset(void) | 73 | mntreset(void) |
| 83 | { | 74 | { |
| @@ -87,20 +78,19 @@ mntreset(void) · 3 unmodified lines | |||
| 87 | fmtinstall('F', fcallfmt); | 78 | fmtinstall('F', fcallfmt); |
| 88 | fmtinstall('D', dirfmt); | 79 | fmtinstall('D', dirfmt); |
| 89 | /* We can't install %M since eipfmt does and is used in the kernel [sape] */ | 80 | /* We can't install %M since eipfmt does and is used in the kernel [sape] */ |
| 90 | |||
| 91 | cinit(); | ||
| 92 | } | 81 | } |
| 93 | 82 | ||
| 94 | /* | 83 | /* |
| 95 | * Version is not multiplexed: message sent only once per connection. | 84 | * Version is not multiplexed: message sent only once per connection. |
| 96 | */ | 85 | */ |
| 97 | long | 86 | int |
| 98 | mntversion(Chan *c, char *version, int msize, int returnlen) | 87 | mntversion(Chan *c, char *version, int msize, int returnlen) |
| 99 | { | 88 | { |
| 100 | Fcall f; | 89 | Fcall f; |
| 101 | uchar *msg; | 90 | uchar *msg; |
| 102 | Mnt *m; | 91 | Mnt *m; |
| 103 | char *v; | 92 | char *v; |
| 93 | Queue *q; | ||
| 104 | long k, l; | 94 | long k, l; |
| 105 | uvlong oo; | 95 | uvlong oo; |
| 106 | char buf[128]; | 96 | char buf[128]; |
| @@ -167,7 +157,6 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 60 unmodified lines | |||
| 167 | unlock(&c->ref.lk); | 157 | unlock(&c->ref.lk); |
| 168 | 158 | ||
| 169 | l = devtab[c->type]->write(c, msg, k, oo); | 159 | l = devtab[c->type]->write(c, msg, k, oo); |
| 170 | |||
| 171 | if(l < k){ | 160 | if(l < k){ |
| 172 | lock(&c->ref.lk); | 161 | lock(&c->ref.lk); |
| 173 | c->offset -= k - l; | 162 | c->offset -= k - l; |
| @@ -176,13 +165,14 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 2 unmodified lines | |||
| 176 | } | 165 | } |
| 177 | 166 | ||
| 178 | /* message sent; receive and decode reply */ | 167 | /* message sent; receive and decode reply */ |
| 179 | k = devtab[c->type]->read(c, msg, 8192+IOHDRSZ, c->offset); | 168 | for(k = 0; k < BIT32SZ || (k < GBIT32(msg) && k < 8192+IOHDRSZ); k += l){ |
| 180 | if(k <= 0) | 169 | l = devtab[c->type]->read(c, msg+k, 8192+IOHDRSZ-k, c->offset); |
| 181 | error("EOF receiving fversion reply"); | 170 | if(l <= 0) |
| 182 | 171 | error("EOF receiving fversion reply"); | |
| 183 | lock(&c->ref.lk); | 172 | lock(&c->ref.lk); |
| 184 | c->offset += k; | 173 | c->offset += l; |
| 185 | unlock(&c->ref.lk); | 174 | unlock(&c->ref.lk); |
| 175 | } | ||
| 186 | 176 | ||
| 187 | l = convM2S(msg, k, &f); | 177 | l = convM2S(msg, k, &f); |
| 188 | if(l != k) | 178 | if(l != k) |
| @@ -199,40 +189,49 @@ mntversion(Chan *c, char *version, int msize, int returnlen) · 10 unmodified lines | |||
| 199 | k = strlen(f.version); | 189 | k = strlen(f.version); |
| 200 | if(strncmp(f.version, v, k) != 0) | 190 | if(strncmp(f.version, v, k) != 0) |
| 201 | error("bad 9P version returned from server"); | 191 | error("bad 9P version returned from server"); |
| 192 | if(returnlen > 0 && returnlen < k) | ||
| 193 | error(Eshort); | ||
| 194 | |||
| 195 | v = nil; | ||
| 196 | kstrdup(&v, f.version); | ||
| 197 | q = qopen(10*MAXRPC, 0, nil, nil); | ||
| 198 | if(q == nil){ | ||
| 199 | free(v); | ||
| 200 | exhausted("mount queues"); | ||
| 201 | } | ||
| 202 | 202 | ||
| 203 | /* now build Mnt associated with this connection */ | 203 | /* now build Mnt associated with this connection */ |
| 204 | lock(&mntalloc.lk); | 204 | lock(&mntalloc.lk); |
| 205 | m = mntalloc.mntfree; | 205 | m = mntalloc.mntfree; |
| 206 | if(m != 0) | 206 | if(m != nil) |
| 207 | mntalloc.mntfree = m->list; | 207 | mntalloc.mntfree = m->list; |
| 208 | else { | 208 | else { |
| 209 | unlock(&mntalloc.lk); | ||
| 209 | m = malloc(sizeof(Mnt)); | 210 | m = malloc(sizeof(Mnt)); |
| 210 | if(m == 0) { | 211 | if(m == nil) { |
| 211 | unlock(&mntalloc.lk); | 212 | qfree(q); |
| 213 | free(v); | ||
| 212 | exhausted("mount devices"); | 214 | exhausted("mount devices"); |
| 213 | } | 215 | } |
| 216 | lock(&mntalloc.lk); | ||
| 214 | } | 217 | } |
| 215 | m->list = mntalloc.list; | 218 | m->list = mntalloc.list; |
| 216 | mntalloc.list = m; | 219 | mntalloc.list = m; |
| 217 | m->version = nil; | 220 | m->version = v; |
| 218 | kstrdup(&m->version, f.version); | ||
| 219 | m->id = mntalloc.id++; | 221 | m->id = mntalloc.id++; |
| 220 | m->q = qopen(10*MAXRPC, 0, 0, nil); | 222 | m->q = q; |
| 221 | m->msize = f.msize; | 223 | m->msize = f.msize; |
| 222 | unlock(&mntalloc.lk); | 224 | unlock(&mntalloc.lk); |
| 223 | 225 | ||
| 224 | if(returnlen > 0){ | 226 | if(returnlen > 0) |
| 225 | if(returnlen < k) | 227 | memmove(version, f.version, k); /* length was checked above */ |
| 226 | error(Eshort); | ||
| 227 | memmove(version, f.version, k); | ||
| 228 | } | ||
| 229 | 228 | ||
| 230 | poperror(); /* msg */ | 229 | poperror(); /* msg */ |
| 231 | free(msg); | 230 | free(msg); |
| 232 | 231 | ||
| 233 | lock(&m->lk); | 232 | lock(&m->lk); |
| 234 | m->queue = 0; | 233 | m->queue = nil; |
| 235 | m->rip = 0; | 234 | m->rip = nil; |
| 236 | 235 | ||
| 237 | c->flag |= CMSG; | 236 | c->flag |= CMSG; |
| 238 | c->mux = m; | 237 | c->mux = m; |
| @@ -252,9 +251,8 @@ mntauth(Chan *c, char *spec) · 13 unmodified lines | |||
| 252 | Mntrpc *r; | 251 | Mntrpc *r; |
| 253 | 252 | ||
| 254 | m = c->mux; | 253 | m = c->mux; |
| 255 | |||
| 256 | if(m == nil){ | 254 | if(m == nil){ |
| 257 | mntversion(c, VERSION9P, MAXRPC, 0); | 255 | mntversion(c, nil, 0, 0); |
| 258 | m = c->mux; | 256 | m = c->mux; |
| 259 | if(m == nil) | 257 | if(m == nil) |
| 260 | error(Enoversion); | 258 | error(Enoversion); |
| @@ -269,8 +267,7 @@ mntauth(Chan *c, char *spec) · 8 unmodified lines | |||
| 269 | nexterror(); | 267 | nexterror(); |
| 270 | } | 268 | } |
| 271 | 269 | ||
| 272 | r = mntralloc(0, m->msize); | 270 | r = mntralloc(c); |
| 273 | |||
| 274 | if(waserror()) { | 271 | if(waserror()) { |
| 275 | mntfree(r); | 272 | mntfree(r); |
| 276 | nexterror(); | 273 | nexterror(); |
| @@ -287,6 +284,7 @@ mntauth(Chan *c, char *spec) · 10 unmodified lines | |||
| 287 | incref(&m->c->ref); | 284 | incref(&m->c->ref); |
| 288 | c->mqid = c->qid; | 285 | c->mqid = c->qid; |
| 289 | c->mode = ORDWR; | 286 | c->mode = ORDWR; |
| 287 | c->iounit = m->msize-IOHDRSZ; | ||
| 290 | 288 | ||
| 291 | poperror(); /* r */ | 289 | poperror(); /* r */ |
| 292 | mntfree(r); | 290 | mntfree(r); |
| @@ -297,24 +295,13 @@ mntauth(Chan *c, char *spec) · 4 unmodified lines | |||
| 297 | 295 | ||
| 298 | } | 296 | } |
| 299 | 297 | ||
| 300 | static Chan* | 298 | Chan* |
| 301 | mntattach(char *muxattach) | 299 | mntattach(Chan *c, Chan *ac, char *spec, int flags) |
| 302 | { | 300 | { |
| 303 | Mnt *m; | 301 | Mnt *m; |
| 304 | Chan *c; | ||
| 305 | Mntrpc *r; | 302 | Mntrpc *r; |
| 306 | struct bogus{ | ||
| 307 | Chan *chan; | ||
| 308 | Chan *authchan; | ||
| 309 | char *spec; | ||
| 310 | int flags; | ||
| 311 | }bogus; | ||
| 312 | |||
| 313 | bogus = *((struct bogus *)muxattach); | ||
| 314 | c = bogus.chan; | ||
| 315 | 303 | ||
| 316 | m = c->mux; | 304 | m = c->mux; |
| 317 | |||
| 318 | if(m == nil){ | 305 | if(m == nil){ |
| 319 | mntversion(c, nil, 0, 0); | 306 | mntversion(c, nil, 0, 0); |
| 320 | m = c->mux; | 307 | m = c->mux; |
| @@ -331,21 +318,19 @@ mntattach(char *muxattach) · 10 unmodified lines | |||
| 331 | nexterror(); | 318 | nexterror(); |
| 332 | } | 319 | } |
| 333 | 320 | ||
| 334 | r = mntralloc(0, m->msize); | 321 | r = mntralloc(c); |
| 335 | |||
| 336 | if(waserror()) { | 322 | if(waserror()) { |
| 337 | mntfree(r); | 323 | mntfree(r); |
| 338 | nexterror(); | 324 | nexterror(); |
| 339 | } | 325 | } |
| 340 | |||
| 341 | r->request.type = Tattach; | 326 | r->request.type = Tattach; |
| 342 | r->request.fid = c->fid; | 327 | r->request.fid = c->fid; |
| 343 | if(bogus.authchan == nil) | 328 | if(ac == nil) |
| 344 | r->request.afid = NOFID; | 329 | r->request.afid = NOFID; |
| 345 | else | 330 | else |
| 346 | r->request.afid = bogus.authchan->fid; | 331 | r->request.afid = ac->fid; |
| 347 | r->request.uname = up->user; | 332 | r->request.uname = up->user; |
| 348 | r->request.aname = bogus.spec; | 333 | r->request.aname = spec; |
| 349 | mountrpc(m, r); | 334 | mountrpc(m, r); |
| 350 | 335 | ||
| 351 | c->qid = r->reply.qid; | 336 | c->qid = r->reply.qid; |
| @@ -358,12 +343,20 @@ mntattach(char *muxattach) · 6 unmodified lines | |||
| 358 | 343 | ||
| 359 | poperror(); /* c */ | 344 | poperror(); /* c */ |
| 360 | 345 | ||
| 361 | if(bogus.flags&MCACHE) | 346 | if(flags&MCACHE) |
| 362 | c->flag |= CCACHE; | 347 | c->flag |= CCACHE; |
| 363 | return c; | 348 | return c; |
| 364 | } | 349 | } |
| 365 | 350 | ||
| 366 | Chan* | 351 | static Chan* |
| 352 | noattach(char *s) | ||
| 353 | { | ||
| 354 | USED(s); | ||
| 355 | error(Enoattach); | ||
| 356 | return nil; | ||
| 357 | } | ||
| 358 | |||
| 359 | static Chan* | ||
| 367 | mntchan(void) | 360 | mntchan(void) |
| 368 | { | 361 | { |
| 369 | Chan *c; | 362 | Chan *c; |
| @@ -373,7 +366,7 @@ mntchan(void) · 3 unmodified lines | |||
| 373 | c->dev = mntalloc.id++; | 366 | c->dev = mntalloc.id++; |
| 374 | unlock(&mntalloc.lk); | 367 | unlock(&mntalloc.lk); |
| 375 | 368 | ||
| 376 | if(c->mchan) | 369 | if(c->mchan != nil) |
| 377 | panic("mntchan non-zero %p", c->mchan); | 370 | panic("mntchan non-zero %p", c->mchan); |
| 378 | return c; | 371 | return c; |
| 379 | } | 372 | } |
| @@ -401,7 +394,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) · 21 unmodified lines | |||
| 401 | 394 | ||
| 402 | alloc = 0; | 395 | alloc = 0; |
| 403 | m = mntchk(c); | 396 | m = mntchk(c); |
| 404 | r = mntralloc(c, m->msize); | 397 | r = mntralloc(c); |
| 405 | if(nc == nil){ | 398 | if(nc == nil){ |
| 406 | nc = devclone(c); | 399 | nc = devclone(c); |
| 407 | /* | 400 | /* |
| @@ -409,6 +402,7 @@ mntwalk(Chan *c, Chan *nc, char **name, int nname) · 1 unmodified line | |||
| 409 | * Therefore set type to 0 for now; rootclose is known to be safe. | 402 | * Therefore set type to 0 for now; rootclose is known to be safe. |
| 410 | */ | 403 | */ |
| 411 | nc->type = 0; | 404 | nc->type = 0; |
| 405 | nc->flag |= (c->flag & CCACHE); | ||
| 412 | alloc = 1; | 406 | alloc = 1; |
| 413 | } | 407 | } |
| 414 | wq->clone = nc; | 408 | wq->clone = nc; |
| @@ -468,7 +462,7 @@ mntstat(Chan *c, uchar *dp, int n) · 53 unmodified lines | |||
| 468 | if(n < BIT16SZ) | 462 | if(n < BIT16SZ) |
| 469 | error(Eshortstat); | 463 | error(Eshortstat); |
| 470 | m = mntchk(c); | 464 | m = mntchk(c); |
| 471 | r = mntralloc(c, m->msize); | 465 | r = mntralloc(c); |
| 472 | if(waserror()) { | 466 | if(waserror()) { |
| 473 | mntfree(r); | 467 | mntfree(r); |
| 474 | nexterror(); | 468 | nexterror(); |
| @@ -477,28 +471,9 @@ mntstat(Chan *c, uchar *dp, int n) · 2 unmodified lines | |||
| 477 | r->request.fid = c->fid; | 471 | r->request.fid = c->fid; |
| 478 | mountrpc(m, r); | 472 | mountrpc(m, r); |
| 479 | 473 | ||
| 480 | /* r->reply.nstat is 16 bits | ||
| 481 | if(r->reply.nstat >= 1<<16) | ||
| 482 | error("returned stat buffer count too large"); | ||
| 483 | */ | ||
| 484 | |||
| 485 | if(r->reply.nstat > n){ | 474 | if(r->reply.nstat > n){ |
| 486 | /* | ||
| 487 | * 12/31/2002 RSC | ||
| 488 | * | ||
| 489 | * This should be nstat-2, which is the first two | ||
| 490 | * bytes of the stat buffer. But dirstat and dirfstat | ||
| 491 | * depended on getting the full nstat (they didn't | ||
| 492 | * add BIT16SZ themselves). I fixed dirstat and dirfstat | ||
| 493 | * but am leaving this unchanged for now. After a | ||
| 494 | * few months, once enough of the relevant binaries | ||
| 495 | * have been recompiled for other reasons, we can | ||
| 496 | * change this to nstat-2. Devstat gets this right | ||
| 497 | * (via convD2M). | ||
| 498 | */ | ||
| 499 | /* doesn't fit; just patch the count and return */ | ||
| 500 | PBIT16((uchar*)dp, r->reply.nstat); | ||
| 501 | n = BIT16SZ; | 475 | n = BIT16SZ; |
| 476 | PBIT16((uchar*)dp, r->reply.nstat-2); | ||
| 502 | }else{ | 477 | }else{ |
| 503 | n = r->reply.nstat; | 478 | n = r->reply.nstat; |
| 504 | memmove(dp, r->reply.stat, n); | 479 | memmove(dp, r->reply.stat, n); |
| @@ -517,7 +492,7 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) · 12 unmodified lines | |||
| 517 | Mntrpc *r; | 492 | Mntrpc *r; |
| 518 | 493 | ||
| 519 | m = mntchk(c); | 494 | m = mntchk(c); |
| 520 | r = mntralloc(c, m->msize); | 495 | r = mntralloc(c); |
| 521 | if(waserror()) { | 496 | if(waserror()) { |
| 522 | mntfree(r); | 497 | mntfree(r); |
| 523 | nexterror(); | 498 | nexterror(); |
| @@ -541,9 +516,6 @@ mntopencreate(int type, Chan *c, char *name, int omode, ulong perm) · 17 unmodified lines | |||
| 541 | poperror(); | 516 | poperror(); |
| 542 | mntfree(r); | 517 | mntfree(r); |
| 543 | 518 | ||
| 544 | if(c->flag & CCACHE) | ||
| 545 | copen(c); | ||
| 546 | |||
| 547 | return c; | 519 | return c; |
| 548 | } | 520 | } |
| 549 | 521 | ||
| @@ -566,12 +538,11 @@ mntclunk(Chan *c, int t) · 16 unmodified lines | |||
| 566 | Mntrpc *r; | 538 | Mntrpc *r; |
| 567 | 539 | ||
| 568 | m = mntchk(c); | 540 | m = mntchk(c); |
| 569 | r = mntralloc(c, m->msize); | 541 | r = mntralloc(c); |
| 570 | if(waserror()){ | 542 | if(waserror()) { |
| 571 | mntfree(r); | 543 | mntfree(r); |
| 572 | nexterror(); | 544 | nexterror(); |
| 573 | } | 545 | } |
| 574 | |||
| 575 | r->request.type = t; | 546 | r->request.type = t; |
| 576 | r->request.fid = c->fid; | 547 | r->request.fid = c->fid; |
| 577 | mountrpc(m, r); | 548 | mountrpc(m, r); |
| @@ -582,27 +553,22 @@ mntclunk(Chan *c, int t) · 4 unmodified lines | |||
| 582 | void | 553 | void |
| 583 | muxclose(Mnt *m) | 554 | muxclose(Mnt *m) |
| 584 | { | 555 | { |
| 585 | Mntrpc *q, *r; | 556 | Mnt *f, **l; |
| 557 | Mntrpc *r; | ||
| 586 | 558 | ||
| 587 | for(q = m->queue; q; q = r) { | 559 | while((r = m->queue) != nil){ |
| 588 | r = q->list; | 560 | m->queue = r->list; |
| 589 | mntfree(q); | 561 | mntfree(r); |
| 590 | } | 562 | } |
| 591 | m->id = 0; | 563 | m->id = 0; |
| 592 | free(m->version); | 564 | free(m->version); |
| 593 | m->version = nil; | 565 | m->version = nil; |
| 594 | mntpntfree(m); | 566 | qfree(m->q); |
| 595 | } | 567 | m->q = nil; |
| 596 | |||
| 597 | void | ||
| 598 | mntpntfree(Mnt *m) | ||
| 599 | { | ||
| 600 | Mnt *f, **l; | ||
| 601 | Queue *q; | ||
| 602 | 568 | ||
| 603 | lock(&mntalloc.lk); | 569 | lock(&mntalloc.lk); |
| 604 | l = &mntalloc.list; | 570 | l = &mntalloc.list; |
| 605 | for(f = *l; f; f = f->list) { | 571 | for(f = *l; f != nil; f = f->list) { |
| 606 | if(f == m) { | 572 | if(f == m) { |
| 607 | *l = m->list; | 573 | *l = m->list; |
| 608 | break; | 574 | break; |
| @@ -611,10 +577,7 @@ mntpntfree(Mnt *m) · 2 unmodified lines | |||
| 611 | } | 577 | } |
| 612 | m->list = mntalloc.mntfree; | 578 | m->list = mntalloc.mntfree; |
| 613 | mntalloc.mntfree = m; | 579 | mntalloc.mntfree = m; |
| 614 | q = m->q; | ||
| 615 | unlock(&mntalloc.lk); | 580 | unlock(&mntalloc.lk); |
| 616 | |||
| 617 | qfree(q); | ||
| 618 | } | 581 | } |
| 619 | 582 | ||
| 620 | static void | 583 | static void |
| @@ -636,7 +599,7 @@ mntwstat(Chan *c, uchar *dp, int n) · 15 unmodified lines | |||
| 636 | Mntrpc *r; | 599 | Mntrpc *r; |
| 637 | 600 | ||
| 638 | m = mntchk(c); | 601 | m = mntchk(c); |
| 639 | r = mntralloc(c, m->msize); | 602 | r = mntralloc(c); |
| 640 | if(waserror()) { | 603 | if(waserror()) { |
| 641 | mntfree(r); | 604 | mntfree(r); |
| 642 | nexterror(); | 605 | nexterror(); |
| @@ -655,32 +618,11 @@ static long · 12 unmodified lines | |||
| 655 | mntread(Chan *c, void *buf, long n, vlong off) | 618 | mntread(Chan *c, void *buf, long n, vlong off) |
| 656 | { | 619 | { |
| 657 | uchar *p, *e; | 620 | uchar *p, *e; |
| 658 | int nc, cache, isdir, dirlen; | 621 | int dirlen; |
| 659 | |||
| 660 | isdir = 0; | ||
| 661 | cache = c->flag & CCACHE; | ||
| 662 | if(c->qid.type & QTDIR) { | ||
| 663 | cache = 0; | ||
| 664 | isdir = 1; | ||
| 665 | } | ||
| 666 | 622 | ||
| 667 | p = buf; | 623 | p = buf; |
| 668 | if(cache) { | 624 | n = mntrdwr(Tread, c, p, n, off); |
| 669 | nc = cread(c, buf, n, off); | 625 | if(c->qid.type & QTDIR) { |
| 670 | if(nc > 0) { | ||
| 671 | n -= nc; | ||
| 672 | if(n == 0) | ||
| 673 | return nc; | ||
| 674 | p += nc; | ||
| 675 | off += nc; | ||
| 676 | } | ||
| 677 | n = mntrdwr(Tread, c, p, n, off); | ||
| 678 | cupdate(c, p, n, off); | ||
| 679 | return n + nc; | ||
| 680 | } | ||
| 681 | |||
| 682 | n = mntrdwr(Tread, c, buf, n, off); | ||
| 683 | if(isdir) { | ||
| 684 | for(e = &p[n]; p+BIT16SZ < e; p += dirlen){ | 626 | for(e = &p[n]; p+BIT16SZ < e; p += dirlen){ |
| 685 | dirlen = BIT16SZ+GBIT16(p); | 627 | dirlen = BIT16SZ+GBIT16(p); |
| 686 | if(p+dirlen > e) | 628 | if(p+dirlen > e) |
| @@ -700,23 +642,24 @@ mntwrite(Chan *c, void *buf, long n, vlong off) · 13 unmodified lines | |||
| 700 | return mntrdwr(Twrite, c, buf, n, off); | 642 | return mntrdwr(Twrite, c, buf, n, off); |
| 701 | } | 643 | } |
| 702 | 644 | ||
| 703 | long | 645 | static long |
| 704 | mntrdwr(int type, Chan *c, void *buf, long n, vlong off) | 646 | mntrdwr(int type, Chan *c, void *buf, long n, vlong off) |
| 705 | { | 647 | { |
| 706 | Mnt *m; | 648 | Mnt *m; |
| 707 | Mntrpc *r; | 649 | Mntrpc *r; |
| 708 | char *uba; | 650 | char *uba; |
| 709 | int cache; | ||
| 710 | ulong cnt, nr, nreq; | 651 | ulong cnt, nr, nreq; |
| 711 | 652 | ||
| 712 | m = mntchk(c); | 653 | m = mntchk(c); |
| 713 | uba = buf; | 654 | uba = buf; |
| 714 | cnt = 0; | 655 | cnt = 0; |
| 715 | cache = c->flag & CCACHE; | 656 | |
| 716 | if(c->qid.type & QTDIR) | ||
| 717 | cache = 0; | ||
| 718 | for(;;) { | 657 | for(;;) { |
| 719 | r = mntralloc(c, m->msize); | 658 | nreq = n; |
| 659 | if(nreq > c->iounit) | ||
| 660 | nreq = c->iounit; | ||
| 661 | |||
| 662 | r = mntralloc(c); | ||
| 720 | if(waserror()) { | 663 | if(waserror()) { |
| 721 | mntfree(r); | 664 | mntfree(r); |
| 722 | nexterror(); | 665 | nexterror(); |
| @@ -725,23 +668,16 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) · 2 unmodified lines | |||
| 725 | r->request.fid = c->fid; | 668 | r->request.fid = c->fid; |
| 726 | r->request.offset = off; | 669 | r->request.offset = off; |
| 727 | r->request.data = uba; | 670 | r->request.data = uba; |
| 728 | nr = n; | 671 | r->request.count = nreq; |
| 729 | if(nr > m->msize-IOHDRSZ) | ||
| 730 | nr = m->msize-IOHDRSZ; | ||
| 731 | r->request.count = nr; | ||
| 732 | mountrpc(m, r); | 672 | mountrpc(m, r); |
| 733 | nreq = r->request.count; | ||
| 734 | nr = r->reply.count; | 673 | nr = r->reply.count; |
| 735 | if(nr > nreq) | 674 | if(nr > nreq) |
| 736 | nr = nreq; | 675 | nr = nreq; |
| 737 | |||
| 738 | if(type == Tread) | 676 | if(type == Tread) |
| 739 | r->b = bl2mem((uchar*)uba, r->b, nr); | 677 | nr = readblist(r->b, (uchar*)uba, nr, 0); |
| 740 | else if(cache) | ||
| 741 | cwrite(c, (uchar*)uba, nr, off); | ||
| 742 | |||
| 743 | poperror(); | ||
| 744 | mntfree(r); | 678 | mntfree(r); |
| 679 | poperror(); | ||
| 680 | |||
| 745 | off += nr; | 681 | off += nr; |
| 746 | uba += nr; | 682 | uba += nr; |
| 747 | cnt += nr; | 683 | cnt += nr; |
| @@ -752,10 +688,9 @@ mntrdwr(int type, Chan *c, void *buf, long n, vlong off) · 4 unmodified lines | |||
| 752 | return cnt; | 688 | return cnt; |
| 753 | } | 689 | } |
| 754 | 690 | ||
| 755 | void | 691 | static void |
| 756 | mountrpc(Mnt *m, Mntrpc *r) | 692 | mountrpc(Mnt *m, Mntrpc *r) |
| 757 | { | 693 | { |
| 758 | char *sn, *cn; | ||
| 759 | int t; | 694 | int t; |
| 760 | 695 | ||
| 761 | r->reply.tag = 0; | 696 | r->reply.tag = 0; |
| @@ -772,60 +707,70 @@ mountrpc(Mnt *m, Mntrpc *r) · 10 unmodified lines | |||
| 772 | default: | 707 | default: |
| 773 | if(t == r->request.type+1) | 708 | if(t == r->request.type+1) |
| 774 | break; | 709 | break; |
| 775 | sn = "?"; | 710 | print("mnt: proc %s %lud: mismatch from %s %s rep %#p tag %d fid %d T%d R%d rp %d\n", |
| 776 | if(m->c->name != nil) | 711 | up->text, up->pid, chanpath(m->c), chanpath(r->c), |
| 777 | sn = m->c->name->s; | ||
| 778 | cn = "?"; | ||
| 779 | if(r->c != nil && r->c->name != nil) | ||
| 780 | cn = r->c->name->s; | ||
| 781 | print("mnt: proc %lud: mismatch from %s %s rep 0x%lux tag %d fid %d T%d R%d rp %d\n", | ||
| 782 | up->pid, sn, cn, | ||
| 783 | r, r->request.tag, r->request.fid, r->request.type, | 712 | r, r->request.tag, r->request.fid, r->request.type, |
| 784 | r->reply.type, r->reply.tag); | 713 | r->reply.type, r->reply.tag); |
| 785 | error(Emountrpc); | 714 | error(Emountrpc); |
| 786 | } | 715 | } |
| 787 | } | 716 | } |
| 788 | 717 | ||
| 789 | void | 718 | static void |
| 790 | mountio(Mnt *m, Mntrpc *r) | 719 | mountio(Mnt *m, Mntrpc *r) |
| 791 | { | 720 | { |
| 721 | Block *b; | ||
| 792 | int n; | 722 | int n; |
| 793 | 723 | ||
| 794 | while(waserror()) { | 724 | while(waserror()) { |
| 795 | if(m->rip == up) | 725 | if(m->rip == up) |
| 796 | mntgate(m); | 726 | mntgate(m); |
| 797 | if(strcmp(up->errstr, Eintr) != 0){ | 727 | if(strcmp(up->errstr, Eintr) != 0 || waserror()){ |
| 798 | mntflushfree(m, r); | 728 | r = mntflushfree(m, r); |
| 729 | switch(r->request.type){ | ||
| 730 | case Tremove: | ||
| 731 | case Tclunk: | ||
| 732 | /* botch, abandon fid */ | ||
| 733 | if(strcmp(up->errstr, Ehungup) != 0) | ||
| 734 | r->c->fid = 0; | ||
| 735 | } | ||
| 799 | nexterror(); | 736 | nexterror(); |
| 800 | } | 737 | } |
| 801 | r = mntflushalloc(r, m->msize); | 738 | r = mntflushalloc(r); |
| 739 | poperror(); | ||
| 802 | } | 740 | } |
| 803 | 741 | ||
| 804 | lock(&m->lk); | 742 | lock(&m->lk); |
| 743 | r->z = &up->sleep; | ||
| 805 | r->m = m; | 744 | r->m = m; |
| 806 | r->list = m->queue; | 745 | r->list = m->queue; |
| 807 | m->queue = r; | 746 | m->queue = r; |
| 808 | unlock(&m->lk); | 747 | unlock(&m->lk); |
| 809 | 748 | ||
| 810 | /* Transmit a file system rpc */ | 749 | /* Transmit a file system rpc */ |
| 811 | if(m->msize == 0) | 750 | n = sizeS2M(&r->request); |
| 812 | panic("msize"); | 751 | b = allocb(n); |
| 813 | n = convS2M(&r->request, r->rpc, m->msize); | 752 | if(waserror()){ |
| 814 | if(n < 0) | 753 | freeb(b); |
| 815 | panic("bad message type in mountio"); | 754 | nexterror(); |
| 816 | if(devtab[m->c->type]->write(m->c, r->rpc, n, 0) != n) | 755 | } |
| 756 | n = convS2M(&r->request, b->wp, n); | ||
| 757 | if(n <= 0 || n > m->msize) { | ||
| 758 | print("mountio: proc %s %lud: convS2M returned %d for tag %d fid %d T%d\n", | ||
| 759 | up->text, up->pid, n, r->request.tag, r->request.fid, r->request.type); | ||
| 817 | error(Emountrpc); | 760 | error(Emountrpc); |
| 818 | r->stime = fastticks(nil); | 761 | } |
| 819 | r->reqlen = n; | 762 | b->wp += n; |
| 763 | poperror(); | ||
| 764 | devtab[m->c->type]->bwrite(m->c, b, 0); | ||
| 820 | 765 | ||
| 821 | /* Gate readers onto the mount point one at a time */ | 766 | /* Gate readers onto the mount point one at a time */ |
| 822 | for(;;) { | 767 | for(;;) { |
| 823 | lock(&m->lk); | 768 | lock(&m->lk); |
| 824 | if(m->rip == 0) | 769 | if(m->rip == nil) |
| 825 | break; | 770 | break; |
| 826 | unlock(&m->lk); | 771 | unlock(&m->lk); |
| 827 | sleep(&r->r, rpcattn, r); | 772 | sleep(r->z, rpcattn, r); |
| 828 | if(r->done){ | 773 | if(r->done) { |
| 829 | poperror(); | 774 | poperror(); |
| 830 | mntflushfree(m, r); | 775 | mntflushfree(m, r); |
| 831 | return; | 776 | return; |
| @@ -850,18 +795,13 @@ doread(Mnt *m, int len) · 18 unmodified lines | |||
| 850 | 795 | ||
| 851 | while(qlen(m->q) < len){ | 796 | while(qlen(m->q) < len){ |
| 852 | b = devtab[m->c->type]->bread(m->c, m->msize, 0); | 797 | b = devtab[m->c->type]->bread(m->c, m->msize, 0); |
| 853 | if(b == nil) | 798 | if(b == nil || qaddlist(m->q, b) == 0) |
| 854 | return -1; | 799 | return -1; |
| 855 | if(BLEN(b) == 0){ | ||
| 856 | freeblist(b); | ||
| 857 | return -1; | ||
| 858 | } | ||
| 859 | qaddlist(m->q, b); | ||
| 860 | } | 800 | } |
| 861 | return 0; | 801 | return 0; |
| 862 | } | 802 | } |
| 863 | 803 | ||
| 864 | int | 804 | static int |
| 865 | mntrpcread(Mnt *m, Mntrpc *r) | 805 | mntrpcread(Mnt *m, Mntrpc *r) |
| 866 | { | 806 | { |
| 867 | int i, t, len, hlen; | 807 | int i, t, len, hlen; |
| @@ -875,7 +815,7 @@ mntrpcread(Mnt *m, Mntrpc *r) · 7 unmodified lines | |||
| 875 | return -1; | 815 | return -1; |
| 876 | nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); | 816 | nb = pullupqueue(m->q, BIT32SZ+BIT8SZ+BIT16SZ); |
| 877 | 817 | ||
| 878 | /* read in the rest of the message, avoid rediculous (for now) message sizes */ | 818 | /* read in the rest of the message, avoid ridiculous (for now) message sizes */ |
| 879 | len = GBIT32(nb->rp); | 819 | len = GBIT32(nb->rp); |
| 880 | if(len > m->msize){ | 820 | if(len > m->msize){ |
| 881 | qdiscard(m->q, qlen(m->q)); | 821 | qdiscard(m->q, qlen(m->q)); |
| @@ -933,49 +873,50 @@ mntrpcread(Mnt *m, Mntrpc *r) · 51 unmodified lines | |||
| 933 | return 0; | 873 | return 0; |
| 934 | } | 874 | } |
| 935 | 875 | ||
| 936 | void | 876 | static void |
| 937 | mntgate(Mnt *m) | 877 | mntgate(Mnt *m) |
| 938 | { | 878 | { |
| 939 | Mntrpc *q; | 879 | Mntrpc *q; |
| 940 | 880 | ||
| 941 | lock(&m->lk); | 881 | lock(&m->lk); |
| 942 | m->rip = 0; | 882 | m->rip = nil; |
| 943 | for(q = m->queue; q; q = q->list) { | 883 | for(q = m->queue; q != nil; q = q->list) { |
| 944 | if(q->done == 0) | 884 | if(q->done == 0) |
| 945 | if(wakeup(&q->r)) | 885 | if(wakeup(q->z)) |
| 946 | break; | 886 | break; |
| 947 | } | 887 | } |
| 948 | unlock(&m->lk); | 888 | unlock(&m->lk); |
| 949 | } | 889 | } |
| 950 | 890 | ||
| 951 | void | 891 | static void |
| 952 | mountmux(Mnt *m, Mntrpc *r) | 892 | mountmux(Mnt *m, Mntrpc *r) |
| 953 | { | 893 | { |
| 954 | Mntrpc **l, *q; | 894 | Mntrpc **l, *q; |
| 895 | Rendez *z; | ||
| 955 | 896 | ||
| 956 | lock(&m->lk); | 897 | lock(&m->lk); |
| 957 | l = &m->queue; | 898 | l = &m->queue; |
| 958 | for(q = *l; q; q = q->list) { | 899 | for(q = *l; q != nil; q = q->list) { |
| 959 | /* look for a reply to a message */ | 900 | /* look for a reply to a message */ |
| 960 | if(q->request.tag == r->reply.tag) { | 901 | if(q->request.tag == r->reply.tag) { |
| 961 | *l = q->list; | 902 | *l = q->list; |
| 962 | if(q != r) { | 903 | if(q == r) { |
| 963 | /* | 904 | q->done = 1; |
| 964 | * Completed someone else. | 905 | unlock(&m->lk); |
| 965 | * Trade pointers to receive buffer. | 906 | return; |
| 966 | */ | ||
| 967 | q->reply = r->reply; | ||
| 968 | q->b = r->b; | ||
| 969 | r->b = nil; | ||
| 970 | } | 907 | } |
| 908 | /* | ||
| 909 | * Completed someone else. | ||
| 910 | * Trade pointers to receive buffer. | ||
| 911 | */ | ||
| 912 | q->reply = r->reply; | ||
| 913 | q->b = r->b; | ||
| 914 | r->b = nil; | ||
| 915 | z = q->z; | ||
| 916 | // coherence(); | ||
| 971 | q->done = 1; | 917 | q->done = 1; |
| 918 | wakeup(z); | ||
| 972 | unlock(&m->lk); | 919 | unlock(&m->lk); |
| 973 | if(mntstats != 0) | ||
| 974 | (*mntstats)(q->request.type, | ||
| 975 | m->c, q->stime, | ||
| 976 | q->reqlen + r->replen); | ||
| 977 | if(q != r) | ||
| 978 | wakeup(&q->r); | ||
| 979 | return; | 920 | return; |
| 980 | } | 921 | } |
| 981 | l = &q->list; | 922 | l = &q->list; |
| @@ -988,13 +929,12 @@ mountmux(Mnt *m, Mntrpc *r) · 6 unmodified lines | |||
| 988 | * Create a new flush request and chain the previous | 929 | * Create a new flush request and chain the previous |
| 989 | * requests from it | 930 | * requests from it |
| 990 | */ | 931 | */ |
| 991 | Mntrpc* | 932 | static Mntrpc* |
| 992 | mntflushalloc(Mntrpc *r, ulong iounit) | 933 | mntflushalloc(Mntrpc *r) |
| 993 | { | 934 | { |
| 994 | Mntrpc *fr; | 935 | Mntrpc *fr; |
| 995 | 936 | ||
| 996 | fr = mntralloc(0, iounit); | 937 | fr = mntralloc(r->c); |
| 997 | |||
| 998 | fr->request.type = Tflush; | 938 | fr->request.type = Tflush; |
| 999 | if(r->request.type == Tflush) | 939 | if(r->request.type == Tflush) |
| 1000 | fr->request.oldtag = r->request.oldtag; | 940 | fr->request.oldtag = r->request.oldtag; |
| @@ -1010,26 +950,28 @@ mntflushalloc(Mntrpc *r, ulong iounit) · 9 unmodified lines | |||
| 1010 | * flush and the original message from the unanswered | 950 | * flush and the original message from the unanswered |
| 1011 | * request queue. Mark the original message as done | 951 | * request queue. Mark the original message as done |
| 1012 | * and if it hasn't been answered set the reply to to | 952 | * and if it hasn't been answered set the reply to to |
| 1013 | * Rflush. | 953 | * Rflush. Return the original rpc. |
| 1014 | */ | 954 | */ |
| 1015 | void | 955 | static Mntrpc* |
| 1016 | mntflushfree(Mnt *m, Mntrpc *r) | 956 | mntflushfree(Mnt *m, Mntrpc *r) |
| 1017 | { | 957 | { |
| 1018 | Mntrpc *fr; | 958 | Mntrpc *fr; |
| 1019 | 959 | ||
| 1020 | while(r){ | 960 | while(r != nil){ |
| 1021 | fr = r->flushed; | 961 | fr = r->flushed; |
| 1022 | if(!r->done){ | 962 | if(!r->done){ |
| 1023 | r->reply.type = Rflush; | 963 | r->reply.type = Rflush; |
| 1024 | mntqrm(m, r); | 964 | mntqrm(m, r); |
| 1025 | } | 965 | } |
| 1026 | if(fr) | 966 | if(fr == nil) |
| 1027 | mntfree(r); | 967 | break; |
| 968 | mntfree(r); | ||
| 1028 | r = fr; | 969 | r = fr; |
| 1029 | } | 970 | } |
| 971 | return r; | ||
| 1030 | } | 972 | } |
| 1031 | 973 | ||
| 1032 | int | 974 | static int |
| 1033 | alloctag(void) | 975 | alloctag(void) |
| 1034 | { | 976 | { |
| 1035 | int i, j; | 977 | int i, j; |
| @@ -1037,7 +979,7 @@ alloctag(void) · 1 unmodified line | |||
| 1037 | 979 | ||
| 1038 | for(i = 0; i < NMASK; i++){ | 980 | for(i = 0; i < NMASK; i++){ |
| 1039 | v = mntalloc.tagmask[i]; | 981 | v = mntalloc.tagmask[i]; |
| 1040 | if(v == ~0) | 982 | if(v == ~0UL) |
| 1041 | continue; | 983 | continue; |
| 1042 | for(j = 0; j < 1<<TAGSHIFT; j++) | 984 | for(j = 0; j < 1<<TAGSHIFT; j++) |
| 1043 | if((v & (1<<j)) == 0){ | 985 | if((v & (1<<j)) == 0){ |
| @@ -1049,52 +991,33 @@ alloctag(void) · 5 unmodified lines | |||
| 1049 | return NOTAG; | 991 | return NOTAG; |
| 1050 | } | 992 | } |
| 1051 | 993 | ||
| 1052 | void | 994 | static void |
| 1053 | freetag(int t) | 995 | freetag(int t) |
| 1054 | { | 996 | { |
| 1055 | mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK)); | 997 | mntalloc.tagmask[t>>TAGSHIFT] &= ~(1<<(t&TAGMASK)); |
| 1056 | } | 998 | } |
| 1057 | 999 | ||
| 1058 | Mntrpc* | 1000 | static Mntrpc* |
| 1059 | mntralloc(Chan *c, ulong msize) | 1001 | mntralloc(Chan *c) |
| 1060 | { | 1002 | { |
| 1061 | Mntrpc *new; | 1003 | Mntrpc *new; |
| 1062 | 1004 | ||
| 1063 | lock(&mntalloc.lk); | 1005 | if(mntalloc.nrpcfree == 0) { |
| 1064 | new = mntalloc.rpcfree; | 1006 | Alloc: |
| 1065 | if(new == nil){ | ||
| 1066 | new = malloc(sizeof(Mntrpc)); | 1007 | new = malloc(sizeof(Mntrpc)); |
| 1067 | if(new == nil) { | 1008 | if(new == nil) |
| 1068 | unlock(&mntalloc.lk); | ||
| 1069 | exhausted("mount rpc header"); | 1009 | exhausted("mount rpc header"); |
| 1070 | } | 1010 | lock(&mntalloc.lk); |
| 1071 | /* | 1011 | new->request.tag = alloctag(); |
| 1072 | * The header is split from the data buffer as | 1012 | } else { |
| 1073 | * mountmux may swap the buffer with another header. | 1013 | lock(&mntalloc.lk); |
| 1074 | */ | 1014 | new = mntalloc.rpcfree; |
| 1075 | new->rpc = mallocz(msize, 0); | 1015 | if(new == nil) { |
| 1076 | if(new->rpc == nil){ | ||
| 1077 | free(new); | ||
| 1078 | unlock(&mntalloc.lk); | 1016 | unlock(&mntalloc.lk); |
| 1079 | exhausted("mount rpc buffer"); | 1017 | goto Alloc; |
| 1080 | } | 1018 | } |
| 1081 | new->rpclen = msize; | ||
| 1082 | new->request.tag = alloctag(); | ||
| 1083 | } | ||
| 1084 | else { | ||
| 1085 | mntalloc.rpcfree = new->list; | 1019 | mntalloc.rpcfree = new->list; |
| 1086 | mntalloc.nrpcfree--; | 1020 | mntalloc.nrpcfree--; |
| 1087 | if(new->rpclen < msize){ | ||
| 1088 | free(new->rpc); | ||
| 1089 | new->rpc = mallocz(msize, 0); | ||
| 1090 | if(new->rpc == nil){ | ||
| 1091 | free(new); | ||
| 1092 | mntalloc.nrpcused--; | ||
| 1093 | unlock(&mntalloc.lk); | ||
| 1094 | exhausted("mount rpc buffer"); | ||
| 1095 | } | ||
| 1096 | new->rpclen = msize; | ||
| 1097 | } | ||
| 1098 | } | 1021 | } |
| 1099 | mntalloc.nrpcused++; | 1022 | mntalloc.nrpcused++; |
| 1100 | unlock(&mntalloc.lk); | 1023 | unlock(&mntalloc.lk); |
| @@ -1105,27 +1028,25 @@ mntralloc(Chan *c, ulong msize) · 4 unmodified lines | |||
| 1105 | return new; | 1028 | return new; |
| 1106 | } | 1029 | } |
| 1107 | 1030 | ||
| 1108 | void | 1031 | static void |
| 1109 | mntfree(Mntrpc *r) | 1032 | mntfree(Mntrpc *r) |
| 1110 | { | 1033 | { |
| 1111 | if(r->b != nil) | 1034 | freeblist(r->b); |
| 1112 | freeblist(r->b); | ||
| 1113 | lock(&mntalloc.lk); | 1035 | lock(&mntalloc.lk); |
| 1114 | if(mntalloc.nrpcfree >= 10){ | 1036 | mntalloc.nrpcused--; |
| 1115 | free(r->rpc); | 1037 | if(mntalloc.nrpcfree < 32) { |
| 1116 | free(r); | ||
| 1117 | freetag(r->request.tag); | ||
| 1118 | } | ||
| 1119 | else{ | ||
| 1120 | r->list = mntalloc.rpcfree; | 1038 | r->list = mntalloc.rpcfree; |
| 1121 | mntalloc.rpcfree = r; | 1039 | mntalloc.rpcfree = r; |
| 1122 | mntalloc.nrpcfree++; | 1040 | mntalloc.nrpcfree++; |
| 1041 | unlock(&mntalloc.lk); | ||
| 1042 | return; | ||
| 1123 | } | 1043 | } |
| 1124 | mntalloc.nrpcused--; | 1044 | freetag(r->request.tag); |
| 1125 | unlock(&mntalloc.lk); | 1045 | unlock(&mntalloc.lk); |
| 1046 | free(r); | ||
| 1126 | } | 1047 | } |
| 1127 | 1048 | ||
| 1128 | void | 1049 | static void |
| 1129 | mntqrm(Mnt *m, Mntrpc *r) | 1050 | mntqrm(Mnt *m, Mntrpc *r) |
| 1130 | { | 1051 | { |
| 1131 | Mntrpc **l, *f; | 1052 | Mntrpc **l, *f; |
| @@ -1134,7 +1055,7 @@ mntqrm(Mnt *m, Mntrpc *r) · 2 unmodified lines | |||
| 1134 | r->done = 1; | 1055 | r->done = 1; |
| 1135 | 1056 | ||
| 1136 | l = &m->queue; | 1057 | l = &m->queue; |
| 1137 | for(f = *l; f; f = f->list) { | 1058 | for(f = *l; f != nil; f = f->list) { |
| 1138 | if(f == r) { | 1059 | if(f == r) { |
| 1139 | *l = r->list; | 1060 | *l = r->list; |
| 1140 | break; | 1061 | break; |
| @@ -1144,23 +1065,21 @@ mntqrm(Mnt *m, Mntrpc *r) · 3 unmodified lines | |||
| 1144 | unlock(&m->lk); | 1065 | unlock(&m->lk); |
| 1145 | } | 1066 | } |
| 1146 | 1067 | ||
| 1147 | Mnt* | 1068 | static Mnt* |
| 1148 | mntchk(Chan *c) | 1069 | mntchk(Chan *c) |
| 1149 | { | 1070 | { |
| 1150 | Mnt *m; | 1071 | Mnt *m; |
| 1151 | 1072 | ||
| 1152 | /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ | 1073 | /* This routine is mostly vestiges of prior lives; now it's just sanity checking */ |
| 1153 | |||
| 1154 | if(c->mchan == nil) | 1074 | if(c->mchan == nil) |
| 1155 | panic("mntchk 1: nil mchan c %s\n", chanpath(c)); | 1075 | panic("mntchk 1: nil mchan c %s", chanpath(c)); |
| 1156 | 1076 | ||
| 1157 | m = c->mchan->mux; | 1077 | m = c->mchan->mux; |
| 1158 | |||
| 1159 | if(m == nil) | 1078 | if(m == nil) |
| 1160 | print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan)); | 1079 | print("mntchk 2: nil mux c %s c->mchan %s \n", chanpath(c), chanpath(c->mchan)); |
| 1161 | 1080 | ||
| 1162 | /* | 1081 | /* |
| 1163 | * Was it closed and reused (was error(Eshutdown); now, it can't happen) | 1082 | * Was it closed and reused (was error(Eshutdown); now, it cannot happen) |
| 1164 | */ | 1083 | */ |
| 1165 | if(m->id == 0 || m->id >= c->dev) | 1084 | if(m->id == 0 || m->id >= c->dev) |
| 1166 | panic("mntchk 3: can't happen"); | 1085 | panic("mntchk 3: can't happen"); |
| @@ -1173,7 +1092,7 @@ mntchk(Chan *c) · 6 unmodified lines | |||
| 1173 | * reflect local values. These entries are known to be | 1092 | * reflect local values. These entries are known to be |
| 1174 | * the first two in the Dir encoding after the count. | 1093 | * the first two in the Dir encoding after the count. |
| 1175 | */ | 1094 | */ |
| 1176 | void | 1095 | static void |
| 1177 | mntdirfix(uchar *dirbuf, Chan *c) | 1096 | mntdirfix(uchar *dirbuf, Chan *c) |
| 1178 | { | 1097 | { |
| 1179 | uint r; | 1098 | uint r; |
| @@ -1185,13 +1104,13 @@ mntdirfix(uchar *dirbuf, Chan *c) · 5 unmodified lines | |||
| 1185 | PBIT32(dirbuf, c->dev); | 1104 | PBIT32(dirbuf, c->dev); |
| 1186 | } | 1105 | } |
| 1187 | 1106 | ||
| 1188 | int | 1107 | static int |
| 1189 | rpcattn(void *v) | 1108 | rpcattn(void *v) |
| 1190 | { | 1109 | { |
| 1191 | Mntrpc *r; | 1110 | Mntrpc *r; |
| 1192 | 1111 | ||
| 1193 | r = v; | 1112 | r = v; |
| 1194 | return r->done || r->m->rip == 0; | 1113 | return r->done || r->m->rip == nil; |
| 1195 | } | 1114 | } |
| 1196 | 1115 | ||
| 1197 | Dev mntdevtab = { | 1116 | Dev mntdevtab = { |
| @@ -1201,7 +1120,7 @@ Dev mntdevtab = { · 3 unmodified lines | |||
| 1201 | mntreset, | 1120 | mntreset, |
| 1202 | devinit, | 1121 | devinit, |
| 1203 | devshutdown, | 1122 | devshutdown, |
| 1204 | mntattach, | 1123 | noattach, |
| 1205 | mntwalk, | 1124 | mntwalk, |
| 1206 | mntstat, | 1125 | mntstat, |
| 1207 | mntopen, | 1126 | mntopen, |
| @@ -10,7 +10,6 @@ Block* allocb(int); · 9 unmodified lines | |||
| 10 | int anyhigher(void); | 10 | int anyhigher(void); |
| 11 | int anyready(void); | 11 | int anyready(void); |
| 12 | Page* auxpage(void); | 12 | Page* auxpage(void); |
| 13 | Block* bl2mem(uchar*, Block*, int); | ||
| 14 | int blocklen(Block*); | 13 | int blocklen(Block*); |
| 15 | void callwithureg(void(*)(Ureg*)); | 14 | void callwithureg(void(*)(Ureg*)); |
| 16 | char* chanpath(Chan*); | 15 | char* chanpath(Chan*); |
| @@ -27,7 +26,6 @@ void chanfree(Chan*); · 10 unmodified lines | |||
| 27 | void chanrec(Mnt*); | 26 | void chanrec(Mnt*); |
| 28 | void checkalarms(void); | 27 | void checkalarms(void); |
| 29 | void checkb(Block*, char*); | 28 | void checkb(Block*, char*); |
| 30 | void cinit(void); | ||
| 31 | Chan* cclone(Chan*); | 29 | Chan* cclone(Chan*); |
| 32 | void cclose(Chan*); | 30 | void cclose(Chan*); |
| 33 | char* clipread(void); | 31 | char* clipread(void); |
| @@ -45,14 +43,10 @@ void confinit(void); · 11 unmodified lines | |||
| 45 | void confinit1(int); | 43 | void confinit1(int); |
| 46 | int consactive(void); | 44 | int consactive(void); |
| 47 | extern void (*consdebug)(void); | 45 | extern void (*consdebug)(void); |
| 48 | void copen(Chan*); | ||
| 49 | Block* concatblock(Block*); | 46 | Block* concatblock(Block*); |
| 50 | Block* copyblock(Block*, int); | 47 | Block* copyblock(Block*, int); |
| 51 | void copypage(Page*, Page*); | 48 | void copypage(Page*, Page*); |
| 52 | int cread(Chan*, uchar*, int, vlong); | ||
| 53 | void cunmount(Chan*, Chan*); | 49 | void cunmount(Chan*, Chan*); |
| 54 | void cupdate(Chan*, uchar*, int, vlong); | ||
| 55 | void cwrite(Chan*, uchar*, int, vlong); | ||
| 56 | ulong dbgpc(Proc*); | 50 | ulong dbgpc(Proc*); |
| 57 | int decref(Ref*); | 51 | int decref(Ref*); |
| 58 | int decrypt(void*, void*, int); | 52 | int decrypt(void*, void*, int); |
| @@ -119,7 +113,6 @@ long hostownerwrite(char*, int); · 60 unmodified lines | |||
| 119 | void hzsched(void); | 113 | void hzsched(void); |
| 120 | void iallocinit(void); | 114 | void iallocinit(void); |
| 121 | Block* iallocb(int); | 115 | Block* iallocb(int); |
| 122 | void iallocsummary(void); | ||
| 123 | long ibrk(ulong, int); | 116 | long ibrk(ulong, int); |
| 124 | void ilock(Lock*); | 117 | void ilock(Lock*); |
| 125 | void iunlock(Lock*); | 118 | void iunlock(Lock*); |
| @@ -161,8 +154,6 @@ void machinit(void); · 35 unmodified lines | |||
| 161 | void* mallocz(ulong, int); | 154 | void* mallocz(ulong, int); |
| 162 | #define malloc kmalloc | 155 | #define malloc kmalloc |
| 163 | void* malloc(ulong); | 156 | void* malloc(ulong); |
| 164 | void mallocsummary(void); | ||
| 165 | Block* mem2bl(uchar*, int); | ||
| 166 | void mfreeseg(Segment*, ulong, int); | 157 | void mfreeseg(Segment*, ulong, int); |
| 167 | void microdelay(int); | 158 | void microdelay(int); |
| 168 | void mkqid(Qid*, vlong, ulong, int); | 159 | void mkqid(Qid*, vlong, ulong, int); |
| @@ -238,7 +229,8 @@ void putstrn(char*, int); · 69 unmodified lines | |||
| 238 | void putswap(Page*); | 229 | void putswap(Page*); |
| 239 | ulong pwait(Waitmsg*); | 230 | ulong pwait(Waitmsg*); |
| 240 | Label* pwaserror(void); | 231 | Label* pwaserror(void); |
| 241 | void qaddlist(Queue*, Block*); | 232 | long readblist(Block*, uchar *, long, long); |
| 233 | int qaddlist(Queue*, Block*); | ||
| 242 | Block* qbread(Queue*, int); | 234 | Block* qbread(Queue*, int); |
| 243 | long qbwrite(Queue*, Block*); | 235 | long qbwrite(Queue*, Block*); |
| 244 | Queue* qbypass(void (*)(void*, Block*), void*); | 236 | Queue* qbypass(void (*)(void*, Block*), void*); |
| @@ -10,18 +10,17 @@ static ulong pullupblockcnt; · 9 unmodified lines | |||
| 10 | static ulong copyblockcnt; | 10 | static ulong copyblockcnt; |
| 11 | static ulong consumecnt; | 11 | static ulong consumecnt; |
| 12 | static ulong producecnt; | 12 | static ulong producecnt; |
| 13 | static ulong qcopycnt; | ||
| 14 | |||
| 15 | static int debugging; | ||
| 16 | 13 | ||
| 17 | #define QDEBUG if(0) | 14 | #define QDEBUG if(0) |
| 18 | 15 | ||
| 19 | /* | 16 | /* |
| 20 | * IO queues | 17 | * IO queues |
| 21 | */ | 18 | */ |
| 19 | typedef struct Queue Queue; | ||
| 20 | |||
| 22 | struct Queue | 21 | struct Queue |
| 23 | { | 22 | { |
| 24 | Lock lk; | 23 | Lock lk; |
| 25 | 24 | ||
| 26 | Block* bfirst; /* buffer */ | 25 | Block* bfirst; /* buffer */ |
| 27 | Block* blast; | 26 | Block* blast; |
| @@ -53,17 +52,6 @@ enum · 25 unmodified lines | |||
| 53 | 52 | ||
| 54 | uint qiomaxatomic = Maxatomic; | 53 | uint qiomaxatomic = Maxatomic; |
| 55 | 54 | ||
| 56 | void | ||
| 57 | ixsummary(void) | ||
| 58 | { | ||
| 59 | debugging ^= 1; | ||
| 60 | iallocsummary(); | ||
| 61 | print("pad %lud, concat %lud, pullup %lud, copy %lud\n", | ||
| 62 | padblockcnt, concatblockcnt, pullupblockcnt, copyblockcnt); | ||
| 63 | print("consume %lud, produce %lud, qcopy %lud\n", | ||
| 64 | consumecnt, producecnt, qcopycnt); | ||
| 65 | } | ||
| 66 | |||
| 67 | /* | 55 | /* |
| 68 | * free a list of blocks | 56 | * free a list of blocks |
| 69 | */ | 57 | */ |
| @@ -72,9 +60,9 @@ freeblist(Block *b) · 2 unmodified lines | |||
| 72 | { | 60 | { |
| 73 | Block *next; | 61 | Block *next; |
| 74 | 62 | ||
| 75 | for(; b != 0; b = next){ | 63 | for(; b != nil; b = next){ |
| 76 | next = b->next; | 64 | next = b->next; |
| 77 | b->next = 0; | 65 | b->next = nil; |
| 78 | freeb(b); | 66 | freeb(b); |
| 79 | } | 67 | } |
| 80 | } | 68 | } |
| @@ -88,40 +76,31 @@ padblock(Block *bp, int size) · 7 unmodified lines | |||
| 88 | int n; | 76 | int n; |
| 89 | Block *nbp; | 77 | Block *nbp; |
| 90 | 78 | ||
| 91 | QDEBUG checkb(bp, "padblock 1"); | 79 | QDEBUG checkb(bp, "padblock 0"); |
| 92 | if(size >= 0){ | 80 | if(size >= 0){ |
| 93 | if(bp->rp - bp->base >= size){ | 81 | if(bp->rp - bp->base >= size){ |
| 94 | bp->rp -= size; | 82 | bp->rp -= size; |
| 95 | return bp; | 83 | return bp; |
| 96 | } | 84 | } |
| 97 | |||
| 98 | if(bp->next) | ||
| 99 | panic("padblock 0x%p", getcallerpc(&bp)); | ||
| 100 | n = BLEN(bp); | 85 | n = BLEN(bp); |
| 101 | padblockcnt++; | ||
| 102 | nbp = allocb(size+n); | 86 | nbp = allocb(size+n); |
| 103 | nbp->rp += size; | 87 | nbp->rp += size; |
| 104 | nbp->wp = nbp->rp; | 88 | nbp->wp = nbp->rp; |
| 105 | memmove(nbp->wp, bp->rp, n); | 89 | memmove(nbp->wp, bp->rp, n); |
| 106 | nbp->wp += n; | 90 | nbp->wp += n; |
| 107 | freeb(bp); | ||
| 108 | nbp->rp -= size; | 91 | nbp->rp -= size; |
| 109 | } else { | 92 | } else { |
| 110 | size = -size; | 93 | size = -size; |
| 111 | |||
| 112 | if(bp->next) | ||
| 113 | panic("padblock 0x%p", getcallerpc(&bp)); | ||
| 114 | |||
| 115 | if(bp->lim - bp->wp >= size) | 94 | if(bp->lim - bp->wp >= size) |
| 116 | return bp; | 95 | return bp; |
| 117 | |||
| 118 | n = BLEN(bp); | 96 | n = BLEN(bp); |
| 119 | padblockcnt++; | 97 | nbp = allocb(n+size); |
| 120 | nbp = allocb(size+n); | ||
| 121 | memmove(nbp->wp, bp->rp, n); | 98 | memmove(nbp->wp, bp->rp, n); |
| 122 | nbp->wp += n; | 99 | nbp->wp += n; |
| 123 | freeb(bp); | ||
| 124 | } | 100 | } |
| 101 | nbp->next = bp->next; | ||
| 102 | freeb(bp); | ||
| 103 | padblockcnt++; | ||
| 125 | QDEBUG checkb(nbp, "padblock 1"); | 104 | QDEBUG checkb(nbp, "padblock 1"); |
| 126 | return nbp; | 105 | return nbp; |
| 127 | } | 106 | } |
| @@ -135,7 +114,7 @@ blocklen(Block *bp) · 7 unmodified lines | |||
| 135 | int len; | 114 | int len; |
| 136 | 115 | ||
| 137 | len = 0; | 116 | len = 0; |
| 138 | while(bp) { | 117 | while(bp != nil) { |
| 139 | len += BLEN(bp); | 118 | len += BLEN(bp); |
| 140 | bp = bp->next; | 119 | bp = bp->next; |
| 141 | } | 120 | } |
| @@ -151,7 +130,7 @@ blockalloclen(Block *bp) · 9 unmodified lines | |||
| 151 | int len; | 130 | int len; |
| 152 | 131 | ||
| 153 | len = 0; | 132 | len = 0; |
| 154 | while(bp) { | 133 | while(bp != nil) { |
| 155 | len += BALLOC(bp); | 134 | len += BALLOC(bp); |
| 156 | bp = bp->next; | 135 | bp = bp->next; |
| 157 | } | 136 | } |
| @@ -159,28 +138,19 @@ blockalloclen(Block *bp) · 1 unmodified line | |||
| 159 | } | 138 | } |
| 160 | 139 | ||
| 161 | /* | 140 | /* |
| 162 | * copy the string of blocks into | 141 | * copy the string of blocks into |
| 163 | * a single block and free the string | 142 | * a single block and free the string |
| 164 | */ | 143 | */ |
| 165 | Block* | 144 | Block* |
| 166 | concatblock(Block *bp) | 145 | concatblock(Block *bp) |
| 167 | { | 146 | { |
| 168 | int len; | 147 | int len; |
| 169 | Block *nb, *f; | ||
| 170 | 148 | ||
| 171 | if(bp->next == 0) | 149 | if(bp->next == nil) |
| 172 | return bp; | 150 | return bp; |
| 173 | 151 | len = blocklen(bp); | |
| 174 | nb = allocb(blocklen(bp)); | 152 | concatblockcnt += len; |
| 175 | for(f = bp; f; f = f->next) { | 153 | return pullupblock(bp, len); |
| 176 | len = BLEN(f); | ||
| 177 | memmove(nb->wp, f->rp, len); | ||
| 178 | nb->wp += len; | ||
| 179 | } | ||
| 180 | concatblockcnt += BLEN(nb); | ||
| 181 | freeblist(bp); | ||
| 182 | QDEBUG checkb(nb, "concatblock 1"); | ||
| 183 | return nb; | ||
| 184 | } | 154 | } |
| 185 | 155 | ||
| 186 | /* | 156 | /* |
| @@ -189,8 +159,8 @@ concatblock(Block *bp) · 2 unmodified lines | |||
| 189 | Block* | 159 | Block* |
| 190 | pullupblock(Block *bp, int n) | 160 | pullupblock(Block *bp, int n) |
| 191 | { | 161 | { |
| 192 | int i; | ||
| 193 | Block *nbp; | 162 | Block *nbp; |
| 163 | int i; | ||
| 194 | 164 | ||
| 195 | /* | 165 | /* |
| 196 | * this should almost always be true, it's | 166 | * this should almost always be true, it's |
| @@ -213,11 +183,11 @@ pullupblock(Block *bp, int n) · 16 unmodified lines | |||
| 213 | * copy bytes from the trailing blocks into the first | 183 | * copy bytes from the trailing blocks into the first |
| 214 | */ | 184 | */ |
| 215 | n -= BLEN(bp); | 185 | n -= BLEN(bp); |
| 216 | while((nbp = bp->next)){ | 186 | while((nbp = bp->next) != nil){ |
| 187 | pullupblockcnt++; | ||
| 217 | i = BLEN(nbp); | 188 | i = BLEN(nbp); |
| 218 | if(i > n) { | 189 | if(i > n) { |
| 219 | memmove(bp->wp, nbp->rp, n); | 190 | memmove(bp->wp, nbp->rp, n); |
| 220 | pullupblockcnt++; | ||
| 221 | bp->wp += n; | 191 | bp->wp += n; |
| 222 | nbp->rp += n; | 192 | nbp->rp += n; |
| 223 | QDEBUG checkb(bp, "pullupblock 1"); | 193 | QDEBUG checkb(bp, "pullupblock 1"); |
| @@ -225,14 +195,14 @@ pullupblock(Block *bp, int n) · 1 unmodified line | |||
| 225 | } else { | 195 | } else { |
| 226 | /* shouldn't happen but why crash if it does */ | 196 | /* shouldn't happen but why crash if it does */ |
| 227 | if(i < 0){ | 197 | if(i < 0){ |
| 228 | print("pullup negative length packet\n"); | 198 | print("pullup negative length packet, called from %#p\n", |
| 199 | getcallerpc(&bp)); | ||
| 229 | i = 0; | 200 | i = 0; |
| 230 | } | 201 | } |
| 231 | memmove(bp->wp, nbp->rp, i); | 202 | memmove(bp->wp, nbp->rp, i); |
| 232 | pullupblockcnt++; | ||
| 233 | bp->wp += i; | 203 | bp->wp += i; |
| 234 | bp->next = nbp->next; | 204 | bp->next = nbp->next; |
| 235 | nbp->next = 0; | 205 | nbp->next = nil; |
| 236 | freeb(nbp); | 206 | freeb(nbp); |
| 237 | n -= i; | 207 | n -= i; |
| 238 | if(n == 0){ | 208 | if(n == 0){ |
| @@ -242,7 +212,7 @@ pullupblock(Block *bp, int n) · 3 unmodified lines | |||
| 242 | } | 212 | } |
| 243 | } | 213 | } |
| 244 | freeb(bp); | 214 | freeb(bp); |
| 245 | return 0; | 215 | return nil; |
| 246 | } | 216 | } |
| 247 | 217 | ||
| 248 | /* | 218 | /* |
| @@ -295,7 +265,7 @@ trimblock(Block *bp, int offset, int len) · 46 unmodified lines | |||
| 295 | 265 | ||
| 296 | bp->wp -= (BLEN(bp) - len); | 266 | bp->wp -= (BLEN(bp) - len); |
| 297 | 267 | ||
| 298 | if(bp->next) { | 268 | if(bp->next != nil) { |
| 299 | freeblist(bp->next); | 269 | freeblist(bp->next); |
| 300 | bp->next = nil; | 270 | bp->next = nil; |
| 301 | } | 271 | } |
| @@ -314,7 +284,7 @@ copyblock(Block *bp, int count) · 12 unmodified lines | |||
| 314 | 284 | ||
| 315 | QDEBUG checkb(bp, "copyblock 0"); | 285 | QDEBUG checkb(bp, "copyblock 0"); |
| 316 | nbp = allocb(count); | 286 | nbp = allocb(count); |
| 317 | for(; count > 0 && bp != 0; bp = bp->next){ | 287 | for(; count > 0 && bp != nil; bp = bp->next){ |
| 318 | l = BLEN(bp); | 288 | l = BLEN(bp); |
| 319 | if(l > count) | 289 | if(l > count) |
| 320 | l = count; | 290 | l = count; |
| @@ -412,11 +382,11 @@ qget(Queue *q) · 91 unmodified lines | |||
| 412 | iunlock(&q->lk); | 382 | iunlock(&q->lk); |
| 413 | return nil; | 383 | return nil; |
| 414 | } | 384 | } |
| 385 | QDEBUG checkb(b, "qget"); | ||
| 415 | q->bfirst = b->next; | 386 | q->bfirst = b->next; |
| 416 | b->next = 0; | 387 | b->next = nil; |
| 417 | q->len -= BALLOC(b); | 388 | q->len -= BALLOC(b); |
| 418 | q->dlen -= BLEN(b); | 389 | q->dlen -= BLEN(b); |
| 419 | QDEBUG checkb(b, "qget"); | ||
| 420 | 390 | ||
| 421 | /* if writer flow controlled, restart */ | 391 | /* if writer flow controlled, restart */ |
| 422 | if((q->state & Qflow) && q->len < q->limit/2){ | 392 | if((q->state & Qflow) && q->len < q->limit/2){ |
| @@ -439,7 +409,7 @@ qget(Queue *q) · 16 unmodified lines | |||
| 439 | int | 409 | int |
| 440 | qdiscard(Queue *q, int len) | 410 | qdiscard(Queue *q, int len) |
| 441 | { | 411 | { |
| 442 | Block *b; | 412 | Block *b, *tofree = nil; |
| 443 | int dowakeup, n, sofar; | 413 | int dowakeup, n, sofar; |
| 444 | 414 | ||
| 445 | ilock(&q->lk); | 415 | ilock(&q->lk); |
| @@ -451,10 +421,12 @@ qdiscard(Queue *q, int len) · 5 unmodified lines | |||
| 451 | n = BLEN(b); | 421 | n = BLEN(b); |
| 452 | if(n <= len - sofar){ | 422 | if(n <= len - sofar){ |
| 453 | q->bfirst = b->next; | 423 | q->bfirst = b->next; |
| 454 | b->next = 0; | ||
| 455 | q->len -= BALLOC(b); | 424 | q->len -= BALLOC(b); |
| 456 | q->dlen -= BLEN(b); | 425 | q->dlen -= BLEN(b); |
| 457 | freeb(b); | 426 | |
| 427 | /* remember to free this */ | ||
| 428 | b->next = tofree; | ||
| 429 | tofree = b; | ||
| 458 | } else { | 430 | } else { |
| 459 | n = len - sofar; | 431 | n = len - sofar; |
| 460 | b->rp += n; | 432 | b->rp += n; |
| @@ -483,6 +455,9 @@ qdiscard(Queue *q, int len) · 22 unmodified lines | |||
| 483 | if(dowakeup) | 455 | if(dowakeup) |
| 484 | wakeup(&q->wr); | 456 | wakeup(&q->wr); |
| 485 | 457 | ||
| 458 | if(tofree != nil) | ||
| 459 | freeblist(tofree); | ||
| 460 | |||
| 486 | return sofar; | 461 | return sofar; |
| 487 | } | 462 | } |
| 488 | 463 | ||
| @@ -492,20 +467,19 @@ qdiscard(Queue *q, int len) · 3 unmodified lines | |||
| 492 | int | 467 | int |
| 493 | qconsume(Queue *q, void *vp, int len) | 468 | qconsume(Queue *q, void *vp, int len) |
| 494 | { | 469 | { |
| 495 | Block *b; | 470 | Block *b, *tofree = nil; |
| 496 | int n, dowakeup; | 471 | int n, dowakeup; |
| 497 | uchar *p = vp; | 472 | uchar *p = vp; |
| 498 | Block *tofree = nil; | ||
| 499 | 473 | ||
| 500 | /* sync with qwrite */ | 474 | /* sync with qwrite */ |
| 501 | ilock(&q->lk); | 475 | ilock(&q->lk); |
| 502 | 476 | ||
| 503 | for(;;) { | 477 | for(;;) { |
| 504 | b = q->bfirst; | 478 | b = q->bfirst; |
| 505 | if(b == 0){ | 479 | if(b == nil){ |
| 506 | q->state |= Qstarve; | 480 | q->state |= Qstarve; |
| 507 | iunlock(&q->lk); | 481 | len = -1; |
| 508 | return -1; | 482 | goto out; |
| 509 | } | 483 | } |
| 510 | QDEBUG checkb(b, "qconsume 1"); | 484 | QDEBUG checkb(b, "qconsume 1"); |
| 511 | 485 | ||
| @@ -520,17 +494,16 @@ qconsume(Queue *q, void *vp, int len) · 8 unmodified lines | |||
| 520 | tofree = b; | 494 | tofree = b; |
| 521 | }; | 495 | }; |
| 522 | 496 | ||
| 497 | consumecnt += n; | ||
| 523 | if(n < len) | 498 | if(n < len) |
| 524 | len = n; | 499 | len = n; |
| 525 | memmove(p, b->rp, len); | 500 | memmove(p, b->rp, len); |
| 526 | consumecnt += n; | ||
| 527 | b->rp += len; | 501 | b->rp += len; |
| 528 | q->dlen -= len; | 502 | q->dlen -= len; |
| 529 | 503 | ||
| 530 | /* discard the block if we're done with it */ | 504 | /* discard the block if we're done with it */ |
| 531 | if((q->state & Qmsg) || len == n){ | 505 | if((q->state & Qmsg) || len == n){ |
| 532 | q->bfirst = b->next; | 506 | q->bfirst = b->next; |
| 533 | b->next = 0; | ||
| 534 | q->len -= BALLOC(b); | 507 | q->len -= BALLOC(b); |
| 535 | q->dlen -= BLEN(b); | 508 | q->dlen -= BLEN(b); |
| 536 | 509 | ||
| @@ -539,6 +512,7 @@ qconsume(Queue *q, void *vp, int len) · 2 unmodified lines | |||
| 539 | tofree = b; | 512 | tofree = b; |
| 540 | } | 513 | } |
| 541 | 514 | ||
| 515 | out: | ||
| 542 | /* if writer flow controlled, restart */ | 516 | /* if writer flow controlled, restart */ |
| 543 | if((q->state & Qflow) && q->len < q->limit/2){ | 517 | if((q->state & Qflow) && q->len < q->limit/2){ |
| 544 | q->state &= ~Qflow; | 518 | q->state &= ~Qflow; |
| @@ -560,39 +534,23 @@ qconsume(Queue *q, void *vp, int len) · 15 unmodified lines | |||
| 560 | int | 534 | int |
| 561 | qpass(Queue *q, Block *b) | 535 | qpass(Queue *q, Block *b) |
| 562 | { | 536 | { |
| 563 | int dlen, len, dowakeup; | 537 | int len, dowakeup; |
| 564 | 538 | ||
| 565 | /* sync with qread */ | 539 | /* sync with qread */ |
| 566 | dowakeup = 0; | 540 | dowakeup = 0; |
| 567 | ilock(&q->lk); | 541 | ilock(&q->lk); |
| 568 | if(q->len >= q->limit){ | 542 | if(q->len >= q->limit){ |
| 569 | freeblist(b); | ||
| 570 | iunlock(&q->lk); | 543 | iunlock(&q->lk); |
| 544 | freeblist(b); | ||
| 571 | return -1; | 545 | return -1; |
| 572 | } | 546 | } |
| 573 | if(q->state & Qclosed){ | 547 | if(q->state & Qclosed){ |
| 574 | freeblist(b); | ||
| 575 | iunlock(&q->lk); | 548 | iunlock(&q->lk); |
| 576 | return BALLOC(b); | 549 | freeblist(b); |
| 550 | return 0; | ||
| 577 | } | 551 | } |
| 578 | 552 | ||
| 579 | /* add buffer to queue */ | 553 | len = qaddlist(q, b); |
| 580 | if(q->bfirst) | ||
| 581 | q->blast->next = b; | ||
| 582 | else | ||
| 583 | q->bfirst = b; | ||
| 584 | len = BALLOC(b); | ||
| 585 | dlen = BLEN(b); | ||
| 586 | QDEBUG checkb(b, "qpass"); | ||
| 587 | while(b->next){ | ||
| 588 | b = b->next; | ||
| 589 | QDEBUG checkb(b, "qpass"); | ||
| 590 | len += BALLOC(b); | ||
| 591 | dlen += BLEN(b); | ||
| 592 | } | ||
| 593 | q->blast = b; | ||
| 594 | q->len += len; | ||
| 595 | q->dlen += dlen; | ||
| 596 | 554 | ||
| 597 | if(q->len >= q->limit/2) | 555 | if(q->len >= q->limit/2) |
| 598 | q->state |= Qflow; | 556 | q->state |= Qflow; |
| @@ -612,35 +570,19 @@ qpass(Queue *q, Block *b) · 13 unmodified lines | |||
| 612 | int | 570 | int |
| 613 | qpassnolim(Queue *q, Block *b) | 571 | qpassnolim(Queue *q, Block *b) |
| 614 | { | 572 | { |
| 615 | int dlen, len, dowakeup; | 573 | int len, dowakeup; |
| 616 | 574 | ||
| 617 | /* sync with qread */ | 575 | /* sync with qread */ |
| 618 | dowakeup = 0; | 576 | dowakeup = 0; |
| 619 | ilock(&q->lk); | 577 | ilock(&q->lk); |
| 620 | 578 | ||
| 621 | if(q->state & Qclosed){ | 579 | if(q->state & Qclosed){ |
| 622 | freeblist(b); | ||
| 623 | iunlock(&q->lk); | 580 | iunlock(&q->lk); |
| 624 | return BALLOC(b); | 581 | freeblist(b); |
| 582 | return 0; | ||
| 625 | } | 583 | } |
| 626 | 584 | ||
| 627 | /* add buffer to queue */ | 585 | len = qaddlist(q, b); |
| 628 | if(q->bfirst) | ||
| 629 | q->blast->next = b; | ||
| 630 | else | ||
| 631 | q->bfirst = b; | ||
| 632 | len = BALLOC(b); | ||
| 633 | dlen = BLEN(b); | ||
| 634 | QDEBUG checkb(b, "qpass"); | ||
| 635 | while(b->next){ | ||
| 636 | b = b->next; | ||
| 637 | QDEBUG checkb(b, "qpass"); | ||
| 638 | len += BALLOC(b); | ||
| 639 | dlen += BLEN(b); | ||
| 640 | } | ||
| 641 | q->blast = b; | ||
| 642 | q->len += len; | ||
| 643 | q->dlen += dlen; | ||
| 644 | 586 | ||
| 645 | if(q->len >= q->limit/2) | 587 | if(q->len >= q->limit/2) |
| 646 | q->state |= Qflow; | 588 | q->state |= Qflow; |
| @@ -667,8 +609,7 @@ packblock(Block *bp) · 20 unmodified lines | |||
| 667 | Block **l, *nbp; | 609 | Block **l, *nbp; |
| 668 | int n; | 610 | int n; |
| 669 | 611 | ||
| 670 | for(l = &bp; *l; l = &(*l)->next){ | 612 | for(l = &bp; (nbp = *l) != nil; l = &(*l)->next){ |
| 671 | nbp = *l; | ||
| 672 | n = BLEN(nbp); | 613 | n = BLEN(nbp); |
| 673 | if((n<<2) < BALLOC(nbp)){ | 614 | if((n<<2) < BALLOC(nbp)){ |
| 674 | *l = allocb(n); | 615 | *l = allocb(n); |
| @@ -689,6 +630,10 @@ qproduce(Queue *q, void *vp, int len) · 14 unmodified lines | |||
| 689 | int dowakeup; | 630 | int dowakeup; |
| 690 | uchar *p = vp; | 631 | uchar *p = vp; |
| 691 | 632 | ||
| 633 | b = iallocb(len); | ||
| 634 | if(b == nil) | ||
| 635 | return 0; | ||
| 636 | |||
| 692 | /* sync with qread */ | 637 | /* sync with qread */ |
| 693 | dowakeup = 0; | 638 | dowakeup = 0; |
| 694 | ilock(&q->lk); | 639 | ilock(&q->lk); |
| @@ -699,25 +644,12 @@ qproduce(Queue *q, void *vp, int len) · 4 unmodified lines | |||
| 699 | iunlock(&q->lk); | 644 | iunlock(&q->lk); |
| 700 | return -1; | 645 | return -1; |
| 701 | } | 646 | } |
| 647 | producecnt += len; | ||
| 702 | 648 | ||
| 703 | /* save in buffer */ | 649 | /* save in buffer */ |
| 704 | b = iallocb(len); | ||
| 705 | if(b == 0){ | ||
| 706 | iunlock(&q->lk); | ||
| 707 | return 0; | ||
| 708 | } | ||
| 709 | memmove(b->wp, p, len); | 650 | memmove(b->wp, p, len); |
| 710 | producecnt += len; | ||
| 711 | b->wp += len; | 651 | b->wp += len; |
| 712 | if(q->bfirst) | 652 | qaddlist(q, b); |
| 713 | q->blast->next = b; | ||
| 714 | else | ||
| 715 | q->bfirst = b; | ||
| 716 | q->blast = b; | ||
| 717 | /* b->next = 0; done by iallocb() */ | ||
| 718 | q->len += BALLOC(b); | ||
| 719 | q->dlen += BLEN(b); | ||
| 720 | QDEBUG checkb(b, "qproduce"); | ||
| 721 | 653 | ||
| 722 | if(q->state & Qstarve){ | 654 | if(q->state & Qstarve){ |
| 723 | q->state &= ~Qstarve; | 655 | q->state &= ~Qstarve; |
| @@ -740,49 +672,13 @@ qproduce(Queue *q, void *vp, int len) · 16 unmodified lines | |||
| 740 | Block* | 672 | Block* |
| 741 | qcopy(Queue *q, int len, ulong offset) | 673 | qcopy(Queue *q, int len, ulong offset) |
| 742 | { | 674 | { |
| 743 | int sofar; | 675 | Block *b; |
| 744 | int n; | ||
| 745 | Block *b, *nb; | ||
| 746 | uchar *p; | ||
| 747 | |||
| 748 | nb = allocb(len); | ||
| 749 | 676 | ||
| 677 | b = allocb(len); | ||
| 750 | ilock(&q->lk); | 678 | ilock(&q->lk); |
| 751 | 679 | b->wp += readblist(q->bfirst, b->wp, len, offset); | |
| 752 | /* go to offset */ | ||
| 753 | b = q->bfirst; | ||
| 754 | for(sofar = 0; ; sofar += n){ | ||
| 755 | if(b == nil){ | ||
| 756 | iunlock(&q->lk); | ||
| 757 | return nb; | ||
| 758 | } | ||
| 759 | n = BLEN(b); | ||
| 760 | if(sofar + n > offset){ | ||
| 761 | p = b->rp + offset - sofar; | ||
| 762 | n -= offset - sofar; | ||
| 763 | break; | ||
| 764 | } | ||
| 765 | QDEBUG checkb(b, "qcopy"); | ||
| 766 | b = b->next; | ||
| 767 | } | ||
| 768 | |||
| 769 | /* copy bytes from there */ | ||
| 770 | for(sofar = 0; sofar < len;){ | ||
| 771 | if(n > len - sofar) | ||
| 772 | n = len - sofar; | ||
| 773 | memmove(nb->wp, p, n); | ||
| 774 | qcopycnt += n; | ||
| 775 | sofar += n; | ||
| 776 | nb->wp += n; | ||
| 777 | b = b->next; | ||
| 778 | if(b == nil) | ||
| 779 | break; | ||
| 780 | n = BLEN(b); | ||
| 781 | p = b->rp; | ||
| 782 | } | ||
| 783 | iunlock(&q->lk); | 680 | iunlock(&q->lk); |
| 784 | 681 | return b; | |
| 785 | return nb; | ||
| 786 | } | 682 | } |
| 787 | 683 | ||
| 788 | /* | 684 | /* |
| @@ -794,8 +690,8 @@ qopen(int limit, int msg, void (*kick)(void*), void *arg) · 5 unmodified lines | |||
| 794 | Queue *q; | 690 | Queue *q; |
| 795 | 691 | ||
| 796 | q = malloc(sizeof(Queue)); | 692 | q = malloc(sizeof(Queue)); |
| 797 | if(q == 0) | 693 | if(q == nil) |
| 798 | return 0; | 694 | return nil; |
| 799 | 695 | ||
| 800 | q->limit = q->inilim = limit; | 696 | q->limit = q->inilim = limit; |
| 801 | q->kick = kick; | 697 | q->kick = kick; |
| @@ -816,8 +712,8 @@ qbypass(void (*bypass)(void*, Block*), void *arg) · 14 unmodified lines | |||
| 816 | Queue *q; | 712 | Queue *q; |
| 817 | 713 | ||
| 818 | q = malloc(sizeof(Queue)); | 714 | q = malloc(sizeof(Queue)); |
| 819 | if(q == 0) | 715 | if(q == nil) |
| 820 | return 0; | 716 | return nil; |
| 821 | 717 | ||
| 822 | q->limit = 0; | 718 | q->limit = 0; |
| 823 | q->arg = arg; | 719 | q->arg = arg; |
| @@ -832,7 +728,7 @@ notempty(void *a) · 8 unmodified lines | |||
| 832 | { | 728 | { |
| 833 | Queue *q = a; | 729 | Queue *q = a; |
| 834 | 730 | ||
| 835 | return (q->state & Qclosed) || q->bfirst != 0; | 731 | return (q->state & Qclosed) || q->bfirst != nil; |
| 836 | } | 732 | } |
| 837 | 733 | ||
| 838 | /* | 734 | /* |
| @@ -864,21 +760,34 @@ qwait(Queue *q) · 25 unmodified lines | |||
| 864 | } | 760 | } |
| 865 | 761 | ||
| 866 | /* | 762 | /* |
| 867 | * add a block list to a queue | 763 | * add a block list to a queue, return bytes added |
| 868 | */ | 764 | */ |
| 869 | void | 765 | int |
| 870 | qaddlist(Queue *q, Block *b) | 766 | qaddlist(Queue *q, Block *b) |
| 871 | { | 767 | { |
| 768 | int len, dlen; | ||
| 769 | |||
| 770 | QDEBUG checkb(b, "qaddlist 1"); | ||
| 771 | |||
| 872 | /* queue the block */ | 772 | /* queue the block */ |
| 873 | if(q->bfirst) | 773 | if(q->bfirst != nil) |
| 874 | q->blast->next = b; | 774 | q->blast->next = b; |
| 875 | else | 775 | else |
| 876 | q->bfirst = b; | 776 | q->bfirst = b; |
| 877 | q->len += blockalloclen(b); | 777 | |
| 878 | q->dlen += blocklen(b); | 778 | len = BALLOC(b); |
| 879 | while(b->next) | 779 | dlen = BLEN(b); |
| 780 | while(b->next != nil){ | ||
| 880 | b = b->next; | 781 | b = b->next; |
| 782 | QDEBUG checkb(b, "qaddlist 2"); | ||
| 783 | |||
| 784 | len += BALLOC(b); | ||
| 785 | dlen += BLEN(b); | ||
| 786 | } | ||
| 881 | q->blast = b; | 787 | q->blast = b; |
| 788 | q->len += len; | ||
| 789 | q->dlen += dlen; | ||
| 790 | return dlen; | ||
| 882 | } | 791 | } |
| 883 | 792 | ||
| 884 | /* | 793 | /* |
| @@ -892,74 +801,42 @@ qremove(Queue *q) · 7 unmodified lines | |||
| 892 | b = q->bfirst; | 801 | b = q->bfirst; |
| 893 | if(b == nil) | 802 | if(b == nil) |
| 894 | return nil; | 803 | return nil; |
| 804 | QDEBUG checkb(b, "qremove"); | ||
| 895 | q->bfirst = b->next; | 805 | q->bfirst = b->next; |
| 896 | b->next = nil; | 806 | b->next = nil; |
| 897 | q->dlen -= BLEN(b); | 807 | q->dlen -= BLEN(b); |
| 898 | q->len -= BALLOC(b); | 808 | q->len -= BALLOC(b); |
| 899 | QDEBUG checkb(b, "qremove"); | ||
| 900 | return b; | 809 | return b; |
| 901 | } | 810 | } |
| 902 | 811 | ||
| 903 | /* | 812 | /* |
| 904 | * copy the contents of a string of blocks into | 813 | * copy the contents of a string of blocks into |
| 905 | * memory. emptied blocks are freed. return | 814 | * memory from an offset. blocklist kept unchanged. |
| 906 | * pointer to first unconsumed block. | 815 | * return number of copied bytes. |
| 907 | */ | 816 | */ |
| 908 | Block* | 817 | long |
| 909 | bl2mem(uchar *p, Block *b, int n) | 818 | readblist(Block *b, uchar *p, long n, long o) |
| 910 | { | 819 | { |
| 911 | int i; | 820 | long m, r; |
| 912 | Block *next; | ||
| 913 | 821 | ||
| 914 | for(; b != nil; b = next){ | 822 | r = 0; |
| 915 | i = BLEN(b); | 823 | while(n > 0 && b != nil){ |
| 916 | if(i > n){ | 824 | m = BLEN(b); |
| 917 | memmove(p, b->rp, n); | 825 | if(o >= m) |
| 918 | b->rp += n; | 826 | o -= m; |
| 919 | return b; | 827 | else { |
| 828 | m -= o; | ||
| 829 | if(n < m) | ||
| 830 | m = n; | ||
| 831 | memmove(p, b->rp + o, m); | ||
| 832 | p += m; | ||
| 833 | r += m; | ||
| 834 | n -= m; | ||
| 835 | o = 0; | ||
| 920 | } | 836 | } |
| 921 | memmove(p, b->rp, i); | 837 | b = b->next; |
| 922 | n -= i; | ||
| 923 | p += i; | ||
| 924 | b->rp += i; | ||
| 925 | next = b->next; | ||
| 926 | freeb(b); | ||
| 927 | } | ||
| 928 | return nil; | ||
| 929 | } | ||
| 930 | |||
| 931 | /* | ||
| 932 | * copy the contents of memory into a string of blocks. | ||
| 933 | * return nil on error. | ||
| 934 | */ | ||
| 935 | Block* | ||
| 936 | mem2bl(uchar *p, int len) | ||
| 937 | { | ||
| 938 | int n; | ||
| 939 | Block *b, *first, **l; | ||
| 940 | |||
| 941 | first = nil; | ||
| 942 | l = &first; | ||
| 943 | if(waserror()){ | ||
| 944 | freeblist(first); | ||
| 945 | nexterror(); | ||
| 946 | } | 838 | } |
| 947 | do { | 839 | return r; |
| 948 | n = len; | ||
| 949 | if(n > Maxatomic) | ||
| 950 | n = Maxatomic; | ||
| 951 | |||
| 952 | *l = b = allocb(n); | ||
| 953 | /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ | ||
| 954 | memmove(b->wp, p, n); | ||
| 955 | b->wp += n; | ||
| 956 | p += n; | ||
| 957 | len -= n; | ||
| 958 | l = &b->next; | ||
| 959 | } while(len > 0); | ||
| 960 | poperror(); | ||
| 961 | |||
| 962 | return first; | ||
| 963 | } | 840 | } |
| 964 | 841 | ||
| 965 | /* | 842 | /* |
| @@ -977,6 +854,35 @@ qputback(Queue *q, Block *b) · 11 unmodified lines | |||
| 977 | q->dlen += BLEN(b); | 854 | q->dlen += BLEN(b); |
| 978 | } | 855 | } |
| 979 | 856 | ||
| 857 | /* | ||
| 858 | * cut off n bytes from the end of *h. return a new | ||
| 859 | * block with the tail and change *h to refer to the | ||
| 860 | * head. | ||
| 861 | */ | ||
| 862 | static Block* | ||
| 863 | splitblock(Block **h, int n) | ||
| 864 | { | ||
| 865 | Block *a, *b; | ||
| 866 | int m; | ||
| 867 | |||
| 868 | a = *h; | ||
| 869 | m = BLEN(a) - n; | ||
| 870 | if(m < n){ | ||
| 871 | b = allocb(m); | ||
| 872 | memmove(b->wp, a->rp, m); | ||
| 873 | b->wp += m; | ||
| 874 | a->rp += m; | ||
| 875 | *h = b; | ||
| 876 | return a; | ||
| 877 | } else { | ||
| 878 | b = allocb(n); | ||
| 879 | a->wp -= n; | ||
| 880 | memmove(b->wp, a->wp, n); | ||
| 881 | b->wp += n; | ||
| 882 | return b; | ||
| 883 | } | ||
| 884 | } | ||
| 885 | |||
| 980 | /* | 886 | /* |
| 981 | * flow control, get producer going again | 887 | * flow control, get producer going again |
| 982 | * called with q ilocked | 888 | * called with q ilocked |
| @@ -996,7 +902,7 @@ qwakeup_iunlock(Queue *q) · 13 unmodified lines | |||
| 996 | 902 | ||
| 997 | /* wakeup flow controlled writers */ | 903 | /* wakeup flow controlled writers */ |
| 998 | if(dowakeup){ | 904 | if(dowakeup){ |
| 999 | if(q->kick) | 905 | if(q->kick != nil) |
| 1000 | q->kick(q->arg); | 906 | q->kick(q->arg); |
| 1001 | wakeup(&q->wr); | 907 | wakeup(&q->wr); |
| 1002 | } | 908 | } |
| @@ -1008,7 +914,7 @@ qwakeup_iunlock(Queue *q) · 5 unmodified lines | |||
| 1008 | Block* | 914 | Block* |
| 1009 | qbread(Queue *q, int len) | 915 | qbread(Queue *q, int len) |
| 1010 | { | 916 | { |
| 1011 | Block *b, *nb; | 917 | Block *b; |
| 1012 | int n; | 918 | int n; |
| 1013 | 919 | ||
| 1014 | qlock(&q->rlock); | 920 | qlock(&q->rlock); |
| @@ -1036,24 +942,21 @@ qbread(Queue *q, int len) · 21 unmodified lines | |||
| 1036 | n = BLEN(b); | 942 | n = BLEN(b); |
| 1037 | 943 | ||
| 1038 | /* split block if it's too big and this is not a message queue */ | 944 | /* split block if it's too big and this is not a message queue */ |
| 1039 | nb = b; | ||
| 1040 | if(n > len){ | 945 | if(n > len){ |
| 1041 | if((q->state&Qmsg) == 0){ | 946 | n -= len; |
| 1042 | n -= len; | 947 | if((q->state & Qmsg) == 0) |
| 1043 | b = allocb(n); | 948 | qputback(q, splitblock(&b, n)); |
| 1044 | memmove(b->wp, nb->rp+len, n); | 949 | else |
| 1045 | b->wp += n; | 950 | b->wp -= n; |
| 1046 | qputback(q, b); | ||
| 1047 | } | ||
| 1048 | nb->wp = nb->rp + len; | ||
| 1049 | } | 951 | } |
| 1050 | 952 | ||
| 1051 | /* restart producer */ | 953 | /* restart producer */ |
| 1052 | qwakeup_iunlock(q); | 954 | qwakeup_iunlock(q); |
| 1053 | 955 | ||
| 1054 | poperror(); | ||
| 1055 | qunlock(&q->rlock); | 956 | qunlock(&q->rlock); |
| 1056 | return nb; | 957 | poperror(); |
| 958 | |||
| 959 | return b; | ||
| 1057 | } | 960 | } |
| 1058 | 961 | ||
| 1059 | /* | 962 | /* |
| @@ -1063,7 +966,7 @@ qbread(Queue *q, int len) · 3 unmodified lines | |||
| 1063 | long | 966 | long |
| 1064 | qread(Queue *q, void *vp, int len) | 967 | qread(Queue *q, void *vp, int len) |
| 1065 | { | 968 | { |
| 1066 | Block *b, *first, **l; | 969 | Block *b, *first, **last; |
| 1067 | int m, n; | 970 | int m, n; |
| 1068 | 971 | ||
| 1069 | qlock(&q->rlock); | 972 | qlock(&q->rlock); |
| @@ -1088,57 +991,53 @@ again: · 18 unmodified lines | |||
| 1088 | } | 991 | } |
| 1089 | 992 | ||
| 1090 | /* if we get here, there's at least one block in the queue */ | 993 | /* if we get here, there's at least one block in the queue */ |
| 994 | last = &first; | ||
| 1091 | if(q->state & Qcoalesce){ | 995 | if(q->state & Qcoalesce){ |
| 1092 | /* when coalescing, 0 length blocks just go away */ | 996 | /* when coalescing, 0 length blocks just go away */ |
| 1093 | b = q->bfirst; | 997 | b = q->bfirst; |
| 1094 | if(BLEN(b) <= 0){ | 998 | m = BLEN(b); |
| 999 | if(m <= 0){ | ||
| 1095 | freeb(qremove(q)); | 1000 | freeb(qremove(q)); |
| 1096 | goto again; | 1001 | goto again; |
| 1097 | } | 1002 | } |
| 1098 | 1003 | ||
| 1099 | /* grab the first block plus as many | 1004 | /* grab the first block plus as many |
| 1100 | * following blocks as will completely | 1005 | * following blocks as will partially |
| 1101 | * fit in the read. | 1006 | * fit in the read. |
| 1102 | */ | 1007 | */ |
| 1103 | n = 0; | 1008 | n = 0; |
| 1104 | l = &first; | ||
| 1105 | m = BLEN(b); | ||
| 1106 | for(;;) { | 1009 | for(;;) { |
| 1107 | *l = qremove(q); | 1010 | *last = qremove(q); |
| 1108 | l = &b->next; | ||
| 1109 | n += m; | 1011 | n += m; |
| 1110 | 1012 | if(n >= len || q->bfirst == nil) | |
| 1111 | b = q->bfirst; | ||
| 1112 | if(b == nil) | ||
| 1113 | break; | 1013 | break; |
| 1014 | last = &b->next; | ||
| 1015 | b = q->bfirst; | ||
| 1114 | m = BLEN(b); | 1016 | m = BLEN(b); |
| 1115 | if(n+m > len) | ||
| 1116 | break; | ||
| 1117 | } | 1017 | } |
| 1118 | } else { | 1018 | } else { |
| 1119 | first = qremove(q); | 1019 | first = qremove(q); |
| 1120 | n = BLEN(first); | 1020 | n = BLEN(first); |
| 1121 | } | 1021 | } |
| 1122 | 1022 | ||
| 1123 | /* copy to user space outside of the ilock */ | 1023 | /* split last block if it's too big and this is not a message queue */ |
| 1124 | iunlock(&q->lk); | 1024 | if(n > len && (q->state & Qmsg) == 0) |
| 1125 | b = bl2mem(vp, first, len); | 1025 | qputback(q, splitblock(last, n - len)); |
| 1126 | ilock(&q->lk); | ||
| 1127 | |||
| 1128 | /* take care of any left over partial block */ | ||
| 1129 | if(b != nil){ | ||
| 1130 | n -= BLEN(b); | ||
| 1131 | if(q->state & Qmsg) | ||
| 1132 | freeb(b); | ||
| 1133 | else | ||
| 1134 | qputback(q, b); | ||
| 1135 | } | ||
| 1136 | 1026 | ||
| 1137 | /* restart producer */ | 1027 | /* restart producer */ |
| 1138 | qwakeup_iunlock(q); | 1028 | qwakeup_iunlock(q); |
| 1139 | 1029 | ||
| 1140 | poperror(); | ||
| 1141 | qunlock(&q->rlock); | 1030 | qunlock(&q->rlock); |
| 1031 | poperror(); | ||
| 1032 | |||
| 1033 | if(waserror()){ | ||
| 1034 | freeblist(first); | ||
| 1035 | nexterror(); | ||
| 1036 | } | ||
| 1037 | n = readblist(first, vp, len, 0); | ||
| 1038 | freeblist(first); | ||
| 1039 | poperror(); | ||
| 1040 | |||
| 1142 | return n; | 1041 | return n; |
| 1143 | } | 1042 | } |
| 1144 | 1043 | ||
| @@ -1150,7 +1049,30 @@ qnotfull(void *a) · 5 unmodified lines | |||
| 1150 | return q->len < q->limit || (q->state & Qclosed); | 1049 | return q->len < q->limit || (q->state & Qclosed); |
| 1151 | } | 1050 | } |
| 1152 | 1051 | ||
| 1153 | ulong noblockcnt; | 1052 | /* |
| 1053 | * flow control, wait for queue to get below the limit | ||
| 1054 | */ | ||
| 1055 | static void | ||
| 1056 | qflow(Queue *q) | ||
| 1057 | { | ||
| 1058 | for(;;){ | ||
| 1059 | if(q->noblock || qnotfull(q)) | ||
| 1060 | break; | ||
| 1061 | |||
| 1062 | ilock(&q->lk); | ||
| 1063 | q->state |= Qflow; | ||
| 1064 | iunlock(&q->lk); | ||
| 1065 | |||
| 1066 | qlock(&q->wlock); | ||
| 1067 | if(waserror()){ | ||
| 1068 | qunlock(&q->wlock); | ||
| 1069 | nexterror(); | ||
| 1070 | } | ||
| 1071 | sleep(&q->wr, qnotfull, q); | ||
| 1072 | qunlock(&q->wlock); | ||
| 1073 | poperror(); | ||
| 1074 | } | ||
| 1075 | } | ||
| 1154 | 1076 | ||
| 1155 | /* | 1077 | /* |
| 1156 | * add a block to a queue obeying flow control | 1078 | * add a block to a queue obeying flow control |
| @@ -1158,24 +1080,19 @@ ulong noblockcnt; · 1 unmodified line | |||
| 1158 | long | 1080 | long |
| 1159 | qbwrite(Queue *q, Block *b) | 1081 | qbwrite(Queue *q, Block *b) |
| 1160 | { | 1082 | { |
| 1161 | int n, dowakeup; | 1083 | int len, dowakeup; |
| 1162 | 1084 | ||
| 1163 | n = BLEN(b); | 1085 | if(q->bypass != nil){ |
| 1164 | 1086 | len = blocklen(b); | |
| 1165 | if(q->bypass){ | ||
| 1166 | (*q->bypass)(q->arg, b); | 1087 | (*q->bypass)(q->arg, b); |
| 1167 | return n; | 1088 | return len; |
| 1168 | } | 1089 | } |
| 1169 | 1090 | ||
| 1170 | dowakeup = 0; | 1091 | dowakeup = 0; |
| 1171 | qlock(&q->wlock); | ||
| 1172 | if(waserror()){ | 1092 | if(waserror()){ |
| 1173 | if(b != nil) | 1093 | freeblist(b); |
| 1174 | freeb(b); | ||
| 1175 | qunlock(&q->wlock); | ||
| 1176 | nexterror(); | 1094 | nexterror(); |
| 1177 | } | 1095 | } |
| 1178 | |||
| 1179 | ilock(&q->lk); | 1096 | ilock(&q->lk); |
| 1180 | 1097 | ||
| 1181 | /* give up if the queue is closed */ | 1098 | /* give up if the queue is closed */ |
| @@ -1184,29 +1101,16 @@ qbwrite(Queue *q, Block *b) · 2 unmodified lines | |||
| 1184 | error(q->err); | 1101 | error(q->err); |
| 1185 | } | 1102 | } |
| 1186 | 1103 | ||
| 1187 | /* if nonblocking, don't queue over the limit */ | 1104 | /* don't queue over the limit */ |
| 1188 | if(q->len >= q->limit){ | 1105 | if(q->len >= q->limit && q->noblock){ |
| 1189 | if(q->noblock){ | 1106 | iunlock(&q->lk); |
| 1190 | iunlock(&q->lk); | 1107 | poperror(); |
| 1191 | freeb(b); | 1108 | len = blocklen(b); |
| 1192 | noblockcnt += n; | 1109 | freeblist(b); |
| 1193 | qunlock(&q->wlock); | 1110 | return len; |
| 1194 | poperror(); | ||
| 1195 | return n; | ||
| 1196 | } | ||
| 1197 | } | 1111 | } |
| 1198 | 1112 | ||
| 1199 | /* queue the block */ | 1113 | len = qaddlist(q, b); |
| 1200 | if(q->bfirst) | ||
| 1201 | q->blast->next = b; | ||
| 1202 | else | ||
| 1203 | q->bfirst = b; | ||
| 1204 | q->blast = b; | ||
| 1205 | b->next = 0; | ||
| 1206 | q->len += BALLOC(b); | ||
| 1207 | q->dlen += n; | ||
| 1208 | QDEBUG checkb(b, "qbwrite"); | ||
| 1209 | b = nil; | ||
| 1210 | 1114 | ||
| 1211 | /* make sure other end gets awakened */ | 1115 | /* make sure other end gets awakened */ |
| 1212 | if(q->state & Qstarve){ | 1116 | if(q->state & Qstarve){ |
| @@ -1214,49 +1118,26 @@ qbwrite(Queue *q, Block *b) · 1 unmodified line | |||
| 1214 | dowakeup = 1; | 1118 | dowakeup = 1; |
| 1215 | } | 1119 | } |
| 1216 | iunlock(&q->lk); | 1120 | iunlock(&q->lk); |
| 1121 | poperror(); | ||
| 1217 | 1122 | ||
| 1218 | /* get output going again */ | 1123 | /* get output going again */ |
| 1219 | if(q->kick && (dowakeup || (q->state&Qkick))) | 1124 | if(q->kick != nil && (dowakeup || (q->state&Qkick))) |
| 1220 | q->kick(q->arg); | 1125 | q->kick(q->arg); |
| 1221 | 1126 | ||
| 1222 | /* wakeup anyone consuming at the other end */ | 1127 | /* wakeup anyone consuming at the other end */ |
| 1223 | if(dowakeup){ | 1128 | if(dowakeup) |
| 1224 | wakeup(&q->rr); | 1129 | wakeup(&q->rr); |
| 1225 | 1130 | ||
| 1226 | /* if we just wokeup a higher priority process, let it run */ | ||
| 1227 | /* | ||
| 1228 | p = wakeup(&q->rr); | ||
| 1229 | if(p != nil && p->priority > up->priority) | ||
| 1230 | sched(); | ||
| 1231 | */ | ||
| 1232 | } | ||
| 1233 | |||
| 1234 | /* | 1131 | /* |
| 1235 | * flow control, wait for queue to get below the limit | 1132 | * flow control, before allowing the process to continue and |
| 1236 | * before allowing the process to continue and queue | 1133 | * queue more. We do this here so that postnote can only |
| 1237 | * more. We do this here so that postnote can only | 1134 | * interrupt us after the data has been queued. This means that |
| 1238 | * interrupt us after the data has been queued. This | 1135 | * things like 9p flushes and ssl messages will not be disrupted |
| 1239 | * means that things like 9p flushes and ssl messages | 1136 | * by software interrupts. |
| 1240 | * will not be disrupted by software interrupts. | ||
| 1241 | * | ||
| 1242 | * Note - this is moderately dangerous since a process | ||
| 1243 | * that keeps getting interrupted and rewriting will | ||
| 1244 | * queue infinite crud. | ||
| 1245 | */ | 1137 | */ |
| 1246 | for(;;){ | 1138 | qflow(q); |
| 1247 | if(q->noblock || qnotfull(q)) | ||
| 1248 | break; | ||
| 1249 | 1139 | ||
| 1250 | ilock(&q->lk); | 1140 | return len; |
| 1251 | q->state |= Qflow; | ||
| 1252 | iunlock(&q->lk); | ||
| 1253 | sleep(&q->wr, qnotfull, q); | ||
| 1254 | } | ||
| 1255 | USED(b); | ||
| 1256 | |||
| 1257 | qunlock(&q->wlock); | ||
| 1258 | poperror(); | ||
| 1259 | return n; | ||
| 1260 | } | 1141 | } |
| 1261 | 1142 | ||
| 1262 | /* | 1143 | /* |
| @@ -1270,7 +1151,15 @@ qwrite(Queue *q, void *vp, int len) · 7 unmodified lines | |||
| 1270 | uchar *p = vp; | 1151 | uchar *p = vp; |
| 1271 | 1152 | ||
| 1272 | QDEBUG if(!islo()) | 1153 | QDEBUG if(!islo()) |
| 1273 | print("qwrite hi %p\n", getcallerpc(&q)); | 1154 | print("qwrite hi %#p\n", getcallerpc(&q)); |
| 1155 | |||
| 1156 | /* stop queue bloat before allocating blocks */ | ||
| 1157 | if(q->len/2 >= q->limit && q->noblock == 0 && q->bypass == nil){ | ||
| 1158 | while(waserror()) | ||
| 1159 | ; | ||
| 1160 | qflow(q); | ||
| 1161 | poperror(); | ||
| 1162 | } | ||
| 1274 | 1163 | ||
| 1275 | sofar = 0; | 1164 | sofar = 0; |
| 1276 | do { | 1165 | do { |
| @@ -1279,7 +1168,6 @@ qwrite(Queue *q, void *vp, int len) · 2 unmodified lines | |||
| 1279 | n = Maxatomic; | 1168 | n = Maxatomic; |
| 1280 | 1169 | ||
| 1281 | b = allocb(n); | 1170 | b = allocb(n); |
| 1282 | /* setmalloctag(b, (up->text[0]<<24)|(up->text[1]<<16)|(up->text[2]<<8)|up->text[3]); */ | ||
| 1283 | if(waserror()){ | 1171 | if(waserror()){ |
| 1284 | freeb(b); | 1172 | freeb(b); |
| 1285 | nexterror(); | 1173 | nexterror(); |
| @@ -1288,9 +1176,7 @@ qwrite(Queue *q, void *vp, int len) · 2 unmodified lines | |||
| 1288 | poperror(); | 1176 | poperror(); |
| 1289 | b->wp += n; | 1177 | b->wp += n; |
| 1290 | 1178 | ||
| 1291 | qbwrite(q, b); | 1179 | sofar += qbwrite(q, b); |
| 1292 | |||
| 1293 | sofar += n; | ||
| 1294 | } while(sofar < len && (q->state & Qmsg) == 0); | 1180 | } while(sofar < len && (q->state & Qmsg) == 0); |
| 1295 | 1181 | ||
| 1296 | return len; | 1182 | return len; |
| @@ -1323,14 +1209,16 @@ qiwrite(Queue *q, void *vp, int len) · 26 unmodified lines | |||
| 1323 | 1209 | ||
| 1324 | ilock(&q->lk); | 1210 | ilock(&q->lk); |
| 1325 | 1211 | ||
| 1326 | QDEBUG checkb(b, "qiwrite"); | 1212 | /* we use an artificially high limit for kernel prints since anything |
| 1327 | if(q->bfirst) | 1213 | * over the limit gets dropped |
| 1328 | q->blast->next = b; | 1214 | */ |
| 1329 | else | 1215 | if((q->state & Qclosed) != 0 || q->len/2 >= q->limit){ |
| 1330 | q->bfirst = b; | 1216 | iunlock(&q->lk); |
| 1331 | q->blast = b; | 1217 | freeb(b); |
| 1332 | q->len += BALLOC(b); | 1218 | break; |
| 1333 | q->dlen += n; | 1219 | } |
| 1220 | |||
| 1221 | qaddlist(q, b); | ||
| 1334 | 1222 | ||
| 1335 | if(q->state & Qstarve){ | 1223 | if(q->state & Qstarve){ |
| 1336 | q->state &= ~Qstarve; | 1224 | q->state &= ~Qstarve; |
| @@ -1340,7 +1228,7 @@ qiwrite(Queue *q, void *vp, int len) · 3 unmodified lines | |||
| 1340 | iunlock(&q->lk); | 1228 | iunlock(&q->lk); |
| 1341 | 1229 | ||
| 1342 | if(dowakeup){ | 1230 | if(dowakeup){ |
| 1343 | if(q->kick) | 1231 | if(q->kick != nil) |
| 1344 | q->kick(q->arg); | 1232 | q->kick(q->arg); |
| 1345 | wakeup(&q->rr); | 1233 | wakeup(&q->rr); |
| 1346 | } | 1234 | } |
| @@ -1378,9 +1266,9 @@ qclose(Queue *q) · 31 unmodified lines | |||
| 1378 | ilock(&q->lk); | 1266 | ilock(&q->lk); |
| 1379 | q->state |= Qclosed; | 1267 | q->state |= Qclosed; |
| 1380 | q->state &= ~(Qflow|Qstarve); | 1268 | q->state &= ~(Qflow|Qstarve); |
| 1381 | strcpy(q->err, Ehungup); | 1269 | kstrcpy(q->err, Ehungup, ERRMAX); |
| 1382 | bfirst = q->bfirst; | 1270 | bfirst = q->bfirst; |
| 1383 | q->bfirst = 0; | 1271 | q->bfirst = nil; |
| 1384 | q->len = 0; | 1272 | q->len = 0; |
| 1385 | q->dlen = 0; | 1273 | q->dlen = 0; |
| 1386 | q->noblock = 0; | 1274 | q->noblock = 0; |
| @@ -1404,10 +1292,9 @@ qhangup(Queue *q, char *msg) · 17 unmodified lines | |||
| 1404 | /* mark it */ | 1292 | /* mark it */ |
| 1405 | ilock(&q->lk); | 1293 | ilock(&q->lk); |
| 1406 | q->state |= Qclosed; | 1294 | q->state |= Qclosed; |
| 1407 | if(msg == 0 || *msg == 0) | 1295 | if(msg == nil || *msg == '\0') |
| 1408 | strcpy(q->err, Ehungup); | 1296 | msg = Ehungup; |
| 1409 | else | 1297 | kstrcpy(q->err, msg, ERRMAX); |
| 1410 | strncpy(q->err, msg, ERRMAX-1); | ||
| 1411 | iunlock(&q->lk); | 1298 | iunlock(&q->lk); |
| 1412 | 1299 | ||
| 1413 | /* wake up readers/writers */ | 1300 | /* wake up readers/writers */ |
| @@ -1467,7 +1354,7 @@ qwindow(Queue *q) · 53 unmodified lines | |||
| 1467 | int | 1354 | int |
| 1468 | qcanread(Queue *q) | 1355 | qcanread(Queue *q) |
| 1469 | { | 1356 | { |
| 1470 | return q->bfirst!=0; | 1357 | return q->bfirst != nil; |
| 1471 | } | 1358 | } |
| 1472 | 1359 | ||
| 1473 | /* | 1360 | /* |
| @@ -1499,7 +1386,7 @@ qflush(Queue *q) · 25 unmodified lines | |||
| 1499 | /* mark it */ | 1386 | /* mark it */ |
| 1500 | ilock(&q->lk); | 1387 | ilock(&q->lk); |
| 1501 | bfirst = q->bfirst; | 1388 | bfirst = q->bfirst; |
| 1502 | q->bfirst = 0; | 1389 | q->bfirst = nil; |
| 1503 | q->len = 0; | 1390 | q->len = 0; |
| 1504 | q->dlen = 0; | 1391 | q->dlen = 0; |
| 1505 | iunlock(&q->lk); | 1392 | iunlock(&q->lk); |
| @@ -1507,7 +1394,7 @@ qflush(Queue *q) · 1 unmodified line | |||
| 1507 | /* free queued blocks */ | 1394 | /* free queued blocks */ |
| 1508 | freeblist(bfirst); | 1395 | freeblist(bfirst); |
| 1509 | 1396 | ||
| 1510 | /* wake up readers/writers */ | 1397 | /* wake up writers */ |
| 1511 | wakeup(&q->wr); | 1398 | wakeup(&q->wr); |
| 1512 | } | 1399 | } |
| 1513 | 1400 | ||
| @@ -1516,9 +1403,3 @@ qfull(Queue *q) · 2 unmodified lines | |||
| 1516 | { | 1403 | { |
| 1517 | return q->state & Qflow; | 1404 | return q->state & Qflow; |
| 1518 | } | 1405 | } |
| 1519 | |||
| 1520 | int | ||
| 1521 | qstate(Queue *q) | ||
| 1522 | { | ||
| 1523 | return q->state; | ||
| 1524 | } | ||