1 #include <u.h> 2 #include <libc.h> 3 #include <auth.h> 4 #include <fcall.h> 5 #include "dat.h" 6 #include "fns.h" 7 8 #define NIOBUF 100 9 #define HIOB (NIOBUF/3) 10 11 static Iobuf* hiob[HIOB]; /* hash buckets */ 12 static Iobuf iobuf[NIOBUF]; /* buffer headers */ 13 static Iobuf* iohead; 14 static Iobuf* iotail; 15 16 Iobuf* 17 getbuf(Xdata *dev, long addr) 18 { 19 Iobuf *p, *h, **l, **f; 20 21 l = &hiob[addr%HIOB]; 22 for(p = *l; p; p = p->next) { 23 if(p->addr == addr && p->dev == dev) { 24 p->busy++; 25 return p; 26 } 27 } 28 29 /* Find a non-busy buffer from the tail */ 30 for(p = iotail; p && p->busy; p = p->prev) 31 ; 32 if(p == 0) 33 panic(0, "all buffers busy"); 34 35 /* Delete from hash chain */ 36 f = &hiob[p->addr%HIOB]; 37 for(h = *f; h; h = h->next) { 38 if(h == p) { 39 *f = p->hash; 40 break; 41 } 42 f = &h->hash; 43 } 44 45 /* Hash and fill */ 46 p->hash = *l; 47 *l = p; 48 p->addr = addr; 49 p->dev = dev; 50 p->busy++; 51 if(waserror()) { 52 p->addr = 0; /* stop caching */ 53 putbuf(p); 54 nexterror(); 55 } 56 xread(p); 57 poperror(); 58 return p; 59 } 60 61 void 62 putbuf(Iobuf *p) 63 { 64 if(p->busy <= 0) 65 panic(0, "putbuf"); 66 67 p->busy--; 68 if(p == iohead) 69 return; 70 71 /* Link onto head for lru */ 72 if(p->prev) 73 p->prev->next = p->next; 74 else 75 iohead = p->next; 76 77 if(p->next) 78 p->next->prev = p->prev; 79 else 80 iotail = p->prev; 81 82 p->prev = 0; 83 p->next = iohead; 84 iohead->prev = p; 85 iohead = p; 86 } 87 88 void 89 purgebuf(Xdata *dev) 90 { 91 Iobuf *p; 92 93 for(p=&iobuf[0]; p<&iobuf[NIOBUF]; p++) 94 if(p->dev == dev) 95 p->busy = 0; 96 97 /* Blow hash chains */ 98 memset(hiob, 0, sizeof(hiob)); 99 } 100 101 void 102 iobuf_init(void) 103 { 104 Iobuf *p; 105 106 iohead = iobuf; 107 iotail = iobuf+NIOBUF-1; 108 109 for(p = iobuf; p <= iotail; p++) { 110 p->next = p+1; 111 p->prev = p-1; 112 113 p->iobuf = sbrk(Sectorsize); 114 if((long)p->iobuf == -1) 115 panic(0, "iobuf_init"); 116 } 117 118 iohead->prev = 0; 119 iotail->next = 0; 120 } 121