]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libventi/packet.c
vmx: clean up mksegment, memset only if segment existed (devsegment clears new ones)
[plan9front.git] / sys / src / libventi / packet.c
1 #include <u.h>
2 #include <libc.h>
3 #include <venti.h>
4 #include <libsec.h>
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(;f<ef; f++) {
762                 if(f->state == 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