LCOV - code coverage report
Current view: directory - src/trusted/service_runtime - dyn_array.c (source / functions) Found Hit Coverage
Test: coverage.lcov Lines: 92 81 88.0 %
Date: 2014-09-25 Functions: 0 0 -

       1                 : /*
       2                 :  * Copyright 2008 The Native Client Authors. All rights reserved.
       3                 :  * Use of this source code is governed by a BSD-style license that can be
       4                 :  * found in the LICENSE file.
       5                 :  */
       6                 : 
       7                 : /*
       8                 :  * Implementation of dynamic arrays.
       9                 :  */
      10                 : 
      11                 : #include "native_client/src/include/portability.h"
      12                 : 
      13                 : #define DYN_ARRAY_DEBUG 1
      14                 : 
      15                 : #include <stdlib.h>
      16                 : #include <string.h>
      17                 : 
      18                 : #if DYN_ARRAY_DEBUG
      19                 : # include "native_client/src/shared/platform/nacl_log.h"
      20                 : #endif
      21                 : 
      22                 : #include "native_client/src/trusted/service_runtime/dyn_array.h"
      23                 : 
      24                 : 
      25                 : static int const kBitsPerWord = 32;
      26                 : static int const kWordIndexShift = 5;  /* 2**kWordIndexShift==kBitsPerWord */
      27                 : 
      28                 : 
      29               1 : static INLINE size_t BitsToAllocWords(size_t nbits) {
      30               1 :   return (nbits + kBitsPerWord - 1) >> kWordIndexShift;
      31               1 : }
      32                 : 
      33                 : 
      34               1 : static INLINE size_t BitsToIndex(size_t nbits) {
      35               1 :   return nbits >> kWordIndexShift;
      36               1 : }
      37                 : 
      38                 : 
      39               1 : static INLINE size_t BitsToOffset(size_t nbits) {
      40               1 :   return nbits & (kBitsPerWord - 1);
      41               1 : }
      42                 : 
      43                 : 
      44                 : int DynArrayCtor(struct DynArray  *dap,
      45               1 :                  size_t           initial_size) {
      46               1 :   if (initial_size == 0) {
      47               0 :     initial_size = 32;
      48                 :   }
      49               1 :   dap->num_entries = 0u;
      50                 :   /* calloc should check internally, but we're paranoid */
      51                 :   if (SIZE_T_MAX / sizeof *dap->ptr_array < initial_size ||
      52               1 :       SIZE_T_MAX/ sizeof *dap->available < BitsToAllocWords(initial_size)) {
      53                 :     /* would integer overflow */
      54               0 :     return 0;
      55                 :   }
      56               1 :   dap->ptr_array = calloc(initial_size, sizeof *dap->ptr_array);
      57               1 :   if (NULL == dap->ptr_array) {
      58               0 :     return 0;
      59                 :   }
      60                 :   dap->available = calloc(BitsToAllocWords(initial_size),
      61               1 :                           sizeof *dap->available);
      62               1 :   if (NULL == dap->available) {
      63               0 :     free(dap->ptr_array);
      64               0 :     dap->ptr_array = NULL;
      65               0 :     return 0;
      66                 :   }
      67               1 :   dap->avail_ix = 0;  /* hint */
      68                 : 
      69               1 :   dap->ptr_array_space = initial_size;
      70               1 :   return 1;
      71               1 : }
      72                 : 
      73                 : 
      74               1 : void DynArrayDtor(struct DynArray *dap) {
      75               1 :   dap->num_entries = 0;  /* assume user has freed entries */
      76               1 :   free(dap->ptr_array);
      77               1 :   dap->ptr_array = NULL;
      78               1 :   dap->ptr_array_space = 0;
      79               1 :   free(dap->available);
      80               1 :   dap->available = NULL;
      81               1 : }
      82                 : 
      83                 : 
      84                 : void *DynArrayGet(struct DynArray *dap,
      85               1 :                   size_t          idx) {
      86               1 :   if (idx < dap->num_entries) {
      87               1 :     return dap->ptr_array[idx];
      88                 :   }
      89               0 :   return NULL;
      90               1 : }
      91                 : 
      92                 : 
      93                 : int DynArraySet(struct DynArray *dap,
      94                 :                 size_t          idx,
      95               1 :                 void            *ptr) {
      96                 :   size_t desired_space;
      97                 :   size_t tmp;
      98                 :   size_t ix;
      99                 : 
     100                 :   for (desired_space = dap->ptr_array_space;
     101                 :        idx >= desired_space;
     102               1 :        desired_space = tmp) {
     103               1 :     tmp = 2 * desired_space;
     104               1 :     if (tmp < desired_space) {
     105               0 :       return 0;  /* failed */
     106                 :     }
     107               1 :   }
     108               1 :   if (desired_space != dap->ptr_array_space) {
     109                 :     /* need to grow */
     110                 : 
     111                 :     void      **new_space;
     112                 :     uint32_t  *new_avail;
     113                 :     size_t    new_avail_nwords;
     114                 :     size_t    old_avail_nwords;
     115                 : 
     116               1 :     new_space = realloc(dap->ptr_array, desired_space * sizeof *new_space);
     117               1 :     if (NULL == new_space) {
     118               0 :       return 0;
     119                 :     }
     120                 :     memset((void *) (new_space + dap->ptr_array_space),
     121                 :            0,
     122               1 :            (desired_space - dap->ptr_array_space) * sizeof *new_space);
     123               1 :     dap->ptr_array = new_space;
     124                 : 
     125               1 :     old_avail_nwords = BitsToAllocWords(dap->ptr_array_space);
     126               1 :     new_avail_nwords = BitsToAllocWords(desired_space);
     127                 : 
     128                 :     new_avail = realloc(dap->available,
     129               1 :                         new_avail_nwords * sizeof *new_avail);
     130               1 :     if (NULL == new_avail) {
     131               0 :       return 0;
     132                 :     }
     133                 :     memset((void *) &new_avail[old_avail_nwords],
     134                 :            0,
     135               1 :            (new_avail_nwords - old_avail_nwords) * sizeof *new_avail);
     136               1 :     dap->available = new_avail;
     137                 : 
     138               1 :     dap->ptr_array_space = desired_space;
     139                 :   }
     140               1 :   dap->ptr_array[idx] = ptr;
     141               1 :   ix = BitsToIndex(idx);
     142                 : #if DYN_ARRAY_DEBUG
     143                 :   NaClLog(4, "Set(%"NACL_PRIuS",%p) @ix %"NACL_PRIuS": 0x%08x\n",
     144               1 :           idx, ptr, ix, dap->available[ix]);
     145                 : #endif
     146               1 :   if (NULL != ptr) {
     147               1 :     dap->available[ix] |= (1 << BitsToOffset(idx));
     148               1 :   } else {
     149               1 :     dap->available[ix] &= ~(1 << BitsToOffset(idx));
     150               1 :     if (ix < dap->avail_ix) {
     151               1 :       dap->avail_ix = ix;
     152                 :     }
     153                 :   }
     154                 : #if DYN_ARRAY_DEBUG
     155                 :   NaClLog(4, "After @ix %"NACL_PRIuS": 0x%08x, avail_ix %"NACL_PRIuS"\n",
     156               1 :           ix, dap->available[ix], dap->avail_ix);
     157                 : #endif
     158               1 :   if (dap->num_entries <= idx) {
     159               1 :     dap->num_entries = idx + 1;
     160                 :   }
     161               1 :   return 1;
     162               1 : }
     163                 : 
     164                 : 
     165               1 : size_t DynArrayFirstAvail(struct DynArray *dap) {
     166                 :   size_t ix;
     167                 :   size_t last_ix;
     168                 :   size_t avail_pos;
     169                 : 
     170               1 :   last_ix = BitsToAllocWords(dap->ptr_array_space);
     171                 : 
     172                 : #if DYN_ARRAY_DEBUG
     173               1 :   for (ix = 0; ix < last_ix; ++ix) {
     174               1 :     NaClLog(4, "ix %"NACL_PRIuS": 0x%08x\n", ix, dap->available[ix]);
     175               1 :   }
     176                 : #endif
     177               1 :   for (ix = dap->avail_ix; ix < last_ix; ++ix) {
     178               1 :     if (0U != ~dap->available[ix]) {
     179                 : #if DYN_ARRAY_DEBUG
     180               1 :       NaClLog(4, "found first not-all-ones ix %"NACL_PRIuS"\n", ix);
     181                 : #endif
     182               1 :       dap->avail_ix = ix;
     183               1 :       break;
     184                 :     }
     185               1 :   }
     186               1 :   if (ix < last_ix) {
     187               1 :     avail_pos = ffs(~dap->available[ix]) - 1;
     188               1 :     avail_pos += ix << kWordIndexShift;
     189               1 :   } else {
     190               0 :     avail_pos = dap->ptr_array_space;
     191                 :   }
     192               1 :   return avail_pos;
     193               1 : }

Generated by: LCOV version 1.7