tpacket.c - plan9port - [fork] Plan 9 from user space
git clone git://src.adamsgaard.dk/plan9port
Log
Files
Refs
README
LICENSE
---
tpacket.c (15872B)
---
     1 #include 
     2 #include 
     3 #include 
     4 #include 
     5 
     6 typedef struct Mem Mem;
     7 typedef struct Frag Frag;
     8 
     9 enum {
    10         BigMemSize = MaxFragSize,
    11         SmallMemSize = BigMemSize/8,
    12         NLocalFrag = 2
    13 };
    14 
    15 /* position to carve out of a Mem */
    16 enum {
    17         PFront,
    18         PMiddle,
    19         PEnd
    20 };
    21 
    22 struct Mem
    23 {
    24         Lock lk;
    25         int ref;
    26         uchar *bp;
    27         uchar *ep;
    28         uchar *rp;
    29         uchar *wp;
    30         Mem *next;
    31 };
    32 
    33 enum {
    34         FragLocalFree,
    35         FragLocalAlloc,
    36         FragGlobal
    37 };
    38 
    39 struct Frag
    40 {
    41         int state;
    42         Mem *mem;
    43         uchar *rp;
    44         uchar *wp;
    45         Frag *next;
    46         void (*free)(void*);
    47         void *a;
    48         Packet *p;        /* parent packet, for debugging only */
    49 };
    50 
    51 struct Packet
    52 {
    53         int size;
    54         int asize;  /* allocated memory - greater than size unless foreign frags */
    55         ulong pc;
    56 
    57         Packet *next;
    58 
    59         Frag *first;
    60         Frag *last;
    61 
    62         Frag local[NLocalFrag];
    63 };
    64 
    65 static Frag *fragalloc(Packet*, int n, int pos, Frag *next);
    66 static Frag *fragdup(Packet*, Frag*);
    67 static void fragfree(Frag*);
    68 
    69 static Mem *memalloc(int, int);
    70 static void memfree(Mem*);
    71 static int memhead(Mem *m, uchar *rp, int n);
    72 static int memtail(Mem *m, uchar *wp, int n);
    73 
    74 static char EPacketSize[] = "bad packet size";
    75 static char EPacketOffset[] = "bad packet offset";
    76 static char EBadSize[] = "bad size";
    77 
    78 #ifdef NOTDEF
    79 static void checkpacket(Packet*);
    80 #endif
    81 
    82 /*
    83  * the free list is primarily for speed, but it is
    84  * also necessary for packetsplit that packets
    85  * are never freed -- a packet can contain a different
    86  * packet's local fragments, thanks to packetsplit!
    87  */
    88 static struct {
    89         Lock lk;
    90         Packet *packet;
    91         int npacket;
    92         Frag *frag;
    93         int nfrag;
    94         Mem *bigmem;
    95         int nbigmem;
    96         Mem *smallmem;
    97         int nsmallmem;
    98 } freelist;
    99 
   100 #define FRAGSIZE(f) ((f)->wp - (f)->rp)
   101 #define FRAGASIZE(f) ((f)->mem ? (f)->mem->ep - (f)->mem->bp : 0)
   102 
   103 #define NOTFREE(p) assert((p)->size>=0)/*; checkpacket(p)*/
   104 
   105 Packet *
   106 packetalloc(void)
   107 {
   108         Packet *p;
   109 
   110         lock(&freelist.lk);
   111         p = freelist.packet;
   112         if(p != nil)
   113                 freelist.packet = p->next;
   114         else
   115                 freelist.npacket++;
   116         unlock(&freelist.lk);
   117 
   118         if(p == nil)
   119                 p = vtbrk(sizeof(Packet));
   120         else
   121                 assert(p->size == -1);
   122         p->size = 0;
   123         p->asize = 0;
   124         p->first = nil;
   125         p->last = nil;
   126         p->next = nil;
   127         p->pc = getcallerpc((char*)&p+8);        /* might not work, but fine */
   128 
   129         NOTFREE(p);
   130         return p;
   131 }
   132 
   133 void
   134 packetfree(Packet *p)
   135 {
   136         Frag *f, *ff;
   137 
   138         if(p == nil)
   139                 return;
   140 
   141         NOTFREE(p);
   142         p->pc = getcallerpc(&p);
   143 
   144         for(f=p->first; f!=nil; f=ff) {
   145                 ff = f->next;
   146                 fragfree(f);
   147         }
   148         p->first = (void*)0xDeadBeef;
   149         p->last = (void*)0xDeadBeef;
   150         p->size = -1;
   151 
   152         lock(&freelist.lk);
   153         p->next = freelist.packet;
   154         freelist.packet = p;
   155         unlock(&freelist.lk);
   156 }
   157 
   158 Packet *
   159 packetdup(Packet *p, int offset, int n)
   160 {
   161         Frag *f, *ff;
   162         Packet *pp;
   163 
   164         NOTFREE(p);
   165         if(offset < 0 || n < 0 || offset+n > p->size) {
   166                 werrstr(EBadSize);
   167                 return nil;
   168         }
   169 
   170         pp = packetalloc();
   171         pp->pc = getcallerpc(&p);
   172         if(n == 0){
   173                 NOTFREE(pp);
   174                 return pp;
   175         }
   176 
   177         pp->size = n;
   178 
   179         /* skip offset */
   180         for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
   181                 offset -= FRAGSIZE(f);
   182 
   183         /* first frag */
   184         ff = fragdup(pp, f);
   185         ff->rp += offset;
   186         pp->first = ff;
   187         n -= FRAGSIZE(ff);
   188         pp->asize += FRAGASIZE(ff);
   189 
   190         /* the remaining */
   191         while(n > 0) {
   192                 f = f->next;
   193                 ff->next = fragdup(pp, f);
   194                 ff = ff->next;
   195                 n -= FRAGSIZE(ff);
   196                 pp->asize += FRAGASIZE(ff);
   197         }
   198 
   199         /* fix up last frag: note n <= 0 */
   200         ff->wp += n;
   201         ff->next = nil;
   202         pp->last = ff;
   203 
   204         NOTFREE(pp);
   205         NOTFREE(p);
   206         return pp;
   207 }
   208 
   209 Packet *
   210 packetsplit(Packet *p, int n)
   211 {
   212         Packet *pp;
   213         Frag *f, *ff;
   214 
   215         NOTFREE(p);
   216         if(n < 0 || n > p->size) {
   217                 werrstr(EPacketSize);
   218                 return nil;
   219         }
   220 
   221         pp = packetalloc();
   222         pp->pc = getcallerpc(&p);
   223         if(n == 0){
   224                 NOTFREE(pp);
   225                 return pp;
   226         }
   227 
   228         pp->size = n;
   229         p->size -= n;
   230         ff = nil;
   231         for(f=p->first; n > 0 && n >= FRAGSIZE(f); f=f->next) {
   232                 n -= FRAGSIZE(f);
   233                 p->asize -= FRAGASIZE(f);
   234                 pp->asize += FRAGASIZE(f);
   235                 f->p = pp;
   236                 ff = f;
   237         }
   238 
   239         /* split shared frag */
   240         if(n > 0) {
   241                 f->p = pp;
   242                 ff = f;
   243                 f = fragdup(p, ff);
   244                 pp->asize += FRAGASIZE(ff);
   245                 ff->wp = ff->rp + n;
   246                 f->rp += n;
   247         }
   248 
   249         pp->first = p->first;
   250         pp->last = ff;
   251         ff->next = nil;
   252         p->first = f;
   253         if(f == nil || f->next == nil)
   254                 p->last = f;
   255         NOTFREE(pp);
   256         NOTFREE(p);
   257         return pp;
   258 }
   259 
   260 int
   261 packetconsume(Packet *p, uchar *buf, int n)
   262 {
   263         NOTFREE(p);
   264         if(buf && packetcopy(p, buf, 0, n) < 0)
   265                 return -1;
   266         return packettrim(p, n, p->size-n);
   267 }
   268 
   269 int
   270 packettrim(Packet *p, int offset, int n)
   271 {
   272         Frag *f, *ff;
   273 
   274         NOTFREE(p);
   275         if(offset < 0 || offset > p->size) {
   276                 werrstr(EPacketOffset);
   277                 return -1;
   278         }
   279 
   280         if(n < 0 || offset + n > p->size) {
   281                 werrstr(EPacketOffset);
   282                 return -1;
   283         }
   284 
   285         p->size = n;
   286 
   287         /* easy case */
   288         if(n == 0) {
   289                 for(f=p->first; f != nil; f=ff) {
   290                         ff = f->next;
   291                         fragfree(f);
   292                 }
   293                 p->first = p->last = nil;
   294                 p->asize = 0;
   295                 NOTFREE(p);
   296                 return 0;
   297         }
   298 
   299         /* free before offset */
   300         for(f=p->first; offset >= FRAGSIZE(f); f=ff) {
   301                 p->asize -= FRAGASIZE(f);
   302                 offset -= FRAGSIZE(f);
   303                 ff = f->next;
   304                 fragfree(f);
   305         }
   306 
   307         /* adjust frag */
   308         f->rp += offset;
   309         p->first = f;
   310 
   311         /* skip middle */
   312         for(; n > 0 && n > FRAGSIZE(f); f=f->next)
   313                 n -= FRAGSIZE(f);
   314 
   315         /* adjust end */
   316         f->wp = f->rp + n;
   317         p->last = f;
   318         ff = f->next;
   319         f->next = nil;
   320 
   321         /* free after */
   322         for(f=ff; f != nil; f=ff) {
   323                 p->asize -= FRAGASIZE(f);
   324                 ff = f->next;
   325                 fragfree(f);
   326         }
   327         NOTFREE(p);
   328         return 0;
   329 }
   330 
   331 uchar *
   332 packetheader(Packet *p, int n)
   333 {
   334         Frag *f;
   335         Mem *m;
   336 
   337         NOTFREE(p);
   338         if(n <= 0 || n > MaxFragSize) {
   339                 werrstr(EPacketSize);
   340                 return nil;
   341         }
   342 
   343         p->size += n;
   344 
   345         /* try and fix in current frag */
   346         f = p->first;
   347         if(f != nil) {
   348                 m = f->mem;
   349                 if(n <= f->rp - m->bp)
   350                 if(m->ref == 1 || memhead(m, f->rp, n) >= 0) {
   351                         f->rp -= n;
   352                         NOTFREE(p);
   353                         return f->rp;
   354                 }
   355         }
   356 
   357         /* add frag to front */
   358         f = fragalloc(p, n, PEnd, p->first);
   359         p->asize += FRAGASIZE(f);
   360         if(p->first == nil)
   361                 p->last = f;
   362         p->first = f;
   363         NOTFREE(p);
   364         return f->rp;
   365 }
   366 
   367 uchar *
   368 packettrailer(Packet *p, int n)
   369 {
   370         Mem *m;
   371         Frag *f;
   372 
   373         NOTFREE(p);
   374         if(n <= 0 || n > MaxFragSize) {
   375                 werrstr(EPacketSize);
   376                 return nil;
   377         }
   378 
   379         p->size += n;
   380 
   381         /* try and fix in current frag */
   382         if(p->first != nil) {
   383                 f = p->last;
   384                 m = f->mem;
   385                 if(n <= m->ep - f->wp)
   386                 if(m->ref == 1 || memtail(m, f->wp, n) >= 0) {
   387                         f->wp += n;
   388                         NOTFREE(p);
   389                         return f->wp - n;
   390                 }
   391         }
   392 
   393         /* add frag to end */
   394         f = fragalloc(p, n, (p->first == nil)?PMiddle:PFront, nil);
   395         p->asize += FRAGASIZE(f);
   396         if(p->first == nil)
   397                 p->first = f;
   398         else
   399                 p->last->next = f;
   400         p->last = f;
   401         NOTFREE(p);
   402         return f->rp;
   403 }
   404 
   405 void
   406 packetprefix(Packet *p, uchar *buf, int n)
   407 {
   408         Frag *f;
   409         int nn;
   410         Mem *m;
   411 
   412         NOTFREE(p);
   413         if(n <= 0)
   414                 return;
   415 
   416         p->size += n;
   417 
   418         /* try and fix in current frag */
   419         f = p->first;
   420         if(f != nil) {
   421                 m = f->mem;
   422                 nn = f->rp - m->bp;
   423                 if(nn > n)
   424                         nn = n;
   425                 if(m->ref == 1 || memhead(m, f->rp, nn) >= 0) {
   426                         f->rp -= nn;
   427                         n -= nn;
   428                         memmove(f->rp, buf+n, nn);
   429                 }
   430         }
   431 
   432         while(n > 0) {
   433                 nn = n;
   434                 if(nn > MaxFragSize)
   435                         nn = MaxFragSize;
   436                 f = fragalloc(p, nn, PEnd, p->first);
   437                 p->asize += FRAGASIZE(f);
   438                 if(p->first == nil)
   439                         p->last = f;
   440                 p->first = f;
   441                 n -= nn;
   442                 memmove(f->rp, buf+n, nn);
   443         }
   444         NOTFREE(p);
   445 }
   446 
   447 void
   448 packetappend(Packet *p, uchar *buf, int n)
   449 {
   450         Frag *f;
   451         int nn;
   452         Mem *m;
   453 
   454         NOTFREE(p);
   455         if(n <= 0)
   456                 return;
   457 
   458         p->size += n;
   459         /* try and fix in current frag */
   460         if(p->first != nil) {
   461                 f = p->last;
   462                 m = f->mem;
   463                 nn = m->ep - f->wp;
   464                 if(nn > n)
   465                         nn = n;
   466                 if(m->ref == 1 || memtail(m, f->wp, nn) >= 0) {
   467                         memmove(f->wp, buf, nn);
   468                         f->wp += nn;
   469                         buf += nn;
   470                         n -= nn;
   471                 }
   472         }
   473 
   474         while(n > 0) {
   475                 nn = n;
   476                 if(nn > MaxFragSize)
   477                         nn = MaxFragSize;
   478                 f = fragalloc(p, nn, (p->first == nil)?PMiddle:PFront, nil);
   479                 p->asize += FRAGASIZE(f);
   480                 if(p->first == nil)
   481                         p->first = f;
   482                 else
   483                         p->last->next = f;
   484                 p->last = f;
   485                 memmove(f->rp, buf, nn);
   486                 buf += nn;
   487                 n -= nn;
   488         }
   489         NOTFREE(p);
   490 }
   491 
   492 void
   493 packetconcat(Packet *p, Packet *pp)
   494 {
   495         Frag *f;
   496 
   497         NOTFREE(p);
   498         NOTFREE(pp);
   499         if(pp->size == 0)
   500                 return;
   501         p->size += pp->size;
   502         p->asize += pp->asize;
   503         for(f=pp->first; f; f=f->next)
   504                 f->p = p;
   505 
   506         if(p->first != nil)
   507                 p->last->next = pp->first;
   508         else
   509                 p->first = pp->first;
   510 
   511         p->last = pp->last;
   512         pp->size = 0;
   513         pp->asize = 0;
   514         pp->first = nil;
   515         pp->last = nil;
   516         NOTFREE(p);
   517         NOTFREE(pp);
   518 }
   519 
   520 uchar *
   521 packetpeek(Packet *p, uchar *buf, int offset, int n)
   522 {
   523         Frag *f;
   524         int nn;
   525         uchar *b;
   526 
   527         NOTFREE(p);
   528         if(n == 0)
   529                 return buf;
   530 
   531         if(offset < 0 || offset >= p->size) {
   532                 werrstr(EPacketOffset);
   533                 return nil;
   534         }
   535 
   536         if(n < 0 || offset + n > p->size) {
   537                 werrstr(EPacketSize);
   538                 return nil;
   539         }
   540 
   541         /* skip up to offset */
   542         for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
   543                 offset -= FRAGSIZE(f);
   544 
   545         /* easy case */
   546         if(offset + n <= FRAGSIZE(f)){
   547                 NOTFREE(p);
   548                 return f->rp + offset;
   549         }
   550 
   551         for(b=buf; n>0; n -= nn) {
   552                 nn = FRAGSIZE(f) - offset;
   553                 if(nn > n)
   554                         nn = n;
   555                 memmove(b, f->rp+offset, nn);
   556                 offset = 0;
   557                 f = f->next;
   558                 b += nn;
   559         }
   560 
   561         NOTFREE(p);
   562         return buf;
   563 }
   564 
   565 int
   566 packetcopy(Packet *p, uchar *buf, int offset, int n)
   567 {
   568         uchar *b;
   569 
   570         NOTFREE(p);
   571         b = packetpeek(p, buf, offset, n);
   572         if(b == nil)
   573                 return -1;
   574         if(b != buf)
   575                 memmove(buf, b, n);
   576         return 0;
   577 }
   578 
   579 int
   580 packetfragments(Packet *p, IOchunk *io, int nio, int offset)
   581 {
   582         Frag *f;
   583         int size;
   584         IOchunk *eio;
   585 
   586         NOTFREE(p);
   587         if(p->size == 0 || nio <= 0)
   588                 return 0;
   589 
   590         if(offset < 0 || offset > p->size) {
   591                 werrstr(EPacketOffset);
   592                 return -1;
   593         }
   594 
   595         for(f=p->first; offset >= FRAGSIZE(f); f=f->next)
   596                 offset -= FRAGSIZE(f);
   597 
   598         size = 0;
   599         eio = io + nio;
   600         for(; f != nil && io < eio; f=f->next) {
   601                 io->addr = f->rp + offset;
   602                 io->len = f->wp - (f->rp + offset);
   603                 offset = 0;
   604                 size += io->len;
   605                 io++;
   606         }
   607         for(; io < eio; io++){
   608                 io->addr = nil;
   609                 io->len = 0;
   610         }
   611         return size;
   612 }
   613 
   614 void
   615 packetstats(void)
   616 {
   617         Packet *p;
   618         Frag *f;
   619         Mem *m;
   620 
   621         int np, nf, nsm, nbm;
   622 
   623         lock(&freelist.lk);
   624         np = 0;
   625         for(p=freelist.packet; p; p=p->next)
   626                 np++;
   627         nf = 0;
   628         for(f=freelist.frag; f; f=f->next)
   629                 nf++;
   630         nsm = 0;
   631         for(m=freelist.smallmem; m; m=m->next)
   632                 nsm++;
   633         nbm = 0;
   634         for(m=freelist.bigmem; m; m=m->next)
   635                 nbm++;
   636 
   637         fprint(2, "packet: %d/%d frag: %d/%d small mem: %d/%d big mem: %d/%d\n",
   638                 np, freelist.npacket,
   639                 nf, freelist.nfrag,
   640                 nsm, freelist.nsmallmem,
   641                 nbm, freelist.nbigmem);
   642 
   643         unlock(&freelist.lk);
   644 }
   645 
   646 
   647 uint
   648 packetsize(Packet *p)
   649 {
   650         NOTFREE(p);
   651         if(1) {
   652                 Frag *f;
   653                 int size = 0;
   654 
   655                 for(f=p->first; f; f=f->next)
   656                         size += FRAGSIZE(f);
   657                 if(size != p->size)
   658                         fprint(2, "packetsize %d %d\n", size, p->size);
   659                 assert(size == p->size);
   660         }
   661         return p->size;
   662 }
   663 
   664 uint
   665 packetasize(Packet *p)
   666 {
   667         NOTFREE(p);
   668         if(0) {
   669                 Frag *f;
   670                 int asize = 0;
   671 
   672                 for(f=p->first; f; f=f->next)
   673                         asize += FRAGASIZE(f);
   674                 if(asize != p->asize)
   675                         fprint(2, "packetasize %d %d\n", asize, p->asize);
   676                 assert(asize == p->asize);
   677         }
   678         return p->asize;
   679 }
   680 
   681 void
   682 packetsha1(Packet *p, uchar digest[VtScoreSize])
   683 {
   684         DigestState ds;
   685         Frag *f;
   686         int size;
   687 
   688         NOTFREE(p);
   689         memset(&ds, 0, sizeof ds);
   690         size = p->size;
   691         for(f=p->first; f; f=f->next) {
   692                 sha1(f->rp, FRAGSIZE(f), nil, &ds);
   693                 size -= FRAGSIZE(f);
   694         }
   695         assert(size == 0);
   696         sha1(nil, 0, digest, &ds);
   697 }
   698 
   699 int
   700 packetcmp(Packet *pkt0, Packet *pkt1)
   701 {
   702         Frag *f0, *f1;
   703         int n0, n1, x;
   704 
   705         NOTFREE(pkt0);
   706         NOTFREE(pkt1);
   707         f0 = pkt0->first;
   708         f1 = pkt1->first;
   709 
   710         if(f0 == nil)
   711                 return (f1 == nil)?0:-1;
   712         if(f1 == nil)
   713                 return 1;
   714         n0 = FRAGSIZE(f0);
   715         n1 = FRAGSIZE(f1);
   716 
   717         for(;;) {
   718                 if(n0 < n1) {
   719                         x = memcmp(f0->wp - n0, f1->wp - n1, n0);
   720                         if(x != 0)
   721                                 return x;
   722                         n1 -= n0;
   723                         f0 = f0->next;
   724                         if(f0 == nil)
   725                                 return -1;
   726                         n0 = FRAGSIZE(f0);
   727                 } else if (n0 > n1) {
   728                         x = memcmp(f0->wp - n0, f1->wp - n1, n1);
   729                         if(x != 0)
   730                                 return x;
   731                         n0 -= n1;
   732                         f1 = f1->next;
   733                         if(f1 == nil)
   734                                 return 1;
   735                         n1 = FRAGSIZE(f1);
   736                 } else { /* n0 == n1 */
   737                         x = memcmp(f0->wp - n0, f1->wp - n1, n0);
   738                         if(x != 0)
   739                                 return x;
   740                         f0 = f0->next;
   741                         f1 = f1->next;
   742                         if(f0 == nil)
   743                                 return (f1 == nil)?0:-1;
   744                         if(f1 == nil)
   745                                 return 1;
   746                         n0 = FRAGSIZE(f0);
   747                         n1 = FRAGSIZE(f1);
   748                 }
   749         }
   750 }
   751 
   752 static Frag *
   753 fragalloc(Packet *p, int n, int pos, Frag *next)
   754 {
   755         Frag *f, *ef;
   756         Mem *m;
   757 
   758         /* look for local frag */
   759         f = &p->local[0];
   760         ef = &p->local[NLocalFrag];
   761         for(;fstate == FragLocalFree) {
   763                         f->state = FragLocalAlloc;
   764                         goto Found;
   765                 }
   766         }
   767         lock(&freelist.lk);
   768         f = freelist.frag;
   769         if(f != nil)
   770                 freelist.frag = f->next;
   771         else
   772                 freelist.nfrag++;
   773         unlock(&freelist.lk);
   774 
   775         if(f == nil) {
   776                 f = vtbrk(sizeof(Frag));
   777                 f->state = FragGlobal;
   778         }
   779 
   780 Found:
   781         f->next = next;
   782         f->p = p;
   783 
   784         if(n == 0){
   785                 f->mem = 0;
   786                 f->rp = 0;
   787                 f->wp = 0;
   788                 return f;
   789         }
   790 
   791         if(pos == PEnd && next == nil)
   792                 pos = PMiddle;
   793         m = memalloc(n, pos);
   794         f->mem = m;
   795         f->rp = m->rp;
   796         f->wp = m->wp;
   797         return f;
   798 }
   799 
   800 Packet*
   801 packetforeign(uchar *buf, int n, void (*free)(void *a), void *a)
   802 {
   803         Packet *p;
   804         Frag *f;
   805 
   806         p = packetalloc();
   807         p->pc = getcallerpc(&buf);
   808         f = fragalloc(p, 0, 0, nil);
   809         f->free = free;
   810         f->a = a;
   811         f->next = nil;
   812         f->rp = buf;
   813         f->wp = buf+n;
   814 
   815         p->first = f;
   816         p->last = f;
   817         p->size = n;
   818         NOTFREE(p);
   819         return p;
   820 }
   821 
   822 static Frag *
   823 fragdup(Packet *p, Frag *f)
   824 {
   825         Frag *ff;
   826         Mem *m;
   827 
   828         m = f->mem;
   829 
   830         /*
   831          * m->rp && m->wp can be out of date when ref == 1
   832          * also, potentially reclaims space from previous frags
   833          */
   834         if(m && m->ref == 1) {
   835                 m->rp = f->rp;
   836                 m->wp = f->wp;
   837         }
   838 
   839         ff = fragalloc(p, 0, 0, nil);
   840         ff->mem = f->mem;
   841         ff->rp = f->rp;
   842         ff->wp = f->wp;
   843         ff->next = f->next;
   844 
   845         /*
   846          * We can't duplicate these -- there's no dup function.
   847          */
   848         assert(f->free==nil && f->a==nil);
   849 
   850         if(m){
   851                 lock(&m->lk);
   852                 m->ref++;
   853                 unlock(&m->lk);
   854         }
   855 
   856 
   857         return ff;
   858 }
   859 
   860 
   861 static void
   862 fragfree(Frag *f)
   863 {
   864         if(f->mem == nil){
   865                 if(f->free)
   866                         (*f->free)(f->a);
   867         }else{
   868                 memfree(f->mem);
   869                 f->mem = 0;
   870         }
   871 
   872         if(f->state == FragLocalAlloc) {
   873                 f->state = FragLocalFree;
   874                 return;
   875         }
   876 
   877         lock(&freelist.lk);
   878         f->next = freelist.frag;
   879         freelist.frag = f;
   880         unlock(&freelist.lk);
   881 }
   882 
   883 static Mem *
   884 memalloc(int n, int pos)
   885 {
   886         Mem *m;
   887         int nn;
   888 
   889         if(n < 0 || n > MaxFragSize) {
   890                 werrstr(EPacketSize);
   891                 return nil;
   892         }
   893         if(n <= SmallMemSize) {
   894                 lock(&freelist.lk);
   895                 m = freelist.smallmem;
   896                 if(m != nil)
   897                         freelist.smallmem = m->next;
   898                 else
   899                         freelist.nsmallmem++;
   900                 unlock(&freelist.lk);
   901                 nn = SmallMemSize;
   902         } else {
   903                 lock(&freelist.lk);
   904                 m = freelist.bigmem;
   905                 if(m != nil)
   906                         freelist.bigmem = m->next;
   907                 else
   908                         freelist.nbigmem++;
   909                 unlock(&freelist.lk);
   910                 nn = BigMemSize;
   911         }
   912 
   913         if(m == nil) {
   914                 m = vtbrk(sizeof(Mem));
   915                 m->bp = vtbrk(nn);
   916                 m->ep = m->bp + nn;
   917         }
   918         assert(m->ref == 0);
   919         m->ref = 1;
   920 
   921         switch(pos) {
   922         default:
   923                 assert(0);
   924         case PFront:
   925                 m->rp = m->bp;
   926                 break;
   927         case PMiddle:
   928                 /* leave a little bit at end */
   929                 m->rp = m->ep - n - 32;
   930                 break;
   931         case PEnd:
   932                 m->rp = m->ep - n;
   933                 break;
   934         }
   935         /* check we did not blow it */
   936         if(m->rp < m->bp)
   937                 m->rp = m->bp;
   938         m->wp = m->rp + n;
   939         assert(m->rp >= m->bp && m->wp <= m->ep);
   940         return m;
   941 }
   942 
   943 static void
   944 memfree(Mem *m)
   945 {
   946         lock(&m->lk);
   947         m->ref--;
   948         if(m->ref > 0) {
   949                 unlock(&m->lk);
   950                 return;
   951         }
   952         unlock(&m->lk);
   953         assert(m->ref == 0);
   954 
   955 /*        memset(m->bp, 0xEF, m->ep-m->bp); */
   956         switch(m->ep - m->bp) {
   957         default:
   958                 assert(0);
   959         case SmallMemSize:
   960                 lock(&freelist.lk);
   961                 m->next = freelist.smallmem;
   962                 freelist.smallmem = m;
   963                 unlock(&freelist.lk);
   964                 break;
   965         case BigMemSize:
   966                 lock(&freelist.lk);
   967                 m->next = freelist.bigmem;
   968                 freelist.bigmem = m;
   969                 unlock(&freelist.lk);
   970                 break;
   971         }
   972 }
   973 
   974 static int
   975 memhead(Mem *m, uchar *rp, int n)
   976 {
   977         fprint(2, "memhead called\n");
   978         abort();
   979         lock(&m->lk);
   980         if(m->rp != rp) {
   981                 unlock(&m->lk);
   982                 return -1;
   983         }
   984         m->rp -= n;
   985         unlock(&m->lk);
   986         return 0;
   987 }
   988 
   989 static int
   990 memtail(Mem *m, uchar *wp, int n)
   991 {
   992         fprint(2, "memtail called\n");
   993         abort();
   994         lock(&m->lk);
   995         if(m->wp != wp) {
   996                 unlock(&m->lk);
   997                 return -1;
   998         }
   999         m->wp += n;
  1000         unlock(&m->lk);
  1001         return 0;
  1002 }
  1003 
  1004 #ifdef NOTDEF
  1005 static void
  1006 checkpacket(Packet *p)
  1007 {
  1008         int s, as;
  1009         Frag *f;
  1010         Frag *ff;
  1011 
  1012         s = 0;
  1013         as = 0;
  1014         ff=p->first;
  1015         for(f=p->first; f; ff=f,f=f->next){
  1016                 assert(f->p == p);
  1017                 s += FRAGSIZE(f);
  1018                 as += FRAGASIZE(f);
  1019         }
  1020         assert(s == p->size);
  1021         assert(as == p->asize);
  1022         if(p->first)
  1023                 assert(ff==p->last);
  1024 }
  1025 #endif