00001
00002
00003
00004
00005
00006
00007 #define BUF_IMPLEMENTATION 1
00008
00009 #include "inet.h"
00010
00011 #include <stdlib.h>
00012 #include <string.h>
00013
00014 #include "generic/assert.h"
00015 #include "generic/buf.h"
00016 #include "generic/type.h"
00017
00018 THIS_FILE
00019
00020 #ifndef BUF_USEMALLOC
00021 #define BUF_USEMALLOC 0
00022 #endif
00023
00024 #ifndef BUF512_NR
00025 #define BUF512_NR 512
00026 #endif
00027 #ifndef BUF2K_NR
00028 #define BUF2K_NR 0
00029 #endif
00030 #ifndef BUF32K_NR
00031 #define BUF32K_NR 0
00032 #endif
00033
00034 #define ACC_NR ((BUF512_NR+BUF2K_NR+BUF32K_NR)*3)
00035 #define CLIENT_NR 7
00036
00037 #define DECLARE_TYPE(Tag, Type, Size) \
00038 typedef struct Tag \
00039 { \
00040 buf_t buf_header; \
00041 char buf_data[Size]; \
00042 } Type
00043
00044 #if BUF_USEMALLOC
00045 #define DECLARE_STORAGE(Type, Ident, Nitems) \
00046 PRIVATE Type *Ident
00047
00048 #define ALLOC_STORAGE(Ident, Nitems, Label) \
00049 do \
00050 { \
00051 printf("buf.c: malloc %d %s\n", Nitems, Label); \
00052 Ident= malloc(sizeof(*Ident) * Nitems); \
00053 if (!Ident) \
00054 ip_panic(( "unable to alloc %s", Label )); \
00055 } while(0)
00056 #else
00057 #define DECLARE_STORAGE(Type, Ident, Nitems) \
00058 PRIVATE Type Ident[Nitems]
00059
00060 #define ALLOC_STORAGE(Ident, Nitems, Label) \
00061 (void)0
00062 #endif
00063
00064 #if BUF512_NR
00065 DECLARE_TYPE(buf512, buf512_t, 512);
00066 PRIVATE acc_t *buf512_freelist;
00067 DECLARE_STORAGE(buf512_t, buffers512, BUF512_NR);
00068 FORWARD void bf_512free ARGS(( acc_t *acc ));
00069 #endif
00070 #if BUF2K_NR
00071 DECLARE_TYPE(buf2K, buf2K_t, (2*1024));
00072 PRIVATE acc_t *buf2K_freelist;
00073 DECLARE_STORAGE(buf2K_t, buffers2K, BUF2K_NR);
00074 FORWARD void bf_2Kfree ARGS(( acc_t *acc ));
00075 #endif
00076 #if BUF32K_NR
00077 DECLARE_TYPE(buf32K, buf32K_t, (32*1024));
00078 PRIVATE acc_t *buf32K_freelist;
00079 DECLARE_STORAGE(buf32K_t, buffers32K, BUF32K_NR);
00080 FORWARD void bf_32Kfree ARGS(( acc_t *acc ));
00081 #endif
00082
00083 PRIVATE acc_t *acc_freelist;
00084 DECLARE_STORAGE(acc_t, accessors, ACC_NR);
00085
00086 PRIVATE bf_freereq_t freereq[CLIENT_NR];
00087 PRIVATE size_t bf_buf_gran;
00088
00089 PUBLIC size_t bf_free_bufsize;
00090 PUBLIC acc_t *bf_temporary_acc;
00091 PUBLIC acc_t *bf_linkcheck_acc;
00092
00093 #ifdef BUF_CONSISTENCY_CHECK
00094 int inet_buf_debug;
00095 unsigned buf_generation;
00096 PRIVATE bf_checkreq_t checkreq[CLIENT_NR];
00097 #endif
00098
00099 #ifndef BUF_TRACK_ALLOC_FREE
00100 FORWARD acc_t *bf_small_memreq ARGS(( size_t size ));
00101 #else
00102 FORWARD acc_t *_bf_small_memreq ARGS(( char *clnt_file, int clnt_line,
00103 size_t size ));
00104 #define bf_small_memreq(a) _bf_small_memreq(clnt_file, clnt_line, a)
00105 #endif
00106 FORWARD void free_accs ARGS(( void ));
00107 #ifdef BUF_CONSISTENCY_CHECK
00108 FORWARD void count_free_bufs ARGS(( acc_t *list ));
00109 FORWARD int report_buffer ARGS(( buf_t *buf, char *label, int i ));
00110 #endif
00111
00112 PUBLIC void bf_init()
00113 {
00114 int i;
00115 size_t buf_s;
00116 acc_t *acc;
00117
00118 bf_buf_gran= BUF_S;
00119 buf_s= 0;
00120
00121 for (i=0;i<CLIENT_NR;i++)
00122 freereq[i]=0;
00123 #ifdef BUF_CONSISTENCY_CHECK
00124 for (i=0;i<CLIENT_NR;i++)
00125 checkreq[i]=0;
00126 #endif
00127
00128 #if BUF512_NR
00129 ALLOC_STORAGE(buffers512, BUF512_NR, "512B-buffers");
00130 #endif
00131 #if BUF2K_NR
00132 ALLOC_STORAGE(buffers2K, BUF2K_NR, "2K-buffers");
00133 #endif
00134 #if BUF32K_NR
00135 ALLOC_STORAGE(buffers32K, BUF32K_NR, "32K-buffers");
00136 #endif
00137 ALLOC_STORAGE(accessors, ACC_NR, "accs");
00138
00139 acc_freelist= NULL;
00140 for (i=0;i<ACC_NR;i++)
00141 {
00142 memset(&accessors[i], '\0', sizeof(accessors[i]));
00143
00144 accessors[i].acc_linkC= 0;
00145 accessors[i].acc_next= acc_freelist;
00146 acc_freelist= &accessors[i];
00147 }
00148
00149 #define INIT_BUFFERS(Ident, Nitems, Freelist, Freefunc) \
00150 do \
00151 { \
00152 Freelist= NULL; \
00153 for (i=0;i<Nitems;i++) \
00154 { \
00155 acc= acc_freelist; \
00156 if (!acc) \
00157 ip_panic(( "fewer accessors than buffers")); \
00158 acc_freelist= acc->acc_next; \
00159 acc->acc_linkC= 0; \
00160 \
00161 memset(&Ident[i], '\0', sizeof(Ident[i])); \
00162 Ident[i].buf_header.buf_linkC= 0; \
00163 Ident[i].buf_header.buf_free= Freefunc; \
00164 Ident[i].buf_header.buf_size= \
00165 sizeof(Ident[i].buf_data); \
00166 Ident[i].buf_header.buf_data_p= \
00167 Ident[i].buf_data; \
00168 \
00169 acc->acc_buffer= &Ident[i].buf_header; \
00170 acc->acc_next= Freelist; \
00171 Freelist= acc; \
00172 } \
00173 if (sizeof(Ident[0].buf_data) < bf_buf_gran) \
00174 bf_buf_gran= sizeof(Ident[0].buf_data); \
00175 if (sizeof(Ident[0].buf_data) > buf_s) \
00176 buf_s= sizeof(Ident[0].buf_data); \
00177 } while(0)
00178
00179 #if BUF512_NR
00180 INIT_BUFFERS(buffers512, BUF512_NR, buf512_freelist, bf_512free);
00181 #endif
00182 #if BUF2K_NR
00183 INIT_BUFFERS(buffers2K, BUF2K_NR, buf2K_freelist, bf_2Kfree);
00184 #endif
00185 #if BUF32K_NR
00186 INIT_BUFFERS(buffers32K, BUF32K_NR, buf32K_freelist, bf_32Kfree);
00187 #endif
00188
00189 #undef INIT_BUFFERS
00190
00191 assert (buf_s == BUF_S);
00192 }
00193
00194 #ifndef BUF_CONSISTENCY_CHECK
00195 PUBLIC void bf_logon(func)
00196 bf_freereq_t func;
00197 #else
00198 PUBLIC void bf_logon(func, checkfunc)
00199 bf_freereq_t func;
00200 bf_checkreq_t checkfunc;
00201 #endif
00202 {
00203 int i;
00204
00205 for (i=0;i<CLIENT_NR;i++)
00206 if (!freereq[i])
00207 {
00208 freereq[i]=func;
00209 #ifdef BUF_CONSISTENCY_CHECK
00210 checkreq[i]= checkfunc;
00211 #endif
00212 return;
00213 }
00214
00215 ip_panic(( "buf.c: too many clients" ));
00216 }
00217
00218
00219
00220
00221
00222 #ifndef BUF_TRACK_ALLOC_FREE
00223 PUBLIC acc_t *bf_memreq(size)
00224 #else
00225 PUBLIC acc_t *_bf_memreq(clnt_file, clnt_line, size)
00226 char *clnt_file;
00227 int clnt_line;
00228 #endif
00229 size_t size;
00230 {
00231 acc_t *head, *tail, *new_acc;
00232 buf_t *buf;
00233 int i,j;
00234 size_t count;
00235
00236 assert (size>0);
00237
00238 head= NULL;
00239 tail= NULL;
00240 while (size)
00241 {
00242 new_acc= NULL;
00243
00244
00245 #define ALLOC_BUF(Freelist, Bufsize) \
00246 if (Freelist && (Bufsize == BUF_S || size <= Bufsize)) \
00247 { \
00248 new_acc= Freelist; \
00249 Freelist= new_acc->acc_next; \
00250 \
00251 assert(new_acc->acc_linkC == 0); \
00252 new_acc->acc_linkC= 1; \
00253 buf= new_acc->acc_buffer; \
00254 assert(buf->buf_linkC == 0); \
00255 buf->buf_linkC= 1; \
00256 } \
00257 else
00258
00259
00260 #if BUF512_NR
00261 ALLOC_BUF(buf512_freelist, 512)
00262 #endif
00263 #if BUF2K_NR
00264 ALLOC_BUF(buf2K_freelist, 2*1024)
00265 #endif
00266 #if BUF32K_NR
00267 ALLOC_BUF(buf32K_freelist, 32*1024)
00268 #endif
00269 #undef ALLOC_BUF
00270 {
00271 DBLOCK(2, printf("freeing buffers\n"));
00272
00273 bf_free_bufsize= 0;
00274 for (i=0; bf_free_bufsize<size && i<MAX_BUFREQ_PRI;
00275 i++)
00276 {
00277 for (j=0; j<CLIENT_NR; j++)
00278 {
00279 if (freereq[j])
00280 (*freereq[j])(i);
00281 }
00282 #if DEBUG && 0
00283 { acc_t *acc;
00284 j= 0; for(acc= buf512_freelist; acc; acc= acc->acc_next) j++;
00285 printf("# of free 512-bytes buffer is now %d\n", j); }
00286 #endif
00287 }
00288 #if DEBUG && 0
00289 { printf("last level was level %d\n", i-1); }
00290 #endif
00291 if (bf_free_bufsize<size)
00292 ip_panic(( "not enough buffers freed" ));
00293
00294 continue;
00295 }
00296
00297 #ifdef BUF_TRACK_ALLOC_FREE
00298 new_acc->acc_alloc_file= clnt_file;
00299 new_acc->acc_alloc_line= clnt_line;
00300 buf->buf_alloc_file= clnt_file;
00301 buf->buf_alloc_line= clnt_line;
00302 #endif
00303
00304 if (!head)
00305 head= new_acc;
00306 else
00307 tail->acc_next= new_acc;
00308 tail= new_acc;
00309
00310 count= tail->acc_buffer->buf_size;
00311 if (count > size)
00312 count= size;
00313
00314 tail->acc_offset= 0;
00315 tail->acc_length= count;
00316 size -= count;
00317 }
00318 tail->acc_next= NULL;
00319
00320 return head;
00321 }
00322
00323
00324
00325
00326
00327 #ifndef BUF_TRACK_ALLOC_FREE
00328 PRIVATE acc_t *bf_small_memreq(size)
00329 #else
00330 PRIVATE acc_t *_bf_small_memreq(clnt_file, clnt_line, size)
00331 char *clnt_file;
00332 int clnt_line;
00333 #endif
00334 size_t size;
00335 {
00336 return bf_memreq(size);
00337 }
00338
00339 #ifndef BUF_TRACK_ALLOC_FREE
00340 PUBLIC void bf_afree(acc)
00341 #else
00342 PUBLIC void _bf_afree(clnt_file, clnt_line, acc)
00343 char *clnt_file;
00344 int clnt_line;
00345 #endif
00346 acc_t *acc;
00347 {
00348 acc_t *next_acc;
00349 buf_t *buf;
00350
00351 while (acc)
00352 {
00353 #if defined(bf_afree)
00354 DIFBLOCK(1, (acc->acc_linkC <= 0),
00355 printf("clnt_file= %s, clnt_line= %d\n",
00356 clnt_file, clnt_line));
00357 #endif
00358 assert (acc->acc_linkC>0);
00359 if (--acc->acc_linkC > 0)
00360 break;
00361
00362 #ifdef BUF_TRACK_ALLOC_FREE
00363 acc->acc_free_file= clnt_file;
00364 acc->acc_free_line= clnt_line;
00365 #endif
00366 buf= acc->acc_buffer;
00367 assert (buf);
00368
00369 #if defined(bf_afree)
00370 DIFBLOCK(1, (buf->buf_linkC == 0),
00371 printf("clnt_file= %s, clnt_line= %d\n",
00372 clnt_file, clnt_line));
00373 #endif
00374 assert (buf->buf_linkC>0);
00375 if (--buf->buf_linkC > 0)
00376 {
00377 acc->acc_buffer= NULL;
00378 next_acc= acc->acc_next;
00379 acc->acc_next= acc_freelist;
00380 acc_freelist= acc;
00381 #ifdef BUF_CONSISTENCY_CHECK
00382 if (inet_buf_debug)
00383 {
00384 acc->acc_offset= 0xdeadbeaf;
00385 acc->acc_length= 0xdeadbeaf;
00386 acc->acc_buffer= (buf_t *)0xdeadbeaf;
00387 acc->acc_ext_link= (acc_t *)0xdeadbeaf;
00388 }
00389 #endif
00390 acc= next_acc;
00391 continue;
00392 }
00393
00394 bf_free_bufsize += buf->buf_size;
00395 #ifdef BUF_TRACK_ALLOC_FREE
00396 buf->buf_free_file= clnt_file;
00397 buf->buf_free_line= clnt_line;
00398 #endif
00399 next_acc= acc->acc_next;
00400 buf->buf_free(acc);
00401 acc= next_acc;
00402 continue;
00403 }
00404 }
00405
00406 #ifndef BUF_TRACK_ALLOC_FREE
00407 PUBLIC acc_t *bf_dupacc(acc_ptr)
00408 #else
00409 PUBLIC acc_t *_bf_dupacc(clnt_file, clnt_line, acc_ptr)
00410 char *clnt_file;
00411 int clnt_line;
00412 #endif
00413 register acc_t *acc_ptr;
00414 {
00415 register acc_t *new_acc;
00416
00417 if (!acc_freelist)
00418 {
00419 free_accs();
00420 if (!acc_freelist)
00421 ip_panic(( "buf.c: out of accessors" ));
00422 }
00423 new_acc= acc_freelist;
00424 acc_freelist= new_acc->acc_next;
00425
00426 *new_acc= *acc_ptr;
00427 if (acc_ptr->acc_next)
00428 acc_ptr->acc_next->acc_linkC++;
00429 if (acc_ptr->acc_buffer)
00430 acc_ptr->acc_buffer->buf_linkC++;
00431 new_acc->acc_linkC= 1;
00432 #ifdef BUF_TRACK_ALLOC_FREE
00433 new_acc->acc_alloc_file= clnt_file;
00434 new_acc->acc_alloc_line= clnt_line;
00435 #endif
00436 return new_acc;
00437 }
00438
00439 PUBLIC size_t bf_bufsize(acc_ptr)
00440 register acc_t *acc_ptr;
00441 {
00442 register size_t size;
00443
00444 assert(acc_ptr);
00445
00446 size=0;
00447
00448 while (acc_ptr)
00449 {
00450 assert(acc_ptr >= accessors && acc_ptr <= &accessors[ACC_NR-1]);
00451 size += acc_ptr->acc_length;
00452 acc_ptr= acc_ptr->acc_next;
00453 }
00454 return size;
00455 }
00456
00457 #ifndef BUF_TRACK_ALLOC_FREE
00458 PUBLIC acc_t *bf_packIffLess(pack, min_len)
00459 #else
00460 PUBLIC acc_t *_bf_packIffLess(clnt_file, clnt_line, pack, min_len)
00461 char *clnt_file;
00462 int clnt_line;
00463 #endif
00464 acc_t *pack;
00465 int min_len;
00466 {
00467 if (!pack || pack->acc_length >= min_len)
00468 return pack;
00469
00470 #if DEBUG
00471 #ifdef bf_packIffLess
00472 { where(); printf("calling bf_pack because of %s %d: %d\n", bf_pack_file,
00473 bf_pack_line, min_len); }
00474 #endif
00475 #endif
00476 return bf_pack(pack);
00477 }
00478
00479 #ifndef BUF_TRACK_ALLOC_FREE
00480 PUBLIC acc_t *bf_pack(old_acc)
00481 #else
00482 PUBLIC acc_t *_bf_pack(clnt_file, clnt_line, old_acc)
00483 char *clnt_file;
00484 int clnt_line;
00485 #endif
00486 acc_t *old_acc;
00487 {
00488 acc_t *new_acc, *acc_ptr_old, *acc_ptr_new;
00489 size_t size, offset_old, offset_new, block_size, block_size_old;
00490
00491
00492 if (!old_acc || (!old_acc->acc_next && old_acc->acc_linkC == 1 &&
00493 old_acc->acc_buffer->buf_linkC == 1))
00494 {
00495 return old_acc;
00496 }
00497
00498 size= bf_bufsize(old_acc);
00499 assert(size > 0);
00500 new_acc= bf_memreq(size);
00501 acc_ptr_old= old_acc;
00502 acc_ptr_new= new_acc;
00503 offset_old= 0;
00504 offset_new= 0;
00505 while (size)
00506 {
00507 assert (acc_ptr_old);
00508 if (offset_old == acc_ptr_old->acc_length)
00509 {
00510 offset_old= 0;
00511 acc_ptr_old= acc_ptr_old->acc_next;
00512 continue;
00513 }
00514 assert (offset_old < acc_ptr_old->acc_length);
00515 block_size_old= acc_ptr_old->acc_length - offset_old;
00516 assert (acc_ptr_new);
00517 if (offset_new == acc_ptr_new->acc_length)
00518 {
00519 offset_new= 0;
00520 acc_ptr_new= acc_ptr_new->acc_next;
00521 continue;
00522 }
00523 assert (offset_new < acc_ptr_new->acc_length);
00524 block_size= acc_ptr_new->acc_length - offset_new;
00525 if (block_size > block_size_old)
00526 block_size= block_size_old;
00527 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
00528 ptr2acc_data(acc_ptr_old)+offset_old, block_size);
00529 offset_new += block_size;
00530 offset_old += block_size;
00531 size -= block_size;
00532 }
00533 bf_afree(old_acc);
00534 return new_acc;
00535 }
00536
00537 #ifndef BUF_TRACK_ALLOC_FREE
00538 PUBLIC acc_t *bf_cut (data, offset, length)
00539 #else
00540 PUBLIC acc_t *_bf_cut (clnt_file, clnt_line, data, offset, length)
00541 char *clnt_file;
00542 int clnt_line;
00543 #endif
00544 register acc_t *data;
00545 register unsigned offset;
00546 register unsigned length;
00547 {
00548 register acc_t *head, *tail;
00549
00550 if (!data && !offset && !length)
00551 return NULL;
00552 #ifdef BUF_TRACK_ALLOC_FREE
00553 assert(data ||
00554 (printf("from %s, %d: %u, %u\n",
00555 clnt_file, clnt_line, offset, length), 0));
00556 #else
00557 assert(data);
00558 #endif
00559
00560 assert(data);
00561
00562 if (!length)
00563 {
00564 head= bf_dupacc(data);
00565 bf_afree(head->acc_next);
00566 head->acc_next= NULL;
00567 head->acc_length= 0;
00568 return head;
00569 }
00570 while (data && offset>=data->acc_length)
00571 {
00572 offset -= data->acc_length;
00573 data= data->acc_next;
00574 }
00575
00576 assert (data);
00577
00578 head= bf_dupacc(data);
00579 bf_afree(head->acc_next);
00580 head->acc_next= NULL;
00581 head->acc_offset += offset;
00582 head->acc_length -= offset;
00583 if (length >= head->acc_length)
00584 length -= head->acc_length;
00585 else
00586 {
00587 head->acc_length= length;
00588 length= 0;
00589 }
00590 tail= head;
00591 data= data->acc_next;
00592 while (data && length && length>=data->acc_length)
00593 {
00594 tail->acc_next= bf_dupacc(data);
00595 tail= tail->acc_next;
00596 bf_afree(tail->acc_next);
00597 tail->acc_next= NULL;
00598 data= data->acc_next;
00599 length -= tail->acc_length;
00600 }
00601 if (length)
00602 {
00603 #ifdef bf_cut
00604 assert (data ||
00605 (printf("bf_cut called from %s:%d\n",
00606 clnt_file, clnt_line), 0));
00607 #else
00608 assert (data);
00609 #endif
00610 tail->acc_next= bf_dupacc(data);
00611 tail= tail->acc_next;
00612 bf_afree(tail->acc_next);
00613 tail->acc_next= NULL;
00614 tail->acc_length= length;
00615 }
00616 return head;
00617 }
00618
00619 #ifndef BUF_TRACK_ALLOC_FREE
00620 PUBLIC acc_t *bf_delhead (data, offset)
00621 #else
00622 PUBLIC acc_t *_bf_delhead (clnt_file, clnt_line, data, offset)
00623 char *clnt_file;
00624 int clnt_line;
00625 #endif
00626 register acc_t *data;
00627 register unsigned offset;
00628 {
00629 acc_t *new_acc;
00630
00631 assert(data);
00632
00633
00634 new_acc= data;
00635 while(offset >= new_acc->acc_length)
00636 {
00637 offset -= new_acc->acc_length;
00638 new_acc= new_acc->acc_next;
00639 #ifdef BUF_TRACK_ALLOC_FREE
00640 assert(new_acc || (printf("called from %s, %d\n",
00641 clnt_file, clnt_line),0));
00642 #else
00643 assert(new_acc);
00644 #endif
00645 }
00646
00647
00648 if (new_acc != data)
00649 {
00650 new_acc->acc_linkC++;
00651 bf_afree(data);
00652 data= new_acc;
00653 }
00654
00655
00656 if (data->acc_linkC != 1)
00657 {
00658 new_acc= bf_dupacc(data);
00659 bf_afree(data);
00660 data= new_acc;
00661 }
00662
00663
00664 data->acc_offset += offset;
00665 data->acc_length -= offset;
00666 return data;
00667 }
00668
00669
00670
00671
00672
00673 #ifndef BUF_TRACK_ALLOC_FREE
00674 PUBLIC acc_t *bf_append(data_first, data_second)
00675 #else
00676 PUBLIC acc_t *_bf_append(clnt_file, clnt_line, data_first, data_second)
00677 char *clnt_file;
00678 int clnt_line;
00679 #endif
00680 acc_t *data_first;
00681 acc_t *data_second;
00682 {
00683 acc_t *head, *tail, *new_acc, *acc_ptr_new, tmp_acc, *curr;
00684 char *src_ptr, *dst_ptr;
00685 size_t size, offset_old, offset_new, block_size_old, block_size;
00686
00687 if (!data_first)
00688 return data_second;
00689 if (!data_second)
00690 return data_first;
00691
00692 head= NULL;
00693 tail= NULL;
00694 while (data_first)
00695 {
00696 if (data_first->acc_linkC == 1)
00697 curr= data_first;
00698 else
00699 {
00700 curr= bf_dupacc(data_first);
00701 assert (curr->acc_linkC == 1);
00702 bf_afree(data_first);
00703 }
00704 data_first= curr->acc_next;
00705 if (!curr->acc_length)
00706 {
00707 curr->acc_next= NULL;
00708 bf_afree(curr);
00709 continue;
00710 }
00711 if (!head)
00712 head= curr;
00713 else
00714 tail->acc_next= curr;
00715 tail= curr;
00716 }
00717 if (!head)
00718 return data_second;
00719 tail->acc_next= NULL;
00720
00721 while (data_second && !data_second->acc_length)
00722 {
00723 curr= data_second;
00724 data_second= data_second->acc_next;
00725 if (data_second)
00726 data_second->acc_linkC++;
00727 bf_afree(curr);
00728 }
00729 if (!data_second)
00730 return head;
00731
00732 if (tail->acc_length + data_second->acc_length >
00733 tail->acc_buffer->buf_size)
00734 {
00735 tail->acc_next= data_second;
00736 return head;
00737 }
00738
00739 if (tail->acc_buffer->buf_size == bf_buf_gran &&
00740 tail->acc_buffer->buf_linkC == 1)
00741 {
00742 if (tail->acc_offset)
00743 {
00744 memmove(tail->acc_buffer->buf_data_p,
00745 ptr2acc_data(tail), tail->acc_length);
00746 tail->acc_offset= 0;
00747 }
00748 dst_ptr= ptr2acc_data(tail) + tail->acc_length;
00749 src_ptr= ptr2acc_data(data_second);
00750 memcpy(dst_ptr, src_ptr, data_second->acc_length);
00751 tail->acc_length += data_second->acc_length;
00752 tail->acc_next= data_second->acc_next;
00753 if (data_second->acc_next)
00754 data_second->acc_next->acc_linkC++;
00755 bf_afree(data_second);
00756 return head;
00757 }
00758
00759 new_acc= bf_small_memreq(tail->acc_length+data_second->acc_length);
00760 acc_ptr_new= new_acc;
00761 offset_old= 0;
00762 offset_new= 0;
00763 size= tail->acc_length;
00764 while (size)
00765 {
00766 assert (acc_ptr_new);
00767 if (offset_new == acc_ptr_new->acc_length)
00768 {
00769 offset_new= 0;
00770 acc_ptr_new= acc_ptr_new->acc_next;
00771 continue;
00772 }
00773 assert (offset_new < acc_ptr_new->acc_length);
00774 assert (offset_old < tail->acc_length);
00775 block_size_old= tail->acc_length - offset_old;
00776 block_size= acc_ptr_new->acc_length - offset_new;
00777 if (block_size > block_size_old)
00778 block_size= block_size_old;
00779 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
00780 ptr2acc_data(tail)+offset_old, block_size);
00781 offset_new += block_size;
00782 offset_old += block_size;
00783 size -= block_size;
00784 }
00785 offset_old= 0;
00786 size= data_second->acc_length;
00787 while (size)
00788 {
00789 assert (acc_ptr_new);
00790 if (offset_new == acc_ptr_new->acc_length)
00791 {
00792 offset_new= 0;
00793 acc_ptr_new= acc_ptr_new->acc_next;
00794 continue;
00795 }
00796 assert (offset_new < acc_ptr_new->acc_length);
00797 assert (offset_old < data_second->acc_length);
00798 block_size_old= data_second->acc_length - offset_old;
00799 block_size= acc_ptr_new->acc_length - offset_new;
00800 if (block_size > block_size_old)
00801 block_size= block_size_old;
00802 memcpy(ptr2acc_data(acc_ptr_new)+offset_new,
00803 ptr2acc_data(data_second)+offset_old, block_size);
00804 offset_new += block_size;
00805 offset_old += block_size;
00806 size -= block_size;
00807 }
00808 tmp_acc= *tail;
00809 *tail= *new_acc;
00810 *new_acc= tmp_acc;
00811
00812 bf_afree(new_acc);
00813 while (tail->acc_next)
00814 tail= tail->acc_next;
00815
00816 tail->acc_next= data_second->acc_next;
00817 if (data_second->acc_next)
00818 data_second->acc_next->acc_linkC++;
00819 bf_afree(data_second);
00820 return head;
00821 }
00822
00823 #if BUF512_NR
00824 PRIVATE void bf_512free(acc)
00825 acc_t *acc;
00826 {
00827 #ifdef BUF_CONSISTENCY_CHECK
00828 if (inet_buf_debug)
00829 memset(acc->acc_buffer->buf_data_p, 0xa5, 512);
00830 #endif
00831 acc->acc_next= buf512_freelist;
00832 buf512_freelist= acc;
00833 }
00834 #endif
00835 #if BUF2K_NR
00836 PRIVATE void bf_2Kfree(acc)
00837 acc_t *acc;
00838 {
00839 #ifdef BUF_CONSISTENCY_CHECK
00840 if (inet_buf_debug)
00841 memset(acc->acc_buffer->buf_data_p, 0xa5, 2*1024);
00842 #endif
00843 acc->acc_next= buf2K_freelist;
00844 buf2K_freelist= acc;
00845 }
00846 #endif
00847 #if BUF32K_NR
00848 PRIVATE void bf_32Kfree(acc)
00849 acc_t *acc;
00850 {
00851 #ifdef BUF_CONSISTENCY_CHECK
00852 if (inet_buf_debug)
00853 memset(acc->acc_buffer->buf_data_p, 0xa5, 32*1024);
00854 #endif
00855 acc->acc_next= buf32K_freelist;
00856 buf32K_freelist= acc;
00857 }
00858 #endif
00859
00860 #ifdef BUF_CONSISTENCY_CHECK
00861 PUBLIC int bf_consistency_check()
00862 {
00863 acc_t *acc;
00864 int silent;
00865 int error;
00866 int i;
00867
00868 buf_generation++;
00869
00870 for (i=0; i<CLIENT_NR; i++)
00871 {
00872 if (checkreq[i])
00873 (*checkreq[i])();
00874 }
00875
00876
00877 for(acc= acc_freelist; acc; acc= acc->acc_next)
00878 {
00879 if (acc->acc_generation == buf_generation-1)
00880 {
00881 acc->acc_generation= buf_generation;
00882 acc->acc_check_linkC= 0;
00883 }
00884 else
00885 {
00886 assert(acc->acc_generation == buf_generation &&
00887 acc->acc_check_linkC > 0);
00888 acc->acc_check_linkC= -acc->acc_check_linkC;
00889 }
00890 }
00891
00892 #if BUF512_NR
00893 count_free_bufs(buf512_freelist);
00894 #endif
00895 #if BUF2K_NR
00896 count_free_bufs(buf2K_freelist);
00897 #endif
00898 #if BUF32K_NR
00899 count_free_bufs(buf32K_freelist);
00900 #endif
00901
00902 error= 0;
00903
00904
00905 silent= 0;
00906 for (i=0, acc= accessors; i<ACC_NR; i++, acc++)
00907 {
00908 if (acc->acc_generation != buf_generation)
00909 {
00910 error++;
00911 assert(acc->acc_generation == buf_generation-1);
00912 acc->acc_generation= buf_generation;
00913 if (!silent)
00914 {
00915 printf(
00916 "acc[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
00917 i, acc, acc->acc_linkC, acc->acc_alloc_file, acc->acc_alloc_line);
00918 #if 0
00919 silent= 1;
00920 #endif
00921 }
00922 continue;
00923 }
00924 if (acc->acc_check_linkC == acc->acc_linkC)
00925 continue;
00926 error++;
00927 if (acc->acc_check_linkC < 0)
00928 {
00929 if (!silent)
00930 {
00931 printf(
00932 "acc[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
00933 i, acc->acc_alloc_file, acc->acc_alloc_line,
00934 acc->acc_free_file, acc->acc_free_line);
00935 }
00936 acc->acc_check_linkC= -acc->acc_check_linkC;
00937 if (acc->acc_check_linkC == acc->acc_linkC)
00938 {
00939 silent= 1;
00940 continue;
00941 }
00942 }
00943 if (!silent)
00944 {
00945 printf(
00946 "# of tracked links (%d) for acc[%d] don't match with stored link count %d\n",
00947 acc->acc_check_linkC, i, acc->acc_linkC);
00948 printf("acc[%d] was allocated at %s, %d\n",
00949 i, acc->acc_alloc_file, acc->acc_alloc_line);
00950 silent=1;
00951 }
00952 }
00953
00954
00955 #if BUF512_NR
00956 {
00957 for (i= 0; i<BUF512_NR; i++)
00958 {
00959 error |= report_buffer(&buffers512[i].buf_header,
00960 "512-buffer", i);
00961 }
00962 }
00963 #endif
00964 #if BUF2K_NR
00965 {
00966 for (i= 0; i<BUF2K_NR; i++)
00967 {
00968 error |= report_buffer(&buffers2K[i].buf_header,
00969 "2K-buffer", i);
00970 }
00971 }
00972 #endif
00973 #if BUF32K_NR
00974 {
00975 for (i= 0; i<BUF32K_NR; i++)
00976 {
00977 error |= report_buffer(&buffers32K[i].buf_header,
00978 "32K-buffer", i);
00979 }
00980 }
00981 #endif
00982
00983 return !error;
00984 }
00985
00986 PRIVATE void count_free_bufs(list)
00987 acc_t *list;
00988 {
00989 acc_t *acc;
00990 buf_t *buf;
00991
00992 for(acc= list; acc; acc= acc->acc_next)
00993 {
00994 if (acc->acc_generation != buf_generation-1)
00995 {
00996 assert(acc->acc_generation == buf_generation &&
00997 acc->acc_check_linkC > 0);
00998 acc->acc_check_linkC= -acc->acc_check_linkC;
00999 continue;
01000 }
01001 acc->acc_generation= buf_generation;
01002 acc->acc_check_linkC= 0;
01003
01004 buf= acc->acc_buffer;
01005 if (buf->buf_generation == buf_generation-1)
01006 {
01007 buf->buf_generation= buf_generation;
01008 buf->buf_check_linkC= 0;
01009 continue;
01010 }
01011 assert(buf->buf_generation == buf_generation &&
01012 buf->buf_check_linkC > 0);
01013 buf->buf_check_linkC= -buf->buf_check_linkC;
01014 }
01015 }
01016
01017 PRIVATE int report_buffer(buf, label, i)
01018 buf_t *buf;
01019 char *label;
01020 int i;
01021 {
01022 if (buf->buf_generation != buf_generation)
01023 {
01024 assert(buf->buf_generation == buf_generation-1);
01025 buf->buf_generation= buf_generation;
01026 printf(
01027 "%s[%d] (%p) has been lost with count %d, last allocated at %s, %d\n",
01028 label, i, buf,
01029 buf->buf_linkC, buf->buf_alloc_file,
01030 buf->buf_alloc_line);
01031 return 1;
01032 }
01033 if (buf->buf_check_linkC == buf->buf_linkC)
01034 return 0;
01035 if (buf->buf_check_linkC < 0)
01036 {
01037 printf(
01038 "%s[%d] is freed but still in use, allocated at %s, %d, freed at %s, %d\n",
01039 label, i, buf->buf_alloc_file, buf->buf_alloc_line,
01040 buf->buf_free_file, buf->buf_free_line);
01041 buf->buf_check_linkC= -buf->buf_check_linkC;
01042 if (buf->buf_check_linkC == buf->buf_linkC)
01043 return 1;
01044 }
01045 printf(
01046 "# of tracked links (%d) for %s[%d] don't match with stored link count %d\n",
01047 buf->buf_check_linkC, label, i, buf->buf_linkC);
01048 printf("%s[%d] was allocated at %s, %d\n",
01049 label, i, buf->buf_alloc_file, buf->buf_alloc_line);
01050 return 1;
01051 }
01052
01053 PUBLIC void bf_check_acc(acc)
01054 acc_t *acc;
01055 {
01056 buf_t *buf;
01057
01058 while(acc != NULL)
01059 {
01060 if (acc->acc_generation == buf_generation)
01061 {
01062 assert(acc->acc_check_linkC > 0);
01063 acc->acc_check_linkC++;
01064 return;
01065 }
01066 assert(acc->acc_generation == buf_generation-1);
01067 acc->acc_generation= buf_generation;
01068 acc->acc_check_linkC= 1;
01069
01070 buf= acc->acc_buffer;
01071 if (buf->buf_generation == buf_generation)
01072 {
01073 assert(buf->buf_check_linkC > 0);
01074 buf->buf_check_linkC++;
01075 }
01076 else
01077 {
01078 assert(buf->buf_generation == buf_generation-1);
01079 buf->buf_generation= buf_generation;
01080 buf->buf_check_linkC= 1;
01081 }
01082
01083 acc= acc->acc_next;
01084 }
01085 }
01086
01087 PUBLIC void _bf_mark_1acc(clnt_file, clnt_line, acc)
01088 char *clnt_file;
01089 int clnt_line;
01090 acc_t *acc;
01091 {
01092 acc->acc_alloc_file= clnt_file;
01093 acc->acc_alloc_line= clnt_line;
01094 }
01095
01096 PUBLIC void _bf_mark_acc(clnt_file, clnt_line, acc)
01097 char *clnt_file;
01098 int clnt_line;
01099 acc_t *acc;
01100 {
01101 buf_t *buf;
01102
01103 for (; acc; acc= acc->acc_next)
01104 {
01105 acc->acc_alloc_file= clnt_file;
01106 acc->acc_alloc_line= clnt_line;
01107 buf= acc->acc_buffer;
01108 buf->buf_alloc_file= clnt_file;
01109 buf->buf_alloc_line= clnt_line;
01110 }
01111 }
01112 #endif
01113
01114 PUBLIC int bf_linkcheck(acc)
01115 acc_t *acc;
01116 {
01117 int i;
01118
01119 buf_t *buffer;
01120 for (i= 0; i<ACC_NR && acc; i++, acc= acc->acc_next)
01121 {
01122 if (acc->acc_linkC <= 0)
01123 {
01124 printf("wrong acc_linkC (%d) for acc %p\n",
01125 acc->acc_linkC, acc);
01126 return 0;
01127 }
01128 if (acc->acc_offset < 0)
01129 {
01130 printf("wrong acc_offset (%d) for acc %p\n",
01131 acc->acc_offset, acc);
01132 return 0;
01133 }
01134 if (acc->acc_length < 0)
01135 {
01136 printf("wrong acc_length (%d) for acc %p\n",
01137 acc->acc_length, acc);
01138 return 0;
01139 }
01140 buffer= acc->acc_buffer;
01141 if (buffer == NULL)
01142 {
01143 printf("no buffer for acc %p\n", acc);
01144 return 0;
01145 }
01146 if (buffer->buf_linkC <= 0)
01147 {
01148 printf(
01149 "wrong buf_linkC (%d) for buffer %p, from acc %p\n",
01150 buffer->buf_linkC, buffer, acc);
01151 return 0;
01152 }
01153 if (acc->acc_offset + acc->acc_length > buffer->buf_size)
01154 {
01155 printf("%d + %d > %d for buffer %p, and acc %p\n",
01156 acc->acc_offset, acc->acc_length,
01157 buffer->buf_size, buffer, acc);
01158 return 0;
01159 }
01160 }
01161 if (acc != NULL)
01162 {
01163 printf("loop\n");
01164 return 0;
01165 }
01166 return 1;
01167 }
01168
01169 PRIVATE void free_accs()
01170 {
01171 int i, j;
01172
01173 DBLOCK(1, printf("free_accs\n"));
01174
01175 assert(bf_linkcheck(bf_linkcheck_acc));
01176 for (i=0; !acc_freelist && i<MAX_BUFREQ_PRI; i++)
01177 {
01178 for (j=0; j<CLIENT_NR; j++)
01179 {
01180 bf_free_bufsize= 0;
01181 if (freereq[j])
01182 {
01183 (*freereq[j])(i);
01184 assert(bf_linkcheck(bf_linkcheck_acc) ||
01185 (printf("just called %p\n",
01186 freereq[i]),0));
01187 }
01188 }
01189 }
01190 #if DEBUG
01191 printf("last level was level %d\n", i-1);
01192 #endif
01193 }
01194
01195 #ifndef BUF_TRACK_ALLOC_FREE
01196 PUBLIC acc_t *bf_align(acc, size, alignment)
01197 #else
01198 PUBLIC acc_t *_bf_align(clnt_file, clnt_line, acc, size, alignment)
01199 char *clnt_file;
01200 int clnt_line;
01201 #endif
01202 acc_t *acc;
01203 size_t size;
01204 size_t alignment;
01205 {
01206 char *ptr;
01207 size_t buf_size;
01208 acc_t *head, *tail;
01209
01210
01211 if (acc->acc_length >= size)
01212 {
01213 ptr= ptr2acc_data(acc);
01214 if (((unsigned)ptr & (alignment-1)) == 0)
01215 return acc;
01216 }
01217 buf_size= bf_bufsize(acc);
01218 #ifdef bf_align
01219 assert((size != 0 && buf_size != 0) ||
01220 (printf("bf_align(..., %d, %d) from %s, %d\n",
01221 size, alignment, clnt_file, clnt_line),0));
01222 #else
01223 assert(size != 0 && buf_size != 0);
01224 #endif
01225 if (buf_size <= size)
01226 {
01227 acc= bf_pack(acc);
01228 return acc;
01229 }
01230 head= bf_cut(acc, 0, size);
01231 tail= bf_cut(acc, size, buf_size-size);
01232 bf_afree(acc);
01233 head= bf_pack(head);
01234 assert(head->acc_next == NULL);
01235 head->acc_next= tail;
01236 return head;
01237 }
01238
01239 #if 0
01240 int chk_acc(acc)
01241 acc_t *acc;
01242 {
01243 int acc_nr;
01244
01245 if (!acc)
01246 return 1;
01247 if (acc < accessors || acc >= &accessors[ACC_NR])
01248 return 0;
01249 acc_nr= acc-accessors;
01250 return acc == &accessors[acc_nr];
01251 }
01252 #endif
01253
01254
01255
01256