LTP GCOV extension - code coverage report
Current view: directory - csrc/cl - arena.c
Test: app.info
Date: 2007-12-10 Instrumented lines: 74
Code covered: 89.2 % Executed lines: 66

       1                 : /*
       2                 :         Copyright (C) 2007, Bruce Ediger
       3                 : 
       4                 :     This file is part of cl.
       5                 : 
       6                 :     cl is free software; you can redistribute it and/or modify
       7                 :     it under the terms of the GNU General Public License as published by
       8                 :     the Free Software Foundation; either version 2 of the License, or
       9                 :     (at your option) any later version.
      10                 : 
      11                 :     cl is distributed in the hope that it will be useful,
      12                 :     but WITHOUT ANY WARRANTY; without even the implied warranty of
      13                 :     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14                 :     GNU General Public License for more details.
      15                 : 
      16                 :     You should have received a copy of the GNU General Public License
      17                 :     along with cl; if not, write to the Free Software
      18                 :     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
      19                 : 
      20                 : */
      21                 : #include <stdio.h>
      22                 : #include <unistd.h>  /* getpagesize() */
      23                 : #include <stdlib.h>  /* malloc(), free() */
      24                 : #include <assert.h>  /* malloc(), free() */
      25                 : 
      26                 : #include <arena.h>
      27                 : 
      28                 : #define roundup(x, y)   ((((x)+((y)-1))/(y))*(y))
      29                 : 
      30                 : union combo {
      31                 :         char c;
      32                 :         short s;
      33                 :         int i;
      34                 :         long l;
      35                 :         long long ll;
      36                 :         void *vp;
      37                 :         char *cp;
      38                 :         short *sp;
      39                 :         int  *ip;
      40                 :         long *lp;
      41                 :         float f;
      42                 :         double d;
      43                 : };
      44                 : 
      45                 : struct memory_arena {
      46                 :         char *first_allocation;
      47                 :         char *next_allocation;
      48                 :         int sz;                     /* max free size */
      49                 :         int remaining;              /* how many bytes remain in allocation */
      50                 :         struct memory_arena *next;
      51                 :         int usage_info;
      52                 :         int sn;                     /* serial number: malloc order */
      53                 : };
      54                 : 
      55                 : static int pagesize = 0;
      56                 : static int headersize = 0;
      57                 : static int combosize = 0;
      58                 : 
      59                 : /* Public way to get a new struct memory_arena
      60                 :  * The first struct memory_arena in a chain constitutes a "dummy",
      61                 :  * an empty head element of a FIFO (stack) of structs memory_arena.
      62                 :  * The first allocation demanded from a memory arena will cause
      63                 :  * the malloc() of one or more pages, and a 2nd element in the stack.
      64                 :  */
      65                 : struct memory_arena *
      66                 : new_arena(int memory_info_flag)
      67              70 : {
      68              70 :         struct memory_arena *ra = NULL;
      69                 : 
      70              70 :         if (!pagesize)
      71                 :         {
      72              70 :                 combosize = sizeof(union combo);
      73              70 :                 pagesize = getpagesize();
      74              70 :                 headersize = roundup(sizeof(struct memory_arena), combosize);
      75                 :         }
      76                 : 
      77              70 :         ra = malloc(sizeof(*ra));
      78                 : 
      79              70 :         ra->sz = 0;
      80              70 :         ra->remaining = 0;
      81              70 :         ra->first_allocation = ra->next_allocation = NULL;
      82              70 :         ra->next = NULL;
      83              70 :         ra->usage_info = memory_info_flag;
      84              70 :         ra->sn = 0;
      85                 : 
      86              70 :         return ra;
      87                 : }
      88                 : 
      89                 : void
      90                 : deallocate_arena(struct memory_arena *ma, int memory_info_flag)
      91              69 : {
      92              69 :         int free_arena_cnt = 0;
      93              69 :         int maxsz = 0;
      94            2279 :         while (ma)
      95                 :         {
      96            2141 :                 struct memory_arena *tmp = ma->next;
      97                 : 
      98            2141 :                 if (ma->sz > maxsz) maxsz = ma->sz;
      99                 : 
     100            2141 :                 ma->next = NULL;
     101            2141 :                 free(ma);
     102                 : 
     103            2141 :                 ma = tmp;
     104            2141 :                 ++free_arena_cnt;
     105                 :         }
     106                 : 
     107              69 :         if (memory_info_flag)
     108                 :         {
     109               2 :                 fprintf(stderr, "Page size %d (0x%x)\n", pagesize, pagesize);
     110               2 :                 fprintf(stderr, "Header size %d (0x%x)\n", headersize, headersize);
     111               2 :                 fprintf(stderr, "Allocated %d arenas\n", free_arena_cnt);
     112               2 :                 fprintf(stderr, "Max arena size %d (0x%x)\n", maxsz, maxsz);
     113                 :         }
     114              69 : }
     115                 : 
     116                 : void
     117                 : free_arena_contents(struct memory_arena *ma)
     118            5818 : {
     119            5818 :         int last_sn = ma->sn;
     120            5818 :         int max_sn = ma->sn;
     121            5818 :         int arena_count = 0;
     122                 : 
     123            5818 :         ma = ma->next; /* dummy head node */
     124           66373 :         while (ma)
     125                 :         {
     126           54737 :                 ++arena_count;
     127                 : 
     128           54737 :                 if (ma->sn >= last_sn + 1)
     129                 :                 {
     130               0 :                         fprintf(stderr, "Loop in chain of allocations: S/N %d, next S/N %d\n",
     131                 :                                 last_sn, ma->sn);
     132               0 :                         fprintf(stderr, "Allocated %d arenas\n", max_sn);
     133               0 :                         break;
     134                 :                 } else
     135           54737 :                         last_sn = ma->sn;
     136                 : 
     137           54737 :                 if (ma->sn > max_sn)
     138                 :                 {
     139               0 :                         fprintf(stderr, "Chain of allocations out of order: max S/N %d, S/N %d\n",
     140                 :                                 max_sn, ma->sn);
     141               0 :                         fprintf(stderr, "Allocated %d arenas\n", max_sn);
     142               0 :                         break;
     143                 :                 }
     144                 : 
     145           54737 :                 if (arena_count > max_sn)
     146                 :                 {
     147               0 :                         fprintf(stderr, "Found at least %d allocations on chain, should only have %d\n",
     148                 :                                 arena_count, max_sn);
     149               0 :                         break;
     150                 :                 }
     151                 : 
     152           54737 :                 ma->remaining = ma->sz;
     153           54737 :                 ma->next_allocation = ma->first_allocation;
     154           54737 :                 ma = ma->next;
     155                 :         }
     156            5818 : }
     157                 : 
     158                 : void *
     159                 : arena_alloc(struct memory_arena *ma, size_t size)
     160         2145250 : {
     161         2145250 :         void *r = NULL;
     162                 :         struct memory_arena *ca;
     163                 :         size_t nsize;
     164                 : 
     165         2145250 :         assert(NULL != ma);
     166                 : 
     167                 :         /* What you actually have to allocate to get to
     168                 :          * a block "suitably aligned" for any use. */
     169         2145250 :         nsize = roundup(size, combosize);
     170                 : 
     171         2145250 :         ca = ma->next;
     172                 : 
     173      1412756767 :         while (ca && nsize > ca->remaining)
     174      1408466267 :                 ca = ca->next;
     175                 : 
     176         2145250 :         if (NULL == ca)
     177                 :         {
     178                 : 
     179                 :                 /* You could do something like moving all arenas with
     180                 :                  * less than combosize remaining into a 2nd list - one
     181                 :                  * that never gets checked, as combosize is the minimum
     182                 :                  * allocation possible. */
     183                 : 
     184                 :                 /* create a new struct memory_arena of at least 1 page */
     185            2073 :                 size_t arena_size = roundup((nsize + headersize), pagesize);
     186                 : 
     187            2073 :                 ca = malloc(arena_size);
     188                 : 
     189            2073 :                 ca->first_allocation = ((char *)ca) + headersize;
     190            2073 :                 ca->next_allocation = ca->first_allocation;
     191            2073 :                 ca->sz = arena_size - headersize;
     192            2073 :                 ca->remaining = ca->sz;
     193                 : 
     194                 :                 /* Each struct arena gets a unique serial number,
     195                 :                  * and the dummy "head" node sn field has a count of
     196                 :                  * how many structs arena reside in the list.
     197                 :                  */
     198            2073 :                 ca->sn = ++ma->sn;
     199                 : 
     200                 :                 /* since the next 2 lines make a FIFO stack of structs
     201                 :                  * arena, the serial numbers must decrease by one 
     202                 :                  * as you walk the stack. */
     203            2073 :                 ca->next = ma->next;
     204            2073 :                 ma->next = ca;
     205                 :         }
     206                 : 
     207         2145250 :         r = ca->next_allocation;
     208         2145250 :         ca->next_allocation += nsize; /* next_allocation stays aligned */
     209         2145250 :         ca->remaining -= nsize;
     210                 : 
     211         2145250 :         return r;
     212                 : }
     213                 : 

Generated by: LTP GCOV extension version 1.6