64-bit VFS_LSEEK_OFF
[minix3.git] / servers / inet / buf.c
blob5a2f20dff939e3a8ed5c6f3e6956bb7294fe4bdf
1 /*
2 This file contains routines for buffer management.
4 Copyright 1995 Philip Homburg
5 */
7 #include "inet.h"
9 #include <stdlib.h>
10 #include <string.h>
12 #include "generic/assert.h"
13 #include "generic/buf.h"
15 THIS_FILE
17 #ifndef BUF_USEMALLOC
18 #define BUF_USEMALLOC 0
19 #endif
21 #ifndef BUF512_NR
22 #define BUF512_NR 512
23 #endif
24 #ifndef BUF2K_NR
25 #define BUF2K_NR 0
26 #endif
27 #ifndef BUF32K_NR
28 #define BUF32K_NR 0
29 #endif
31 #define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
32 #define CLIENT_NR 10
34 #define DECLARE_TYPE(Tag, Type, Size) \
35 typedef struct Tag \
36 { \
37 buf_t buf_header; \
38 char buf_data[Size]; \
39 } Type
41 #if BUF_USEMALLOC
42 #define DECLARE_STORAGE(Type, Ident, Nitems) \
43 PRIVATE Type *Ident
45 #define ALLOC_STORAGE(Ident, Nitems, Label) \
46 do \
47 { \
48 printf("buf.c: malloc %d %s\n", Nitems, Label); \
49 Ident= malloc(sizeof(*Ident) * Nitems); \
50 if (!Ident) \
51 ip_panic(( "unable to alloc %s", Label )); \
52 } while(0)
53 #else
54 #define DECLARE_STORAGE(Type, Ident, Nitems) \
55 PRIVATE Type Ident[Nitems]
57 #define ALLOC_STORAGE(Ident, Nitems, Label) \
58 (void)0
59 #endif
61 #if BUF512_NR
62 DECLARE_TYPE(buf512, buf512_t, 512);
63 static acc_t *buf512_freelist;
64 DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
65 static void bf_512free ARGS(( acc_t *acc ));
66 #endif
67 #if BUF2K_NR
68 DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
69 static acc_t *buf2K_freelist;
70 DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
71 static void bf_2Kfree ARGS(( acc_t *acc ));
72 #endif
73 #if BUF32K_NR
74 DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
75 static acc_t *buf32K_freelist;
76 DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
77 static void bf_32Kfree ARGS(( acc_t *acc ));
78 #endif
80 static acc_t *acc_freelist;
81 DECLARE_STORAGE(acc_t, accessors, ACC_NR);
83 static bf_freereq_t freereq[CLIENT_NR];
84 static size_t bf_buf_gran;
86 size_t bf_free_bufsize;
87 acc_t *bf_temporary_acc;
88 acc_t *bf_linkcheck_acc;
90 #ifdef BUF_CONSISTENCY_CHECK
91 int inet_buf_debug;
92 unsigned buf_generation;
93 static bf_checkreq_t checkreq[CLIENT_NR];
94 #endif
96 #ifndef BUF_TRACK_ALLOC_FREE
97 static acc_t *bf_small_memreq ARGS(( size_t size ));
98 #else
99 static acc_t *_bf_small_memreq ARGS(( char *clnt_file, int clnt_line,
100 size_t size ));
101 #define bf_small_memreq(a) _bf_small_memreq(clnt_file, clnt_line, a)
102 #endif
103 static void free_accs ARGS(( void ));
104 #ifdef BUF_CONSISTENCY_CHECK
105 static void count_free_bufs ARGS(( acc_t *list ));
106 static int report_buffer ARGS(( buf_t *buf, char *label, int i ));
107 #endif
109 void bf_init()
111 int i;
112 size_t buf_s;
113 acc_t *acc;
115 bf_buf_gran= BUF_S;
116 buf_s= 0;
118 for (i=0;i<CLIENT_NR;i++)
119 freereq[i]=0;
120 #ifdef BUF_CONSISTENCY_CHECK
121 for (i=0;i<CLIENT_NR;i++)
122 checkreq[i]=0;
123 #endif
125 #if BUF512_NR
126 ALLOC_STORAGE(buffers512, BUF512_NR, "512B-buffers");
127 #endif
128 #if BUF2K_NR
129 ALLOC_STORAGE(buffers2K, BUF2K_NR, "2K-buffers");
130 #endif
131 #if BUF32K_NR
132 ALLOC_STORAGE(buffers32K, BUF32K_NR, "32K-buffers");
133 #endif
134 ALLOC_STORAGE(accessors, ACC_NR, "accs");
136 acc_freelist= NULL;
137 for (i=0;i<ACC_NR;i++)
139 memset(&accessors[i], '\0', sizeof(accessors[i]));
141 accessors[i].acc_linkC= 0;
142 accessors[i].acc_next= acc_freelist;
143 acc_freelist= &accessors[i];
146 #define INIT_BUFFERS(Ident, Nitems, Freelist, Freefunc) \
147 do \
149 Freelist= NULL; \
150 for (i=0;i<Nitems;i++) \
152 acc= acc_freelist; \
153 if (!acc) \
154 ip_panic(( "fewer accessors than buffers")); \
155 acc_freelist= acc->acc_next; \
156 acc->acc_linkC= 0; \
158 memset(&Ident[i], '\0', sizeof(Ident[i])); \
159 Ident[i].buf_header.buf_linkC= 0; \
160 Ident[i].buf_header.buf_free= Freefunc; \
161 Ident[i].buf_header.buf_size= \
162 sizeof(Ident[i].buf_data); \
163 Ident[i].buf_header.buf_data_p= \
164 Ident[i].buf_data; \
166 acc->acc_buffer= &Ident[i].buf_header; \
167 acc->acc_next= Freelist; \
168 Freelist= acc; \
170 if (sizeof(Ident[0].buf_data) < bf_buf_gran) \
171 bf_buf_gran= sizeof(Ident[0].buf_data); \
172 if (sizeof(Ident[0].buf_data) > buf_s) \
173 buf_s= sizeof(Ident[0].buf_data); \
174 } while(0)
176 #if BUF512_NR
177 INIT_BUFFERS(buffers512, BUF512_NR, buf512_freelist, bf_512free);
178 #endif
179 #if BUF2K_NR
180 INIT_BUFFERS(buffers2K, BUF2K_NR, buf2K_freelist, bf_2Kfree);
181 #endif
182 #if BUF32K_NR
183 INIT_BUFFERS(buffers32K, BUF32K_NR, buf32K_freelist, bf_32Kfree);
184 #endif
186 #undef INIT_BUFFERS
188 assert (buf_s == BUF_S);
191 #ifndef BUF_CONSISTENCY_CHECK
192 void bf_logon(func)
193 bf_freereq_t func;
194 #else
195 void bf_logon(func, checkfunc)
196 bf_freereq_t func;
197 bf_checkreq_t checkfunc;
198 #endif
200 int i;
202 for (i=0;i<CLIENT_NR;i++)
203 if (!freereq[i])
205 freereq[i]=func;
206 #ifdef BUF_CONSISTENCY_CHECK
207 checkreq[i]= checkfunc;
208 #endif
209 return;
212 ip_panic(( "buf.c: too many clients" ));
216 bf_memreq
219 #ifndef BUF_TRACK_ALLOC_FREE
220 acc_t *bf_memreq(size)
221 #else
222 acc_t *_bf_memreq(clnt_file, clnt_line, size)
223 char *clnt_file;
224 int clnt_line;
225 #endif
226 size_t size;
228 acc_t *head, *tail, *new_acc;
229 buf_t *buf;
230 int i,j;
231 size_t count;
233 assert (size>0);
235 head= NULL;
236 tail= NULL;
237 while (size)
239 new_acc= NULL;
241 /* Note the tricky dangling else... */
242 #define ALLOC_BUF(Freelist, Bufsize) \
243 if (Freelist && (Bufsize == BUF_S || size <= Bufsize)) \
245 new_acc= Freelist; \
246 Freelist= new_acc->acc_next; \
248 assert(new_acc->acc_linkC == 0); \
249 new_acc->acc_linkC= 1; \
250 buf= new_acc->acc_buffer; \
251 assert(buf->buf_linkC == 0); \
252 buf->buf_linkC= 1; \
254 else
256 /* Sort attempts by buffer size */
257 #if BUF512_NR
258 ALLOC_BUF(buf512_freelist, 512)
259 #endif
260 #if BUF2K_NR
261 ALLOC_BUF(buf2K_freelist, 2*1024)
262 #endif
263 #if BUF32K_NR
264 ALLOC_BUF(buf32K_freelist, 32*1024)
265 #endif
266 #undef ALLOC_BUF
268 DBLOCK(2, printf("freeing buffers\n"));
270 bf_free_bufsize= 0;
271 for (i=0; bf_free_bufsize<size && i<MAX_BUFREQ_PRI;
272 i++)
274 for (j=0; j<CLIENT_NR; j++)
276 if (freereq[j])
277 (*freereq[j])(i);
279 #if DEBUG && 0
280 { acc_t *acc;
281 j= 0; for(acc= buf512_freelist; acc; acc= acc->acc_next) j++;
282 printf("# of free 512-bytes buffer is now %d\n", j); }
283 #endif
285 #if DEBUG && 0
286 { printf("last level was level %d\n", i-1); }
287 #endif
288 if (bf_free_bufsize<size)
289 ip_panic(( "not enough buffers freed" ));
291 continue;
294 #ifdef BUF_TRACK_ALLOC_FREE
295 new_acc->acc_alloc_file= clnt_file;
296 new_acc->acc_alloc_line= clnt_line;
297 buf->buf_alloc_file= clnt_file;
298 buf->buf_alloc_line= clnt_line;
299 #endif
301 if (!head)
302 head= new_acc;
303 else
304 tail->acc_next= new_acc;
305 tail= new_acc;
307 count= tail->acc_buffer->buf_size;
308 if (count > size)
309 count= size;
311 tail->acc_offset= 0;
312 tail->acc_length= count;
313 size -= count;
315 tail->acc_next= NULL;
317 return head;
321 bf_small_memreq
324 #ifndef BUF_TRACK_ALLOC_FREE
325 static acc_t *bf_small_memreq(size)
326 #else
327 static acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
328 char *clnt_file;
329 int clnt_line;
330 #endif
331 size_t size;
333 return bf_memreq(size);
336 #ifndef BUF_TRACK_ALLOC_FREE
337 void bf_afree(acc)
338 #else
339 void _bf_afree(clnt_file, clnt_line, acc)
340 char *clnt_file;
341 int clnt_line;
342 #endif
343 acc_t *acc;
345 acc_t *next_acc;
346 buf_t *buf;
348 while (acc)
350 #if defined(bf_afree)
351 DIFBLOCK(1, (acc->acc_linkC <= 0),
352 printf("clnt_file= %s, clnt_line= %d\n",
353 clnt_file, clnt_line));
354 #endif
355 assert (acc->acc_linkC>0);
356 if (--acc->acc_linkC > 0)
357 break;
359 #ifdef BUF_TRACK_ALLOC_FREE
360 acc->acc_free_file= clnt_file;
361 acc->acc_free_line= clnt_line;
362 #endif
363 buf= acc->acc_buffer;
364 assert (buf);
366 #if defined(bf_afree)
367 DIFBLOCK(1, (buf->buf_linkC == 0),
368 printf("clnt_file= %s, clnt_line= %d\n",
369 clnt_file, clnt_line));
370 #endif
371 assert (buf->buf_linkC>0);
372 if (--buf->buf_linkC > 0)
374 acc->acc_buffer= NULL;
375 next_acc= acc->acc_next;
376 acc->acc_next= acc_freelist;
377 acc_freelist= acc;
378 #ifdef BUF_CONSISTENCY_CHECK
379 if (inet_buf_debug)
381 acc->acc_offset= 0xdeadbeaf;
382 acc->acc_length= 0xdeadbeaf;
383 acc->acc_buffer= (buf_t *)0xdeadbeaf;
384 acc->acc_ext_link= (acc_t *)0xdeadbeaf;
386 #endif
387 acc= next_acc;
388 continue;
391 bf_free_bufsize += buf->buf_size;
392 #ifdef BUF_TRACK_ALLOC_FREE
393 buf->buf_free_file= clnt_file;
394 buf->buf_free_line= clnt_line;
395 #endif
396 next_acc= acc->acc_next;
397 buf->buf_free(acc);
398 acc= next_acc;
399 continue;
403 #ifndef BUF_TRACK_ALLOC_FREE
404 acc_t *bf_dupacc(acc_ptr)
405 #else
406 acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
407 char *clnt_file;
408 int clnt_line;
409 #endif
410 register acc_t *acc_ptr;
412 register acc_t *new_acc;
414 if (!acc_freelist)
416 free_accs();
417 if (!acc_freelist)
418 ip_panic(( "buf.c: out of accessors" ));
420 new_acc= acc_freelist;
421 acc_freelist= new_acc->acc_next;
423 *new_acc= *acc_ptr;
424 if (acc_ptr->acc_next)
425 acc_ptr->acc_next->acc_linkC++;
426 if (acc_ptr->acc_buffer)
427 acc_ptr->acc_buffer->buf_linkC++;
428 new_acc->acc_linkC= 1;
429 #ifdef BUF_TRACK_ALLOC_FREE
430 new_acc->acc_alloc_file= clnt_file;
431 new_acc->acc_alloc_line= clnt_line;
432 #endif
433 return new_acc;
436 size_t bf_bufsize(acc_ptr)
437 register acc_t *acc_ptr;
439 register size_t size;
441 assert(acc_ptr);
443 size=0;
445 while (acc_ptr)
447 assert(acc_ptr >= accessors && acc_ptr <= &accessors[ACC_NR-1]);
448 size += acc_ptr->acc_length;
449 acc_ptr= acc_ptr->acc_next;
451 return size;
454 #ifndef BUF_TRACK_ALLOC_FREE
455 acc_t *bf_packIffLess(pack, min_len)
456 #else
457 acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
458 char *clnt_file;
459 int clnt_line;
460 #endif
461 acc_t *pack;
462 int min_len;
464 if (!pack || pack->acc_length >= min_len)
465 return pack;
467 #if DEBUG
468 #ifdef bf_packIffLess
469 { where(); printf("calling bf_pack because of %s %d: %d\n", bf_pack_file,
470 bf_pack_line, min_len); }
471 #endif
472 #endif
473 return bf_pack(pack);
476 #ifndef BUF_TRACK_ALLOC_FREE
477 acc_t *bf_pack(old_acc)
478 #else
479 acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
480 char *clnt_file;
481 int clnt_line;
482 #endif
483 acc_t *old_acc;
485 acc_t *new_acc, *acc_ptr_old, *acc_ptr_new;
486 size_t size, offset_old, offset_new, block_size, block_size_old;
488 /* Check if old acc is good enough. */
489 if (!old_acc || (!old_acc->acc_next && old_acc->acc_linkC == 1 &&
490 old_acc->acc_buffer->buf_linkC == 1))
492 return old_acc;
495 size= bf_bufsize(old_acc);
496 assert(size > 0);
497 new_acc= bf_memreq(size);
498 acc_ptr_old= old_acc;
499 acc_ptr_new= new_acc;
500 offset_old= 0;
501 offset_new= 0;
502 while (size)
504 assert (acc_ptr_old);
505 if (offset_old == acc_ptr_old->acc_length)
507 offset_old= 0;
508 acc_ptr_old= acc_ptr_old->acc_next;
509 continue;
511 assert (offset_old < acc_ptr_old->acc_length);
512 block_size_old= acc_ptr_old->acc_length - offset_old;
513 assert (acc_ptr_new);
514 if (offset_new == acc_ptr_new->acc_length)
516 offset_new= 0;
517 acc_ptr_new= acc_ptr_new->acc_next;
518 continue;
520 assert (offset_new < acc_ptr_new->acc_length);
521 block_size= acc_ptr_new->acc_length - offset_new;
522 if (block_size > block_size_old)
523 block_size= block_size_old;
524 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
525 ptr2acc_data(acc_ptr_old)+offset_old, block_size);
526 offset_new += block_size;
527 offset_old += block_size;
528 size -= block_size;
530 bf_afree(old_acc);
531 return new_acc;
534 #ifndef BUF_TRACK_ALLOC_FREE
535 acc_t *bf_cut (data, offset, length)
536 #else
537 acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
538 char *clnt_file;
539 int clnt_line;
540 #endif
541 register acc_t *data;
542 register unsigned offset;
543 register unsigned length;
545 register acc_t *head, *tail;
547 if (!data && !offset && !length)
548 return NULL;
549 #ifdef BUF_TRACK_ALLOC_FREE
550 assert(data ||
551 (printf("from %s, %d: %u, %u\n",
552 clnt_file, clnt_line, offset, length), 0));
553 #else
554 assert(data);
555 #endif
557 assert(data);
559 if (!length)
561 head= bf_dupacc(data);
562 bf_afree(head->acc_next);
563 head->acc_next= NULL;
564 head->acc_length= 0;
565 return head;
567 while (data && offset>=data->acc_length)
569 offset -= data->acc_length;
570 data= data->acc_next;
573 assert (data);
575 head= bf_dupacc(data);
576 bf_afree(head->acc_next);
577 head->acc_next= NULL;
578 head->acc_offset += offset;
579 head->acc_length -= offset;
580 if (length >= head->acc_length)
581 length -= head->acc_length;
582 else
584 head->acc_length= length;
585 length= 0;
587 tail= head;
588 data= data->acc_next;
589 while (data && length && length>=data->acc_length)
591 tail->acc_next= bf_dupacc(data);
592 tail= tail->acc_next;
593 bf_afree(tail->acc_next);
594 tail->acc_next= NULL;
595 data= data->acc_next;
596 length -= tail->acc_length;
598 if (length)
600 #ifdef bf_cut
601 assert (data ||
602 (printf("bf_cut called from %s:%d\n",
603 clnt_file, clnt_line), 0));
604 #else
605 assert (data);
606 #endif
607 tail->acc_next= bf_dupacc(data);
608 tail= tail->acc_next;
609 bf_afree(tail->acc_next);
610 tail->acc_next= NULL;
611 tail->acc_length= length;
613 return head;
616 #ifndef BUF_TRACK_ALLOC_FREE
617 acc_t *bf_delhead (data, offset)
618 #else
619 acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
620 char *clnt_file;
621 int clnt_line;
622 #endif
623 register acc_t *data;
624 register unsigned offset;
626 acc_t *new_acc;
628 assert(data);
630 /* Find the acc we need to modify. */
631 new_acc= data;
632 while(offset >= new_acc->acc_length)
634 offset -= new_acc->acc_length;
635 new_acc= new_acc->acc_next;
636 #ifdef BUF_TRACK_ALLOC_FREE
637 assert(new_acc || (printf("called from %s, %d\n",
638 clnt_file, clnt_line),0));
639 #else
640 assert(new_acc);
641 #endif
644 /* Discard the old acc(s) */
645 if (new_acc != data)
647 new_acc->acc_linkC++;
648 bf_afree(data);
649 data= new_acc;
652 /* Make sure that acc_linkC == 1 */
653 if (data->acc_linkC != 1)
655 new_acc= bf_dupacc(data);
656 bf_afree(data);
657 data= new_acc;
660 /* Delete the last bit by modifying acc_offset and acc_length */
661 data->acc_offset += offset;
662 data->acc_length -= offset;
663 return data;
667 bf_append
670 #ifndef BUF_TRACK_ALLOC_FREE
671 acc_t *bf_append(data_first, data_second)
672 #else
673 acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
674 char *clnt_file;
675 int clnt_line;
676 #endif
677 acc_t *data_first;
678 acc_t *data_second;
680 acc_t *head, *tail, *new_acc, *acc_ptr_new, tmp_acc, *curr;
681 char *src_ptr, *dst_ptr;
682 size_t size, offset_old, offset_new, block_size_old, block_size;
684 if (!data_first)
685 return data_second;
686 if (!data_second)
687 return data_first;
689 head= NULL;
690 tail= NULL;
691 while (data_first)
693 if (data_first->acc_linkC == 1)
694 curr= data_first;
695 else
697 curr= bf_dupacc(data_first);
698 assert (curr->acc_linkC == 1);
699 bf_afree(data_first);
701 data_first= curr->acc_next;
702 if (!curr->acc_length)
704 curr->acc_next= NULL;
705 bf_afree(curr);
706 continue;
708 if (!head)
709 head= curr;
710 else
711 tail->acc_next= curr;
712 tail= curr;
714 if (!head)
715 return data_second;
716 tail->acc_next= NULL;
718 while (data_second && !data_second->acc_length)
720 curr= data_second;
721 data_second= data_second->acc_next;
722 if (data_second)
723 data_second->acc_linkC++;
724 bf_afree(curr);
726 if (!data_second)
727 return head;
729 if (tail->acc_length + data_second->acc_length >
730 tail->acc_buffer->buf_size)
732 tail->acc_next= data_second;
733 return head;
736 if (tail->acc_buffer->buf_size == bf_buf_gran &&
737 tail->acc_buffer->buf_linkC == 1)
739 if (tail->acc_offset)
741 memmove(tail->acc_buffer->buf_data_p,
742 ptr2acc_data(tail), tail->acc_length);
743 tail->acc_offset= 0;
745 dst_ptr= ptr2acc_data(tail) + tail->acc_length;
746 src_ptr= ptr2acc_data(data_second);
747 memcpy(dst_ptr, src_ptr, data_second->acc_length);
748 tail->acc_length += data_second->acc_length;
749 tail->acc_next= data_second->acc_next;
750 if (data_second->acc_next)
751 data_second->acc_next->acc_linkC++;
752 bf_afree(data_second);
753 return head;
756 new_acc= bf_small_memreq(tail->acc_length+data_second->acc_length);
757 acc_ptr_new= new_acc;
758 offset_old= 0;
759 offset_new= 0;
760 size= tail->acc_length;
761 while (size)
763 assert (acc_ptr_new);
764 if (offset_new == acc_ptr_new->acc_length)
766 offset_new= 0;
767 acc_ptr_new= acc_ptr_new->acc_next;
768 continue;
770 assert (offset_new < acc_ptr_new->acc_length);
771 assert (offset_old < tail->acc_length);
772 block_size_old= tail->acc_length - offset_old;
773 block_size= acc_ptr_new->acc_length - offset_new;
774 if (block_size > block_size_old)
775 block_size= block_size_old;
776 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
777 ptr2acc_data(tail)+offset_old, block_size);
778 offset_new += block_size;
779 offset_old += block_size;
780 size -= block_size;
782 offset_old= 0;
783 size= data_second->acc_length;
784 while (size)
786 assert (acc_ptr_new);
787 if (offset_new == acc_ptr_new->acc_length)
789 offset_new= 0;
790 acc_ptr_new= acc_ptr_new->acc_next;
791 continue;
793 assert (offset_new < acc_ptr_new->acc_length);
794 assert (offset_old < data_second->acc_length);
795 block_size_old= data_second->acc_length - offset_old;
796 block_size= acc_ptr_new->acc_length - offset_new;
797 if (block_size > block_size_old)
798 block_size= block_size_old;
799 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
800 ptr2acc_data(data_second)+offset_old, block_size);
801 offset_new += block_size;
802 offset_old += block_size;
803 size -= block_size;
805 tmp_acc= *tail;
806 *tail= *new_acc;
807 *new_acc= tmp_acc;
809 bf_afree(new_acc);
810 while (tail->acc_next)
811 tail= tail->acc_next;
813 tail->acc_next= data_second->acc_next;
814 if (data_second->acc_next)
815 data_second->acc_next->acc_linkC++;
816 bf_afree(data_second);
817 return head;
820 #if BUF512_NR
821 static void bf_512free(acc)
822 acc_t *acc;
824 #ifdef BUF_CONSISTENCY_CHECK
825 if (inet_buf_debug)
826 memset(acc->acc_buffer->buf_data_p, 0xa5, 512);
827 #endif
828 acc->acc_next= buf512_freelist;
829 buf512_freelist= acc;
831 #endif
832 #if BUF2K_NR
833 static void bf_2Kfree(acc)
834 acc_t *acc;
836 #ifdef BUF_CONSISTENCY_CHECK
837 if (inet_buf_debug)
838 memset(acc->acc_buffer->buf_data_p, 0xa5, 2*1024);
839 #endif
840 acc->acc_next= buf2K_freelist;
841 buf2K_freelist= acc;
843 #endif
844 #if BUF32K_NR
845 static void bf_32Kfree(acc)
846 acc_t *acc;
848 #ifdef BUF_CONSISTENCY_CHECK
849 if (inet_buf_debug)
850 memset(acc->acc_buffer->buf_data_p, 0xa5, 32*1024);
851 #endif
852 acc->acc_next= buf32K_freelist;
853 buf32K_freelist= acc;
855 #endif
857 #ifdef BUF_CONSISTENCY_CHECK
858 int bf_consistency_check()
860 acc_t *acc;
861 int silent;
862 int error;
863 int i;
865 buf_generation++;
867 for (i=0; i<CLIENT_NR; i++)
869 if (checkreq[i])
870 (*checkreq[i])();
873 /* Add information about free accessors */
874 for(acc= acc_freelist; acc; acc= acc->acc_next)
876 if (acc->acc_generation == buf_generation-1)
878 acc->acc_generation= buf_generation;
879 acc->acc_check_linkC= 0;
881 else
883 assert(acc->acc_generation == buf_generation &&
884 acc->acc_check_linkC > 0);
885 acc->acc_check_linkC= -acc->acc_check_linkC;
889 #if BUF512_NR
890 count_free_bufs(buf512_freelist);
891 #endif
892 #if BUF2K_NR
893 count_free_bufs(buf2K_freelist);
894 #endif
895 #if BUF32K_NR
896 count_free_bufs(buf32K_freelist);
897 #endif
899 error= 0;
901 /* Report about accessors */
902 silent= 0;
903 for (i=0, acc= accessors; i<ACC_NR; i++, acc++)
905 if (acc->acc_generation != buf_generation)
907 error++;
908 assert(acc->acc_generation == buf_generation-1);
909 acc->acc_generation= buf_generation;
910 if (!silent)
912 printf(
913 "acc[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
914 i, acc, acc->acc_linkC, acc->acc_alloc_file, acc->acc_alloc_line);
915 #if 0
916 silent= 1;
917 #endif
919 continue;
921 if (acc->acc_check_linkC == acc->acc_linkC)
922 continue;
923 error++;
924 if (acc->acc_check_linkC < 0)
926 if (!silent)
928 printf(
929 "acc[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
930 i, acc->acc_alloc_file, acc->acc_alloc_line,
931 acc->acc_free_file, acc->acc_free_line);
933 acc->acc_check_linkC= -acc->acc_check_linkC;
934 if (acc->acc_check_linkC == acc->acc_linkC)
936 silent= 1;
937 continue;
940 if (!silent)
942 printf(
943 "# of tracked links (%d) for acc[%d] don't match with stored link count %d\n",
944 acc->acc_check_linkC, i, acc->acc_linkC);
945 printf("acc[%d] was allocated at %s, %d\n",
946 i, acc->acc_alloc_file, acc->acc_alloc_line);
947 silent=1;
951 /* Report about buffers */
952 #if BUF512_NR
954 for (i= 0; i<BUF512_NR; i++)
956 error |= report_buffer(&buffers512[i].buf_header,
957 "512-buffer", i);
960 #endif
961 #if BUF2K_NR
963 for (i= 0; i<BUF2K_NR; i++)
965 error |= report_buffer(&buffers2K[i].buf_header,
966 "2K-buffer", i);
969 #endif
970 #if BUF32K_NR
972 for (i= 0; i<BUF32K_NR; i++)
974 error |= report_buffer(&buffers32K[i].buf_header,
975 "32K-buffer", i);
978 #endif
980 return !error;
983 static void count_free_bufs(list)
984 acc_t *list;
986 acc_t *acc;
987 buf_t *buf;
989 for(acc= list; acc; acc= acc->acc_next)
991 if (acc->acc_generation != buf_generation-1)
993 assert(acc->acc_generation == buf_generation &&
994 acc->acc_check_linkC > 0);
995 acc->acc_check_linkC= -acc->acc_check_linkC;
996 continue;
998 acc->acc_generation= buf_generation;
999 acc->acc_check_linkC= 0;
1001 buf= acc->acc_buffer;
1002 if (buf->buf_generation == buf_generation-1)
1004 buf->buf_generation= buf_generation;
1005 buf->buf_check_linkC= 0;
1006 continue;
1008 assert(buf->buf_generation == buf_generation &&
1009 buf->buf_check_linkC > 0);
1010 buf->buf_check_linkC= -buf->buf_check_linkC;
1014 static int report_buffer(buf, label, i)
1015 buf_t *buf;
1016 char *label;
1017 int i;
1019 if (buf->buf_generation != buf_generation)
1021 assert(buf->buf_generation == buf_generation-1);
1022 buf->buf_generation= buf_generation;
1023 printf(
1024 "%s[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
1025 label, i, buf,
1026 buf->buf_linkC, buf->buf_alloc_file,
1027 buf->buf_alloc_line);
1028 return 1;
1030 if (buf->buf_check_linkC == buf->buf_linkC)
1031 return 0;
1032 if (buf->buf_check_linkC < 0)
1034 printf(
1035 "%s[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
1036 label, i, buf->buf_alloc_file, buf->buf_alloc_line,
1037 buf->buf_free_file, buf->buf_free_line);
1038 buf->buf_check_linkC= -buf->buf_check_linkC;
1039 if (buf->buf_check_linkC == buf->buf_linkC)
1040 return 1;
1042 printf(
1043 "# of tracked links (%d) for %s[%d] don't match with stored link count %d\n",
1044 buf->buf_check_linkC, label, i, buf->buf_linkC);
1045 printf("%s[%d] was allocated at %s, %d\n",
1046 label, i, buf->buf_alloc_file, buf->buf_alloc_line);
1047 return 1;
1050 void bf_check_acc(acc)
1051 acc_t *acc;
1053 buf_t *buf;
1055 while(acc != NULL)
1057 if (acc->acc_generation == buf_generation)
1059 assert(acc->acc_check_linkC > 0);
1060 acc->acc_check_linkC++;
1061 return;
1063 assert(acc->acc_generation == buf_generation-1);
1064 acc->acc_generation= buf_generation;
1065 acc->acc_check_linkC= 1;
1067 buf= acc->acc_buffer;
1068 if (buf->buf_generation == buf_generation)
1070 assert(buf->buf_check_linkC > 0);
1071 buf->buf_check_linkC++;
1073 else
1075 assert(buf->buf_generation == buf_generation-1);
1076 buf->buf_generation= buf_generation;
1077 buf->buf_check_linkC= 1;
1080 acc= acc->acc_next;
1084 void _bf_mark_1acc(clnt_file, clnt_line, acc)
1085 char *clnt_file;
1086 int clnt_line;
1087 acc_t *acc;
1089 acc->acc_alloc_file= clnt_file;
1090 acc->acc_alloc_line= clnt_line;
1093 void _bf_mark_acc(clnt_file, clnt_line, acc)
1094 char *clnt_file;
1095 int clnt_line;
1096 acc_t *acc;
1098 buf_t *buf;
1100 for (; acc; acc= acc->acc_next)
1102 acc->acc_alloc_file= clnt_file;
1103 acc->acc_alloc_line= clnt_line;
1104 buf= acc->acc_buffer;
1105 buf->buf_alloc_file= clnt_file;
1106 buf->buf_alloc_line= clnt_line;
1109 #endif
1111 int bf_linkcheck(acc)
1112 acc_t *acc;
1114 int i;
1116 buf_t *buffer;
1117 for (i= 0; i<ACC_NR && acc; i++, acc= acc->acc_next)
1119 if (acc->acc_linkC <= 0)
1121 printf("wrong acc_linkC (%d) for acc %p\n",
1122 acc->acc_linkC, acc);
1123 return 0;
1125 if (acc->acc_offset < 0)
1127 printf("wrong acc_offset (%d) for acc %p\n",
1128 acc->acc_offset, acc);
1129 return 0;
1131 if (acc->acc_length < 0)
1133 printf("wrong acc_length (%d) for acc %p\n",
1134 acc->acc_length, acc);
1135 return 0;
1137 buffer= acc->acc_buffer;
1138 if (buffer == NULL)
1140 printf("no buffer for acc %p\n", acc);
1141 return 0;
1143 if (buffer->buf_linkC <= 0)
1145 printf(
1146 "wrong buf_linkC (%d) for buffer %p, from acc %p\n",
1147 buffer->buf_linkC, buffer, acc);
1148 return 0;
1150 if (acc->acc_offset + acc->acc_length > buffer->buf_size)
1152 printf("%d + %d > %d for buffer %p, and acc %p\n",
1153 acc->acc_offset, acc->acc_length,
1154 buffer->buf_size, buffer, acc);
1155 return 0;
1158 if (acc != NULL)
1160 printf("loop\n");
1161 return 0;
1163 return 1;
1166 static void free_accs()
1168 int i, j;
1170 DBLOCK(1, printf("free_accs\n"));
1172 assert(bf_linkcheck(bf_linkcheck_acc));
1173 for (i=0; !acc_freelist && i<MAX_BUFREQ_PRI; i++)
1175 for (j=0; j<CLIENT_NR; j++)
1177 bf_free_bufsize= 0;
1178 if (freereq[j])
1180 (*freereq[j])(i);
1181 assert(bf_linkcheck(bf_linkcheck_acc) ||
1182 (printf("just called %p\n",
1183 freereq[i]),0));
1187 #if DEBUG
1188 printf("last level was level %d\n", i-1);
1189 #endif
1192 #ifndef BUF_TRACK_ALLOC_FREE
1193 acc_t *bf_align(acc, size, alignment)
1194 #else
1195 acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
1196 char *clnt_file;
1197 int clnt_line;
1198 #endif
1199 acc_t *acc;
1200 size_t size;
1201 size_t alignment;
1203 char *ptr;
1204 size_t buf_size;
1205 acc_t *head, *tail;
1207 /* Fast check if the buffer is aligned already. */
1208 if (acc->acc_length >= size)
1210 ptr= ptr2acc_data(acc);
1211 if (((unsigned)ptr & (alignment-1)) == 0)
1212 return acc;
1214 buf_size= bf_bufsize(acc);
1215 #ifdef bf_align
1216 assert((size != 0 && buf_size != 0) ||
1217 (printf("bf_align(..., %d, %d) from %s, %d\n",
1218 size, alignment, clnt_file, clnt_line),0));
1219 #else
1220 assert(size != 0 && buf_size != 0);
1221 #endif
1222 if (buf_size <= size)
1224 acc= bf_pack(acc);
1225 return acc;
1227 head= bf_cut(acc, 0, size);
1228 tail= bf_cut(acc, size, buf_size-size);
1229 bf_afree(acc);
1230 head= bf_pack(head);
1231 assert(head->acc_next == NULL);
1232 head->acc_next= tail;
1233 return head;
1236 #if 0
1237 int chk_acc(acc)
1238 acc_t *acc;
1240 int acc_nr;
1242 if (!acc)
1243 return 1;
1244 if (acc < accessors || acc >= &accessors[ACC_NR])
1245 return 0;
1246 acc_nr= acc-accessors;
1247 return acc == &accessors[acc_nr];
1249 #endif
1252 * $PchId: buf.c,v 1.19 2003/09/10 08:54:23 philip Exp $