buf.c

Go to the documentation of this file.
00001 /*
00002 This file contains routines for buffer management.
00003 
00004 Copyright 1995 Philip Homburg
00005 */
00006 
00007 #define BUF_IMPLEMENTATION      1       /* Avoid some macros */
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 bf_memreq
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                 /* Note the tricky dangling else... */
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                 /* Sort attempts by buffer size */
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 bf_small_memreq
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         /* Check if old acc is good enough. */
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         /* Find the acc we need to modify. */
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         /* Discard the old acc(s) */
00648         if (new_acc != data)
00649         {
00650                 new_acc->acc_linkC++;
00651                 bf_afree(data);
00652                 data= new_acc;
00653         }
00654 
00655         /* Make sure that acc_linkC == 1 */
00656         if (data->acc_linkC != 1)
00657         {
00658                 new_acc= bf_dupacc(data);
00659                 bf_afree(data);
00660                 data= new_acc;
00661         }
00662 
00663         /* Delete the last bit by modifying acc_offset and acc_length */
00664         data->acc_offset += offset;
00665         data->acc_length -= offset;
00666         return data;
00667 }
00668 
00669 /*
00670 bf_append
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         /* Add information about free accessors */
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         /* Report about accessors */
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         /* Report about buffers */
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         /* Fast check if the buffer is aligned already. */
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  * $PchId: buf.c,v 1.19 2003/09/10 08:54:23 philip Exp $
01256  */

Generated on Fri Apr 14 22:57:30 2006 for minix by  doxygen 1.4.6