The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/servers/inet/buf.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 0b7bdb0bead877414378a01a9195d5c4


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.