FreeBSD/Linux Kernel Cross Reference
sys/servers/inet/buf.c
1 /*
2 This file contains routines for buffer management.
3
4 Copyright 1995 Philip Homburg
5 */
6
7 #define BUF_IMPLEMENTATION 1 /* Avoid some macros */
8
9 #include "inet.h"
10
11 #include <stdlib.h>
12 #include <string.h>
13
14 #include "generic/assert.h"
15 #include "generic/buf.h"
16 #include "generic/type.h"
17
18 THIS_FILE
19
20 #ifndef BUF_USEMALLOC
21 #define BUF_USEMALLOC 0
22 #endif
23
24 #ifndef BUF512_NR
25 #define BUF512_NR 512
26 #endif
27 #ifndef BUF2K_NR
28 #define BUF2K_NR 0
29 #endif
30 #ifndef BUF32K_NR
31 #define BUF32K_NR 0
32 #endif
33
34 #define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
35 #define CLIENT_NR 7
36
37 #define DECLARE_TYPE(Tag, Type, Size) \
38 typedef struct Tag \
39 { \
40 buf_t buf_header; \
41 char buf_data[Size]; \
42 } Type
43
44 #if BUF_USEMALLOC
45 #define DECLARE_STORAGE(Type, Ident, Nitems) \
46 PRIVATE Type *Ident
47
48 #define ALLOC_STORAGE(Ident, Nitems, Label) \
49 do \
50 { \
51 printf("buf.c: malloc %d %s\n", Nitems, Label); \
52 Ident= malloc(sizeof(*Ident) * Nitems); \
53 if (!Ident) \
54 ip_panic(( "unable to alloc %s", Label )); \
55 } while(0)
56 #else
57 #define DECLARE_STORAGE(Type, Ident, Nitems) \
58 PRIVATE Type Ident[Nitems]
59
60 #define ALLOC_STORAGE(Ident, Nitems, Label) \
61 (void)0
62 #endif
63
64 #if BUF512_NR
65 DECLARE_TYPE(buf512, buf512_t, 512);
66 PRIVATE acc_t *buf512_freelist;
67 DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
68 FORWARD void bf_512free ARGS(( acc_t *acc ));
69 #endif
70 #if BUF2K_NR
71 DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
72 PRIVATE acc_t *buf2K_freelist;
73 DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
74 FORWARD void bf_2Kfree ARGS(( acc_t *acc ));
75 #endif
76 #if BUF32K_NR
77 DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
78 PRIVATE acc_t *buf32K_freelist;
79 DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
80 FORWARD void bf_32Kfree ARGS(( acc_t *acc ));
81 #endif
82
83 PRIVATE acc_t *acc_freelist;
84 DECLARE_STORAGE(acc_t, accessors, ACC_NR);
85
86 PRIVATE bf_freereq_t freereq[CLIENT_NR];
87 PRIVATE size_t bf_buf_gran;
88
89 PUBLIC size_t bf_free_bufsize;
90 PUBLIC acc_t *bf_temporary_acc;
91 PUBLIC acc_t *bf_linkcheck_acc;
92
93 #ifdef BUF_CONSISTENCY_CHECK
94 int inet_buf_debug;
95 unsigned buf_generation;
96 PRIVATE bf_checkreq_t checkreq[CLIENT_NR];
97 #endif
98
99 #ifndef BUF_TRACK_ALLOC_FREE
100 FORWARD acc_t *bf_small_memreq ARGS(( size_t size ));
101 #else
102 FORWARD acc_t *_bf_small_memreq ARGS(( char *clnt_file, int clnt_line,
103 size_t size ));
104 #define bf_small_memreq(a) _bf_small_memreq(clnt_file, clnt_line, a)
105 #endif
106 FORWARD void free_accs ARGS(( void ));
107 #ifdef BUF_CONSISTENCY_CHECK
108 FORWARD void count_free_bufs ARGS(( acc_t *list ));
109 FORWARD int report_buffer ARGS(( buf_t *buf, char *label, int i ));
110 #endif
111
112 PUBLIC void bf_init()
113 {
114 int i;
115 size_t buf_s;
116 acc_t *acc;
117
118 bf_buf_gran= BUF_S;
119 buf_s= 0;
120
121 for (i=0;i<CLIENT_NR;i++)
122 freereq[i]=0;
123 #ifdef BUF_CONSISTENCY_CHECK
124 for (i=0;i<CLIENT_NR;i++)
125 checkreq[i]=0;
126 #endif
127
128 #if BUF512_NR
129 ALLOC_STORAGE(buffers512, BUF512_NR, "512B-buffers");
130 #endif
131 #if BUF2K_NR
132 ALLOC_STORAGE(buffers2K, BUF2K_NR, "2K-buffers");
133 #endif
134 #if BUF32K_NR
135 ALLOC_STORAGE(buffers32K, BUF32K_NR, "32K-buffers");
136 #endif
137 ALLOC_STORAGE(accessors, ACC_NR, "accs");
138
139 acc_freelist= NULL;
140 for (i=0;i<ACC_NR;i++)
141 {
142 memset(&accessors[i], '\0', sizeof(accessors[i]));
143
144 accessors[i].acc_linkC= 0;
145 accessors[i].acc_next= acc_freelist;
146 acc_freelist= &accessors[i];
147 }
148
149 #define INIT_BUFFERS(Ident, Nitems, Freelist, Freefunc) \
150 do \
151 { \
152 Freelist= NULL; \
153 for (i=0;i<Nitems;i++) \
154 { \
155 acc= acc_freelist; \
156 if (!acc) \
157 ip_panic(( "fewer accessors than buffers")); \
158 acc_freelist= acc->acc_next; \
159 acc->acc_linkC= 0; \
160 \
161 memset(&Ident[i], '\0', sizeof(Ident[i])); \
162 Ident[i].buf_header.buf_linkC= 0; \
163 Ident[i].buf_header.buf_free= Freefunc; \
164 Ident[i].buf_header.buf_size= \
165 sizeof(Ident[i].buf_data); \
166 Ident[i].buf_header.buf_data_p= \
167 Ident[i].buf_data; \
168 \
169 acc->acc_buffer= &Ident[i].buf_header; \
170 acc->acc_next= Freelist; \
171 Freelist= acc; \
172 } \
173 if (sizeof(Ident[0].buf_data) < bf_buf_gran) \
174 bf_buf_gran= sizeof(Ident[0].buf_data); \
175 if (sizeof(Ident[0].buf_data) > buf_s) \
176 buf_s= sizeof(Ident[0].buf_data); \
177 } while(0)
178
179 #if BUF512_NR
180 INIT_BUFFERS(buffers512, BUF512_NR, buf512_freelist, bf_512free);
181 #endif
182 #if BUF2K_NR
183 INIT_BUFFERS(buffers2K, BUF2K_NR, buf2K_freelist, bf_2Kfree);
184 #endif
185 #if BUF32K_NR
186 INIT_BUFFERS(buffers32K, BUF32K_NR, buf32K_freelist, bf_32Kfree);
187 #endif
188
189 #undef INIT_BUFFERS
190
191 assert (buf_s == BUF_S);
192 }
193
194 #ifndef BUF_CONSISTENCY_CHECK
195 PUBLIC void bf_logon(func)
196 bf_freereq_t func;
197 #else
198 PUBLIC void bf_logon(func, checkfunc)
199 bf_freereq_t func;
200 bf_checkreq_t checkfunc;
201 #endif
202 {
203 int i;
204
205 for (i=0;i<CLIENT_NR;i++)
206 if (!freereq[i])
207 {
208 freereq[i]=func;
209 #ifdef BUF_CONSISTENCY_CHECK
210 checkreq[i]= checkfunc;
211 #endif
212 return;
213 }
214
215 ip_panic(( "buf.c: too many clients" ));
216 }
217
218 /*
219 bf_memreq
220 */
221
222 #ifndef BUF_TRACK_ALLOC_FREE
223 PUBLIC acc_t *bf_memreq(size)
224 #else
225 PUBLIC acc_t *_bf_memreq(clnt_file, clnt_line, size)
226 char *clnt_file;
227 int clnt_line;
228 #endif
229 size_t size;
230 {
231 acc_t *head, *tail, *new_acc;
232 buf_t *buf;
233 int i,j;
234 size_t count;
235
236 assert (size>0);
237
238 head= NULL;
239 tail= NULL;
240 while (size)
241 {
242 new_acc= NULL;
243
244 /* Note the tricky dangling else... */
245 #define ALLOC_BUF(Freelist, Bufsize) \
246 if (Freelist && (Bufsize == BUF_S || size <= Bufsize)) \
247 { \
248 new_acc= Freelist; \
249 Freelist= new_acc->acc_next; \
250 \
251 assert(new_acc->acc_linkC == 0); \
252 new_acc->acc_linkC= 1; \
253 buf= new_acc->acc_buffer; \
254 assert(buf->buf_linkC == 0); \
255 buf->buf_linkC= 1; \
256 } \
257 else
258
259 /* Sort attempts by buffer size */
260 #if BUF512_NR
261 ALLOC_BUF(buf512_freelist, 512)
262 #endif
263 #if BUF2K_NR
264 ALLOC_BUF(buf2K_freelist, 2*1024)
265 #endif
266 #if BUF32K_NR
267 ALLOC_BUF(buf32K_freelist, 32*1024)
268 #endif
269 #undef ALLOC_BUF
270 {
271 DBLOCK(2, printf("freeing buffers\n"));
272
273 bf_free_bufsize= 0;
274 for (i=0; bf_free_bufsize<size && i<MAX_BUFREQ_PRI;
275 i++)
276 {
277 for (j=0; j<CLIENT_NR; j++)
278 {
279 if (freereq[j])
280 (*freereq[j])(i);
281 }
282 #if DEBUG && 0
283 { acc_t *acc;
284 j= 0; for(acc= buf512_freelist; acc; acc= acc->acc_next) j++;
285 printf("# of free 512-bytes buffer is now %d\n", j); }
286 #endif
287 }
288 #if DEBUG && 0
289 { printf("last level was level %d\n", i-1); }
290 #endif
291 if (bf_free_bufsize<size)
292 ip_panic(( "not enough buffers freed" ));
293
294 continue;
295 }
296
297 #ifdef BUF_TRACK_ALLOC_FREE
298 new_acc->acc_alloc_file= clnt_file;
299 new_acc->acc_alloc_line= clnt_line;
300 buf->buf_alloc_file= clnt_file;
301 buf->buf_alloc_line= clnt_line;
302 #endif
303
304 if (!head)
305 head= new_acc;
306 else
307 tail->acc_next= new_acc;
308 tail= new_acc;
309
310 count= tail->acc_buffer->buf_size;
311 if (count > size)
312 count= size;
313
314 tail->acc_offset= 0;
315 tail->acc_length= count;
316 size -= count;
317 }
318 tail->acc_next= NULL;
319
320 return head;
321 }
322
323 /*
324 bf_small_memreq
325 */
326
327 #ifndef BUF_TRACK_ALLOC_FREE
328 PRIVATE acc_t *bf_small_memreq(size)
329 #else
330 PRIVATE acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
331 char *clnt_file;
332 int clnt_line;
333 #endif
334 size_t size;
335 {
336 return bf_memreq(size);
337 }
338
339 #ifndef BUF_TRACK_ALLOC_FREE
340 PUBLIC void bf_afree(acc)
341 #else
342 PUBLIC void _bf_afree(clnt_file, clnt_line, acc)
343 char *clnt_file;
344 int clnt_line;
345 #endif
346 acc_t *acc;
347 {
348 acc_t *next_acc;
349 buf_t *buf;
350
351 while (acc)
352 {
353 #if defined(bf_afree)
354 DIFBLOCK(1, (acc->acc_linkC <= 0),
355 printf("clnt_file= %s, clnt_line= %d\n",
356 clnt_file, clnt_line));
357 #endif
358 assert (acc->acc_linkC>0);
359 if (--acc->acc_linkC > 0)
360 break;
361
362 #ifdef BUF_TRACK_ALLOC_FREE
363 acc->acc_free_file= clnt_file;
364 acc->acc_free_line= clnt_line;
365 #endif
366 buf= acc->acc_buffer;
367 assert (buf);
368
369 #if defined(bf_afree)
370 DIFBLOCK(1, (buf->buf_linkC == 0),
371 printf("clnt_file= %s, clnt_line= %d\n",
372 clnt_file, clnt_line));
373 #endif
374 assert (buf->buf_linkC>0);
375 if (--buf->buf_linkC > 0)
376 {
377 acc->acc_buffer= NULL;
378 next_acc= acc->acc_next;
379 acc->acc_next= acc_freelist;
380 acc_freelist= acc;
381 #ifdef BUF_CONSISTENCY_CHECK
382 if (inet_buf_debug)
383 {
384 acc->acc_offset= 0xdeadbeaf;
385 acc->acc_length= 0xdeadbeaf;
386 acc->acc_buffer= (buf_t *)0xdeadbeaf;
387 acc->acc_ext_link= (acc_t *)0xdeadbeaf;
388 }
389 #endif
390 acc= next_acc;
391 continue;
392 }
393
394 bf_free_bufsize += buf->buf_size;
395 #ifdef BUF_TRACK_ALLOC_FREE
396 buf->buf_free_file= clnt_file;
397 buf->buf_free_line= clnt_line;
398 #endif
399 next_acc= acc->acc_next;
400 buf->buf_free(acc);
401 acc= next_acc;
402 continue;
403 }
404 }
405
406 #ifndef BUF_TRACK_ALLOC_FREE
407 PUBLIC acc_t *bf_dupacc(acc_ptr)
408 #else
409 PUBLIC acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
410 char *clnt_file;
411 int clnt_line;
412 #endif
413 register acc_t *acc_ptr;
414 {
415 register acc_t *new_acc;
416
417 if (!acc_freelist)
418 {
419 free_accs();
420 if (!acc_freelist)
421 ip_panic(( "buf.c: out of accessors" ));
422 }
423 new_acc= acc_freelist;
424 acc_freelist= new_acc->acc_next;
425
426 *new_acc= *acc_ptr;
427 if (acc_ptr->acc_next)
428 acc_ptr->acc_next->acc_linkC++;
429 if (acc_ptr->acc_buffer)
430 acc_ptr->acc_buffer->buf_linkC++;
431 new_acc->acc_linkC= 1;
432 #ifdef BUF_TRACK_ALLOC_FREE
433 new_acc->acc_alloc_file= clnt_file;
434 new_acc->acc_alloc_line= clnt_line;
435 #endif
436 return new_acc;
437 }
438
439 PUBLIC size_t bf_bufsize(acc_ptr)
440 register acc_t *acc_ptr;
441 {
442 register size_t size;
443
444 assert(acc_ptr);
445
446 size=0;
447
448 while (acc_ptr)
449 {
450 assert(acc_ptr >= accessors && acc_ptr <= &accessors[ACC_NR-1]);
451 size += acc_ptr->acc_length;
452 acc_ptr= acc_ptr->acc_next;
453 }
454 return size;
455 }
456
457 #ifndef BUF_TRACK_ALLOC_FREE
458 PUBLIC acc_t *bf_packIffLess(pack, min_len)
459 #else
460 PUBLIC acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
461 char *clnt_file;
462 int clnt_line;
463 #endif
464 acc_t *pack;
465 int min_len;
466 {
467 if (!pack || pack->acc_length >= min_len)
468 return pack;
469
470 #if DEBUG
471 #ifdef bf_packIffLess
472 { where(); printf("calling bf_pack because of %s %d: %d\n", bf_pack_file,
473 bf_pack_line, min_len); }
474 #endif
475 #endif
476 return bf_pack(pack);
477 }
478
479 #ifndef BUF_TRACK_ALLOC_FREE
480 PUBLIC acc_t *bf_pack(old_acc)
481 #else
482 PUBLIC acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
483 char *clnt_file;
484 int clnt_line;
485 #endif
486 acc_t *old_acc;
487 {
488 acc_t *new_acc, *acc_ptr_old, *acc_ptr_new;
489 size_t size, offset_old, offset_new, block_size, block_size_old;
490
491 /* Check if old acc is good enough. */
492 if (!old_acc || (!old_acc->acc_next && old_acc->acc_linkC == 1 &&
493 old_acc->acc_buffer->buf_linkC == 1))
494 {
495 return old_acc;
496 }
497
498 size= bf_bufsize(old_acc);
499 assert(size > 0);
500 new_acc= bf_memreq(size);
501 acc_ptr_old= old_acc;
502 acc_ptr_new= new_acc;
503 offset_old= 0;
504 offset_new= 0;
505 while (size)
506 {
507 assert (acc_ptr_old);
508 if (offset_old == acc_ptr_old->acc_length)
509 {
510 offset_old= 0;
511 acc_ptr_old= acc_ptr_old->acc_next;
512 continue;
513 }
514 assert (offset_old < acc_ptr_old->acc_length);
515 block_size_old= acc_ptr_old->acc_length - offset_old;
516 assert (acc_ptr_new);
517 if (offset_new == acc_ptr_new->acc_length)
518 {
519 offset_new= 0;
520 acc_ptr_new= acc_ptr_new->acc_next;
521 continue;
522 }
523 assert (offset_new < acc_ptr_new->acc_length);
524 block_size= acc_ptr_new->acc_length - offset_new;
525 if (block_size > block_size_old)
526 block_size= block_size_old;
527 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
528 ptr2acc_data(acc_ptr_old)+offset_old, block_size);
529 offset_new += block_size;
530 offset_old += block_size;
531 size -= block_size;
532 }
533 bf_afree(old_acc);
534 return new_acc;
535 }
536
537 #ifndef BUF_TRACK_ALLOC_FREE
538 PUBLIC acc_t *bf_cut (data, offset, length)
539 #else
540 PUBLIC acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
541 char *clnt_file;
542 int clnt_line;
543 #endif
544 register acc_t *data;
545 register unsigned offset;
546 register unsigned length;
547 {
548 register acc_t *head, *tail;
549
550 if (!data && !offset && !length)
551 return NULL;
552 #ifdef BUF_TRACK_ALLOC_FREE
553 assert(data ||
554 (printf("from %s, %d: %u, %u\n",
555 clnt_file, clnt_line, offset, length), 0));
556 #else
557 assert(data);
558 #endif
559
560 assert(data);
561
562 if (!length)
563 {
564 head= bf_dupacc(data);
565 bf_afree(head->acc_next);
566 head->acc_next= NULL;
567 head->acc_length= 0;
568 return head;
569 }
570 while (data && offset>=data->acc_length)
571 {
572 offset -= data->acc_length;
573 data= data->acc_next;
574 }
575
576 assert (data);
577
578 head= bf_dupacc(data);
579 bf_afree(head->acc_next);
580 head->acc_next= NULL;
581 head->acc_offset += offset;
582 head->acc_length -= offset;
583 if (length >= head->acc_length)
584 length -= head->acc_length;
585 else
586 {
587 head->acc_length= length;
588 length= 0;
589 }
590 tail= head;
591 data= data->acc_next;
592 while (data && length && length>=data->acc_length)
593 {
594 tail->acc_next= bf_dupacc(data);
595 tail= tail->acc_next;
596 bf_afree(tail->acc_next);
597 tail->acc_next= NULL;
598 data= data->acc_next;
599 length -= tail->acc_length;
600 }
601 if (length)
602 {
603 #ifdef bf_cut
604 assert (data ||
605 (printf("bf_cut called from %s:%d\n",
606 clnt_file, clnt_line), 0));
607 #else
608 assert (data);
609 #endif
610 tail->acc_next= bf_dupacc(data);
611 tail= tail->acc_next;
612 bf_afree(tail->acc_next);
613 tail->acc_next= NULL;
614 tail->acc_length= length;
615 }
616 return head;
617 }
618
619 #ifndef BUF_TRACK_ALLOC_FREE
620 PUBLIC acc_t *bf_delhead (data, offset)
621 #else
622 PUBLIC acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
623 char *clnt_file;
624 int clnt_line;
625 #endif
626 register acc_t *data;
627 register unsigned offset;
628 {
629 acc_t *new_acc;
630
631 assert(data);
632
633 /* Find the acc we need to modify. */
634 new_acc= data;
635 while(offset >= new_acc->acc_length)
636 {
637 offset -= new_acc->acc_length;
638 new_acc= new_acc->acc_next;
639 #ifdef BUF_TRACK_ALLOC_FREE
640 assert(new_acc || (printf("called from %s, %d\n",
641 clnt_file, clnt_line),0));
642 #else
643 assert(new_acc);
644 #endif
645 }
646
647 /* Discard the old acc(s) */
648 if (new_acc != data)
649 {
650 new_acc->acc_linkC++;
651 bf_afree(data);
652 data= new_acc;
653 }
654
655 /* Make sure that acc_linkC == 1 */
656 if (data->acc_linkC != 1)
657 {
658 new_acc= bf_dupacc(data);
659 bf_afree(data);
660 data= new_acc;
661 }
662
663 /* Delete the last bit by modifying acc_offset and acc_length */
664 data->acc_offset += offset;
665 data->acc_length -= offset;
666 return data;
667 }
668
669 /*
670 bf_append
671 */
672
673 #ifndef BUF_TRACK_ALLOC_FREE
674 PUBLIC acc_t *bf_append(data_first, data_second)
675 #else
676 PUBLIC acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
677 char *clnt_file;
678 int clnt_line;
679 #endif
680 acc_t *data_first;
681 acc_t *data_second;
682 {
683 acc_t *head, *tail, *new_acc, *acc_ptr_new, tmp_acc, *curr;
684 char *src_ptr, *dst_ptr;
685 size_t size, offset_old, offset_new, block_size_old, block_size;
686
687 if (!data_first)
688 return data_second;
689 if (!data_second)
690 return data_first;
691
692 head= NULL;
693 tail= NULL;
694 while (data_first)
695 {
696 if (data_first->acc_linkC == 1)
697 curr= data_first;
698 else
699 {
700 curr= bf_dupacc(data_first);
701 assert (curr->acc_linkC == 1);
702 bf_afree(data_first);
703 }
704 data_first= curr->acc_next;
705 if (!curr->acc_length)
706 {
707 curr->acc_next= NULL;
708 bf_afree(curr);
709 continue;
710 }
711 if (!head)
712 head= curr;
713 else
714 tail->acc_next= curr;
715 tail= curr;
716 }
717 if (!head)
718 return data_second;
719 tail->acc_next= NULL;
720
721 while (data_second && !data_second->acc_length)
722 {
723 curr= data_second;
724 data_second= data_second->acc_next;
725 if (data_second)
726 data_second->acc_linkC++;
727 bf_afree(curr);
728 }
729 if (!data_second)
730 return head;
731
732 if (tail->acc_length + data_second->acc_length >
733 tail->acc_buffer->buf_size)
734 {
735 tail->acc_next= data_second;
736 return head;
737 }
738
739 if (tail->acc_buffer->buf_size == bf_buf_gran &&
740 tail->acc_buffer->buf_linkC == 1)
741 {
742 if (tail->acc_offset)
743 {
744 memmove(tail->acc_buffer->buf_data_p,
745 ptr2acc_data(tail), tail->acc_length);
746 tail->acc_offset= 0;
747 }
748 dst_ptr= ptr2acc_data(tail) + tail->acc_length;
749 src_ptr= ptr2acc_data(data_second);
750 memcpy(dst_ptr, src_ptr, data_second->acc_length);
751 tail->acc_length += data_second->acc_length;
752 tail->acc_next= data_second->acc_next;
753 if (data_second->acc_next)
754 data_second->acc_next->acc_linkC++;
755 bf_afree(data_second);
756 return head;
757 }
758
759 new_acc= bf_small_memreq(tail->acc_length+data_second->acc_length);
760 acc_ptr_new= new_acc;
761 offset_old= 0;
762 offset_new= 0;
763 size= tail->acc_length;
764 while (size)
765 {
766 assert (acc_ptr_new);
767 if (offset_new == acc_ptr_new->acc_length)
768 {
769 offset_new= 0;
770 acc_ptr_new= acc_ptr_new->acc_next;
771 continue;
772 }
773 assert (offset_new < acc_ptr_new->acc_length);
774 assert (offset_old < tail->acc_length);
775 block_size_old= tail->acc_length - offset_old;
776 block_size= acc_ptr_new->acc_length - offset_new;
777 if (block_size > block_size_old)
778 block_size= block_size_old;
779 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
780 ptr2acc_data(tail)+offset_old, block_size);
781 offset_new += block_size;
782 offset_old += block_size;
783 size -= block_size;
784 }
785 offset_old= 0;
786 size= data_second->acc_length;
787 while (size)
788 {
789 assert (acc_ptr_new);
790 if (offset_new == acc_ptr_new->acc_length)
791 {
792 offset_new= 0;
793 acc_ptr_new= acc_ptr_new->acc_next;
794 continue;
795 }
796 assert (offset_new < acc_ptr_new->acc_length);
797 assert (offset_old < data_second->acc_length);
798 block_size_old= data_second->acc_length - offset_old;
799 block_size= acc_ptr_new->acc_length - offset_new;
800 if (block_size > block_size_old)
801 block_size= block_size_old;
802 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
803 ptr2acc_data(data_second)+offset_old, block_size);
804 offset_new += block_size;
805 offset_old += block_size;
806 size -= block_size;
807 }
808 tmp_acc= *tail;
809 *tail= *new_acc;
810 *new_acc= tmp_acc;
811
812 bf_afree(new_acc);
813 while (tail->acc_next)
814 tail= tail->acc_next;
815
816 tail->acc_next= data_second->acc_next;
817 if (data_second->acc_next)
818 data_second->acc_next->acc_linkC++;
819 bf_afree(data_second);
820 return head;
821 }
822
823 #if BUF512_NR
824 PRIVATE void bf_512free(acc)
825 acc_t *acc;
826 {
827 #ifdef BUF_CONSISTENCY_CHECK
828 if (inet_buf_debug)
829 memset(acc->acc_buffer->buf_data_p, 0xa5, 512);
830 #endif
831 acc->acc_next= buf512_freelist;
832 buf512_freelist= acc;
833 }
834 #endif
835 #if BUF2K_NR
836 PRIVATE void bf_2Kfree(acc)
837 acc_t *acc;
838 {
839 #ifdef BUF_CONSISTENCY_CHECK
840 if (inet_buf_debug)
841 memset(acc->acc_buffer->buf_data_p, 0xa5, 2*1024);
842 #endif
843 acc->acc_next= buf2K_freelist;
844 buf2K_freelist= acc;
845 }
846 #endif
847 #if BUF32K_NR
848 PRIVATE void bf_32Kfree(acc)
849 acc_t *acc;
850 {
851 #ifdef BUF_CONSISTENCY_CHECK
852 if (inet_buf_debug)
853 memset(acc->acc_buffer->buf_data_p, 0xa5, 32*1024);
854 #endif
855 acc->acc_next= buf32K_freelist;
856 buf32K_freelist= acc;
857 }
858 #endif
859
860 #ifdef BUF_CONSISTENCY_CHECK
861 PUBLIC int bf_consistency_check()
862 {
863 acc_t *acc;
864 int silent;
865 int error;
866 int i;
867
868 buf_generation++;
869
870 for (i=0; i<CLIENT_NR; i++)
871 {
872 if (checkreq[i])
873 (*checkreq[i])();
874 }
875
876 /* Add information about free accessors */
877 for(acc= acc_freelist; acc; acc= acc->acc_next)
878 {
879 if (acc->acc_generation == buf_generation-1)
880 {
881 acc->acc_generation= buf_generation;
882 acc->acc_check_linkC= 0;
883 }
884 else
885 {
886 assert(acc->acc_generation == buf_generation &&
887 acc->acc_check_linkC > 0);
888 acc->acc_check_linkC= -acc->acc_check_linkC;
889 }
890 }
891
892 #if BUF512_NR
893 count_free_bufs(buf512_freelist);
894 #endif
895 #if BUF2K_NR
896 count_free_bufs(buf2K_freelist);
897 #endif
898 #if BUF32K_NR
899 count_free_bufs(buf32K_freelist);
900 #endif
901
902 error= 0;
903
904 /* Report about accessors */
905 silent= 0;
906 for (i=0, acc= accessors; i<ACC_NR; i++, acc++)
907 {
908 if (acc->acc_generation != buf_generation)
909 {
910 error++;
911 assert(acc->acc_generation == buf_generation-1);
912 acc->acc_generation= buf_generation;
913 if (!silent)
914 {
915 printf(
916 "acc[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
917 i, acc, acc->acc_linkC, acc->acc_alloc_file, acc->acc_alloc_line);
918 #if 0
919 silent= 1;
920 #endif
921 }
922 continue;
923 }
924 if (acc->acc_check_linkC == acc->acc_linkC)
925 continue;
926 error++;
927 if (acc->acc_check_linkC < 0)
928 {
929 if (!silent)
930 {
931 printf(
932 "acc[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
933 i, acc->acc_alloc_file, acc->acc_alloc_line,
934 acc->acc_free_file, acc->acc_free_line);
935 }
936 acc->acc_check_linkC= -acc->acc_check_linkC;
937 if (acc->acc_check_linkC == acc->acc_linkC)
938 {
939 silent= 1;
940 continue;
941 }
942 }
943 if (!silent)
944 {
945 printf(
946 "# of tracked links (%d) for acc[%d] don't match with stored link count %d\n",
947 acc->acc_check_linkC, i, acc->acc_linkC);
948 printf("acc[%d] was allocated at %s, %d\n",
949 i, acc->acc_alloc_file, acc->acc_alloc_line);
950 silent=1;
951 }
952 }
953
954 /* Report about buffers */
955 #if BUF512_NR
956 {
957 for (i= 0; i<BUF512_NR; i++)
958 {
959 error |= report_buffer(&buffers512[i].buf_header,
960 "512-buffer", i);
961 }
962 }
963 #endif
964 #if BUF2K_NR
965 {
966 for (i= 0; i<BUF2K_NR; i++)
967 {
968 error |= report_buffer(&buffers2K[i].buf_header,
969 "2K-buffer", i);
970 }
971 }
972 #endif
973 #if BUF32K_NR
974 {
975 for (i= 0; i<BUF32K_NR; i++)
976 {
977 error |= report_buffer(&buffers32K[i].buf_header,
978 "32K-buffer", i);
979 }
980 }
981 #endif
982
983 return !error;
984 }
985
986 PRIVATE void count_free_bufs(list)
987 acc_t *list;
988 {
989 acc_t *acc;
990 buf_t *buf;
991
992 for(acc= list; acc; acc= acc->acc_next)
993 {
994 if (acc->acc_generation != buf_generation-1)
995 {
996 assert(acc->acc_generation == buf_generation &&
997 acc->acc_check_linkC > 0);
998 acc->acc_check_linkC= -acc->acc_check_linkC;
999 continue;
1000 }
1001 acc->acc_generation= buf_generation;
1002 acc->acc_check_linkC= 0;
1003
1004 buf= acc->acc_buffer;
1005 if (buf->buf_generation == buf_generation-1)
1006 {
1007 buf->buf_generation= buf_generation;
1008 buf->buf_check_linkC= 0;
1009 continue;
1010 }
1011 assert(buf->buf_generation == buf_generation &&
1012 buf->buf_check_linkC > 0);
1013 buf->buf_check_linkC= -buf->buf_check_linkC;
1014 }
1015 }
1016
1017 PRIVATE int report_buffer(buf, label, i)
1018 buf_t *buf;
1019 char *label;
1020 int i;
1021 {
1022 if (buf->buf_generation != buf_generation)
1023 {
1024 assert(buf->buf_generation == buf_generation-1);
1025 buf->buf_generation= buf_generation;
1026 printf(
1027 "%s[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
1028 label, i, buf,
1029 buf->buf_linkC, buf->buf_alloc_file,
1030 buf->buf_alloc_line);
1031 return 1;
1032 }
1033 if (buf->buf_check_linkC == buf->buf_linkC)
1034 return 0;
1035 if (buf->buf_check_linkC < 0)
1036 {
1037 printf(
1038 "%s[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
1039 label, i, buf->buf_alloc_file, buf->buf_alloc_line,
1040 buf->buf_free_file, buf->buf_free_line);
1041 buf->buf_check_linkC= -buf->buf_check_linkC;
1042 if (buf->buf_check_linkC == buf->buf_linkC)
1043 return 1;
1044 }
1045 printf(
1046 "# of tracked links (%d) for %s[%d] don't match with stored link count %d\n",
1047 buf->buf_check_linkC, label, i, buf->buf_linkC);
1048 printf("%s[%d] was allocated at %s, %d\n",
1049 label, i, buf->buf_alloc_file, buf->buf_alloc_line);
1050 return 1;
1051 }
1052
1053 PUBLIC void bf_check_acc(acc)
1054 acc_t *acc;
1055 {
1056 buf_t *buf;
1057
1058 while(acc != NULL)
1059 {
1060 if (acc->acc_generation == buf_generation)
1061 {
1062 assert(acc->acc_check_linkC > 0);
1063 acc->acc_check_linkC++;
1064 return;
1065 }
1066 assert(acc->acc_generation == buf_generation-1);
1067 acc->acc_generation= buf_generation;
1068 acc->acc_check_linkC= 1;
1069
1070 buf= acc->acc_buffer;
1071 if (buf->buf_generation == buf_generation)
1072 {
1073 assert(buf->buf_check_linkC > 0);
1074 buf->buf_check_linkC++;
1075 }
1076 else
1077 {
1078 assert(buf->buf_generation == buf_generation-1);
1079 buf->buf_generation= buf_generation;
1080 buf->buf_check_linkC= 1;
1081 }
1082
1083 acc= acc->acc_next;
1084 }
1085 }
1086
1087 PUBLIC void _bf_mark_1acc(clnt_file, clnt_line, acc)
1088 char *clnt_file;
1089 int clnt_line;
1090 acc_t *acc;
1091 {
1092 acc->acc_alloc_file= clnt_file;
1093 acc->acc_alloc_line= clnt_line;
1094 }
1095
1096 PUBLIC void _bf_mark_acc(clnt_file, clnt_line, acc)
1097 char *clnt_file;
1098 int clnt_line;
1099 acc_t *acc;
1100 {
1101 buf_t *buf;
1102
1103 for (; acc; acc= acc->acc_next)
1104 {
1105 acc->acc_alloc_file= clnt_file;
1106 acc->acc_alloc_line= clnt_line;
1107 buf= acc->acc_buffer;
1108 buf->buf_alloc_file= clnt_file;
1109 buf->buf_alloc_line= clnt_line;
1110 }
1111 }
1112 #endif
1113
1114 PUBLIC int bf_linkcheck(acc)
1115 acc_t *acc;
1116 {
1117 int i;
1118
1119 buf_t *buffer;
1120 for (i= 0; i<ACC_NR && acc; i++, acc= acc->acc_next)
1121 {
1122 if (acc->acc_linkC <= 0)
1123 {
1124 printf("wrong acc_linkC (%d) for acc %p\n",
1125 acc->acc_linkC, acc);
1126 return 0;
1127 }
1128 if (acc->acc_offset < 0)
1129 {
1130 printf("wrong acc_offset (%d) for acc %p\n",
1131 acc->acc_offset, acc);
1132 return 0;
1133 }
1134 if (acc->acc_length < 0)
1135 {
1136 printf("wrong acc_length (%d) for acc %p\n",
1137 acc->acc_length, acc);
1138 return 0;
1139 }
1140 buffer= acc->acc_buffer;
1141 if (buffer == NULL)
1142 {
1143 printf("no buffer for acc %p\n", acc);
1144 return 0;
1145 }
1146 if (buffer->buf_linkC <= 0)
1147 {
1148 printf(
1149 "wrong buf_linkC (%d) for buffer %p, from acc %p\n",
1150 buffer->buf_linkC, buffer, acc);
1151 return 0;
1152 }
1153 if (acc->acc_offset + acc->acc_length > buffer->buf_size)
1154 {
1155 printf("%d + %d > %d for buffer %p, and acc %p\n",
1156 acc->acc_offset, acc->acc_length,
1157 buffer->buf_size, buffer, acc);
1158 return 0;
1159 }
1160 }
1161 if (acc != NULL)
1162 {
1163 printf("loop\n");
1164 return 0;
1165 }
1166 return 1;
1167 }
1168
1169 PRIVATE void free_accs()
1170 {
1171 int i, j;
1172
1173 DBLOCK(1, printf("free_accs\n"));
1174
1175 assert(bf_linkcheck(bf_linkcheck_acc));
1176 for (i=0; !acc_freelist && i<MAX_BUFREQ_PRI; i++)
1177 {
1178 for (j=0; j<CLIENT_NR; j++)
1179 {
1180 bf_free_bufsize= 0;
1181 if (freereq[j])
1182 {
1183 (*freereq[j])(i);
1184 assert(bf_linkcheck(bf_linkcheck_acc) ||
1185 (printf("just called %p\n",
1186 freereq[i]),0));
1187 }
1188 }
1189 }
1190 #if DEBUG
1191 printf("last level was level %d\n", i-1);
1192 #endif
1193 }
1194
1195 #ifndef BUF_TRACK_ALLOC_FREE
1196 PUBLIC acc_t *bf_align(acc, size, alignment)
1197 #else
1198 PUBLIC acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
1199 char *clnt_file;
1200 int clnt_line;
1201 #endif
1202 acc_t *acc;
1203 size_t size;
1204 size_t alignment;
1205 {
1206 char *ptr;
1207 size_t buf_size;
1208 acc_t *head, *tail;
1209
1210 /* Fast check if the buffer is aligned already. */
1211 if (acc->acc_length >= size)
1212 {
1213 ptr= ptr2acc_data(acc);
1214 if (((unsigned)ptr & (alignment-1)) == 0)
1215 return acc;
1216 }
1217 buf_size= bf_bufsize(acc);
1218 #ifdef bf_align
1219 assert((size != 0 && buf_size != 0) ||
1220 (printf("bf_align(..., %d, %d) from %s, %d\n",
1221 size, alignment, clnt_file, clnt_line),0));
1222 #else
1223 assert(size != 0 && buf_size != 0);
1224 #endif
1225 if (buf_size <= size)
1226 {
1227 acc= bf_pack(acc);
1228 return acc;
1229 }
1230 head= bf_cut(acc, 0, size);
1231 tail= bf_cut(acc, size, buf_size-size);
1232 bf_afree(acc);
1233 head= bf_pack(head);
1234 assert(head->acc_next == NULL);
1235 head->acc_next= tail;
1236 return head;
1237 }
1238
1239 #if 0
1240 int chk_acc(acc)
1241 acc_t *acc;
1242 {
1243 int acc_nr;
1244
1245 if (!acc)
1246 return 1;
1247 if (acc < accessors || acc >= &accessors[ACC_NR])
1248 return 0;
1249 acc_nr= acc-accessors;
1250 return acc == &accessors[acc_nr];
1251 }
1252 #endif
1253
1254 /*
1255 * $PchId: buf.c,v 1.19 2003/09/10 08:54:23 philip Exp $
1256 */
Cache object: 0b7bdb0bead877414378a01a9195d5c4
|