source: trunk/minix/servers/inet/buf.c@ 15

Last change on this file since 15 was 9, checked in by Mattia Monga, 14 years ago

Minix 3.1.2a

File size: 25.4 KB
Line 
1/*
2This file contains routines for buffer management.
3
4Copyright 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
18THIS_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
65DECLARE_TYPE(buf512, buf512_t, 512);
66PRIVATE acc_t *buf512_freelist;
67DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
68FORWARD void bf_512free ARGS(( acc_t *acc ));
69#endif
70#if BUF2K_NR
71DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
72PRIVATE acc_t *buf2K_freelist;
73DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
74FORWARD void bf_2Kfree ARGS(( acc_t *acc ));
75#endif
76#if BUF32K_NR
77DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
78PRIVATE acc_t *buf32K_freelist;
79DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
80FORWARD void bf_32Kfree ARGS(( acc_t *acc ));
81#endif
82
83PRIVATE acc_t *acc_freelist;
84DECLARE_STORAGE(acc_t, accessors, ACC_NR);
85
86PRIVATE bf_freereq_t freereq[CLIENT_NR];
87PRIVATE size_t bf_buf_gran;
88
89PUBLIC size_t bf_free_bufsize;
90PUBLIC acc_t *bf_temporary_acc;
91PUBLIC acc_t *bf_linkcheck_acc;
92
93#ifdef BUF_CONSISTENCY_CHECK
94int inet_buf_debug;
95unsigned buf_generation;
96PRIVATE bf_checkreq_t checkreq[CLIENT_NR];
97#endif
98
99#ifndef BUF_TRACK_ALLOC_FREE
100FORWARD acc_t *bf_small_memreq ARGS(( size_t size ));
101#else
102FORWARD 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
106FORWARD void free_accs ARGS(( void ));
107#ifdef BUF_CONSISTENCY_CHECK
108FORWARD void count_free_bufs ARGS(( acc_t *list ));
109FORWARD int report_buffer ARGS(( buf_t *buf, char *label, int i ));
110#endif
111
112PUBLIC 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
195PUBLIC void bf_logon(func)
196bf_freereq_t func;
197#else
198PUBLIC void bf_logon(func, checkfunc)
199bf_freereq_t func;
200bf_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/*
219bf_memreq
220*/
221
222#ifndef BUF_TRACK_ALLOC_FREE
223PUBLIC acc_t *bf_memreq(size)
224#else
225PUBLIC acc_t *_bf_memreq(clnt_file, clnt_line, size)
226char *clnt_file;
227int clnt_line;
228#endif
229size_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/*
324bf_small_memreq
325*/
326
327#ifndef BUF_TRACK_ALLOC_FREE
328PRIVATE acc_t *bf_small_memreq(size)
329#else
330PRIVATE acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
331char *clnt_file;
332int clnt_line;
333#endif
334size_t size;
335{
336 return bf_memreq(size);
337}
338
339#ifndef BUF_TRACK_ALLOC_FREE
340PUBLIC void bf_afree(acc)
341#else
342PUBLIC void _bf_afree(clnt_file, clnt_line, acc)
343char *clnt_file;
344int clnt_line;
345#endif
346acc_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
407PUBLIC acc_t *bf_dupacc(acc_ptr)
408#else
409PUBLIC acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
410char *clnt_file;
411int clnt_line;
412#endif
413register 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
439PUBLIC size_t bf_bufsize(acc_ptr)
440register acc_t *acc_ptr;
441{
442 register size_t size;
443
444assert(acc_ptr);
445
446 size=0;
447
448 while (acc_ptr)
449 {
450assert(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
458PUBLIC acc_t *bf_packIffLess(pack, min_len)
459#else
460PUBLIC acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
461char *clnt_file;
462int clnt_line;
463#endif
464acc_t *pack;
465int 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
480PUBLIC acc_t *bf_pack(old_acc)
481#else
482PUBLIC acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
483char *clnt_file;
484int clnt_line;
485#endif
486acc_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
538PUBLIC acc_t *bf_cut (data, offset, length)
539#else
540PUBLIC acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
541char *clnt_file;
542int clnt_line;
543#endif
544register acc_t *data;
545register unsigned offset;
546register 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
620PUBLIC acc_t *bf_delhead (data, offset)
621#else
622PUBLIC acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
623char *clnt_file;
624int clnt_line;
625#endif
626register acc_t *data;
627register 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/*
670bf_append
671*/
672
673#ifndef BUF_TRACK_ALLOC_FREE
674PUBLIC acc_t *bf_append(data_first, data_second)
675#else
676PUBLIC acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
677char *clnt_file;
678int clnt_line;
679#endif
680acc_t *data_first;
681acc_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 {
766assert (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 }
773assert (offset_new < acc_ptr_new->acc_length);
774assert (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 {
789assert (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 }
796assert (offset_new < acc_ptr_new->acc_length);
797assert (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
824PRIVATE void bf_512free(acc)
825acc_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
836PRIVATE void bf_2Kfree(acc)
837acc_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
848PRIVATE void bf_32Kfree(acc)
849acc_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
861PUBLIC 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
986PRIVATE void count_free_bufs(list)
987acc_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
1017PRIVATE int report_buffer(buf, label, i)
1018buf_t *buf;
1019char *label;
1020int 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
1053PUBLIC void bf_check_acc(acc)
1054acc_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
1087PUBLIC void _bf_mark_1acc(clnt_file, clnt_line, acc)
1088char *clnt_file;
1089int clnt_line;
1090acc_t *acc;
1091{
1092 acc->acc_alloc_file= clnt_file;
1093 acc->acc_alloc_line= clnt_line;
1094}
1095
1096PUBLIC void _bf_mark_acc(clnt_file, clnt_line, acc)
1097char *clnt_file;
1098int clnt_line;
1099acc_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
1114PUBLIC int bf_linkcheck(acc)
1115acc_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
1169PRIVATE void free_accs()
1170{
1171 int i, j;
1172
1173 DBLOCK(1, printf("free_accs\n"));
1174
1175assert(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
1196PUBLIC acc_t *bf_align(acc, size, alignment)
1197#else
1198PUBLIC acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
1199char *clnt_file;
1200int clnt_line;
1201#endif
1202acc_t *acc;
1203size_t size;
1204size_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
1240int chk_acc(acc)
1241acc_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 */
Note: See TracBrowser for help on using the repository browser.