1#!/bin/sh 2# 3# Usage: size_classes.sh <lg_qarr> <lg_tmin> <lg_parr> <lg_g> 4 5# The following limits are chosen such that they cover all supported platforms. 6 7# Pointer sizes. 8lg_zarr="2 3" 9 10# Quanta. 11lg_qarr=$1 12 13# The range of tiny size classes is [2^lg_tmin..2^(lg_q-1)]. 14lg_tmin=$2 15 16# Maximum lookup size. 17lg_kmax=12 18 19# Page sizes. 20lg_parr=`echo $3 | tr ',' ' '` 21 22# Size class group size (number of size classes for each size doubling). 23lg_g=$4 24 25pow2() { 26 e=$1 27 pow2_result=1 28 while [ ${e} -gt 0 ] ; do 29 pow2_result=$((${pow2_result} + ${pow2_result})) 30 e=$((${e} - 1)) 31 done 32} 33 34lg() { 35 x=$1 36 lg_result=0 37 while [ ${x} -gt 1 ] ; do 38 lg_result=$((${lg_result} + 1)) 39 x=$((${x} / 2)) 40 done 41} 42 43size_class() { 44 index=$1 45 lg_grp=$2 46 lg_delta=$3 47 ndelta=$4 48 lg_p=$5 49 lg_kmax=$6 50 51 if [ ${lg_delta} -ge ${lg_p} ] ; then 52 psz="yes" 53 else 54 pow2 ${lg_p}; p=${pow2_result} 55 pow2 ${lg_grp}; grp=${pow2_result} 56 pow2 ${lg_delta}; delta=${pow2_result} 57 sz=$((${grp} + ${delta} * ${ndelta})) 58 npgs=$((${sz} / ${p})) 59 if [ ${sz} -eq $((${npgs} * ${p})) ] ; then 60 psz="yes" 61 else 62 psz="no" 63 fi 64 fi 65 66 lg ${ndelta}; lg_ndelta=${lg_result}; pow2 ${lg_ndelta} 67 if [ ${pow2_result} -lt ${ndelta} ] ; then 68 rem="yes" 69 else 70 rem="no" 71 fi 72 73 lg_size=${lg_grp} 74 if [ $((${lg_delta} + ${lg_ndelta})) -eq ${lg_grp} ] ; then 75 lg_size=$((${lg_grp} + 1)) 76 else 77 lg_size=${lg_grp} 78 rem="yes" 79 fi 80 81 if [ ${lg_size} -lt $((${lg_p} + ${lg_g})) ] ; then 82 bin="yes" 83 else 84 bin="no" 85 fi 86 if [ ${lg_size} -lt ${lg_kmax} \ 87 -o ${lg_size} -eq ${lg_kmax} -a ${rem} = "no" ] ; then 88 lg_delta_lookup=${lg_delta} 89 else 90 lg_delta_lookup="no" 91 fi 92 printf ' SC(%3d, %6d, %8d, %6d, %3s, %3s, %2s) \\\n' ${index} ${lg_grp} ${lg_delta} ${ndelta} ${psz} ${bin} ${lg_delta_lookup} 93 # Defined upon return: 94 # - psz ("yes" or "no") 95 # - bin ("yes" or "no") 96 # - lg_delta_lookup (${lg_delta} or "no") 97} 98 99sep_line() { 100 echo " \\" 101} 102 103size_classes() { 104 lg_z=$1 105 lg_q=$2 106 lg_t=$3 107 lg_p=$4 108 lg_g=$5 109 110 pow2 $((${lg_z} + 3)); ptr_bits=${pow2_result} 111 pow2 ${lg_g}; g=${pow2_result} 112 113 echo "#define SIZE_CLASSES \\" 114 echo " /* index, lg_grp, lg_delta, ndelta, psz, bin, lg_delta_lookup */ \\" 115 116 ntbins=0 117 nlbins=0 118 lg_tiny_maxclass='"NA"' 119 nbins=0 120 npsizes=0 121 122 # Tiny size classes. 123 ndelta=0 124 index=0 125 lg_grp=${lg_t} 126 lg_delta=${lg_grp} 127 while [ ${lg_grp} -lt ${lg_q} ] ; do 128 size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} 129 if [ ${lg_delta_lookup} != "no" ] ; then 130 nlbins=$((${index} + 1)) 131 fi 132 if [ ${psz} = "yes" ] ; then 133 npsizes=$((${npsizes} + 1)) 134 fi 135 if [ ${bin} != "no" ] ; then 136 nbins=$((${index} + 1)) 137 fi 138 ntbins=$((${ntbins} + 1)) 139 lg_tiny_maxclass=${lg_grp} # Final written value is correct. 140 index=$((${index} + 1)) 141 lg_delta=${lg_grp} 142 lg_grp=$((${lg_grp} + 1)) 143 done 144 145 # First non-tiny group. 146 if [ ${ntbins} -gt 0 ] ; then 147 sep_line 148 # The first size class has an unusual encoding, because the size has to be 149 # split between grp and delta*ndelta. 150 lg_grp=$((${lg_grp} - 1)) 151 ndelta=1 152 size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} 153 index=$((${index} + 1)) 154 lg_grp=$((${lg_grp} + 1)) 155 lg_delta=$((${lg_delta} + 1)) 156 if [ ${psz} = "yes" ] ; then 157 npsizes=$((${npsizes} + 1)) 158 fi 159 fi 160 while [ ${ndelta} -lt ${g} ] ; do 161 size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} 162 index=$((${index} + 1)) 163 ndelta=$((${ndelta} + 1)) 164 if [ ${psz} = "yes" ] ; then 165 npsizes=$((${npsizes} + 1)) 166 fi 167 done 168 169 # All remaining groups. 170 lg_grp=$((${lg_grp} + ${lg_g})) 171 while [ ${lg_grp} -lt $((${ptr_bits} - 1)) ] ; do 172 sep_line 173 ndelta=1 174 if [ ${lg_grp} -eq $((${ptr_bits} - 2)) ] ; then 175 ndelta_limit=$((${g} - 1)) 176 else 177 ndelta_limit=${g} 178 fi 179 while [ ${ndelta} -le ${ndelta_limit} ] ; do 180 size_class ${index} ${lg_grp} ${lg_delta} ${ndelta} ${lg_p} ${lg_kmax} 181 if [ ${lg_delta_lookup} != "no" ] ; then 182 nlbins=$((${index} + 1)) 183 # Final written value is correct: 184 lookup_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" 185 fi 186 if [ ${psz} = "yes" ] ; then 187 npsizes=$((${npsizes} + 1)) 188 fi 189 if [ ${bin} != "no" ] ; then 190 nbins=$((${index} + 1)) 191 # Final written value is correct: 192 small_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" 193 if [ ${lg_g} -gt 0 ] ; then 194 lg_large_minclass=$((${lg_grp} + 1)) 195 else 196 lg_large_minclass=$((${lg_grp} + 2)) 197 fi 198 fi 199 # Final written value is correct: 200 huge_maxclass="((((size_t)1) << ${lg_grp}) + (((size_t)${ndelta}) << ${lg_delta}))" 201 index=$((${index} + 1)) 202 ndelta=$((${ndelta} + 1)) 203 done 204 lg_grp=$((${lg_grp} + 1)) 205 lg_delta=$((${lg_delta} + 1)) 206 done 207 echo 208 nsizes=${index} 209 210 # Defined upon completion: 211 # - ntbins 212 # - nlbins 213 # - nbins 214 # - nsizes 215 # - npsizes 216 # - lg_tiny_maxclass 217 # - lookup_maxclass 218 # - small_maxclass 219 # - lg_large_minclass 220 # - huge_maxclass 221} 222 223cat <<EOF 224/* This file was automatically generated by size_classes.sh. */ 225/******************************************************************************/ 226#ifdef JEMALLOC_H_TYPES 227 228/* 229 * This header requires LG_SIZEOF_PTR, LG_TINY_MIN, LG_QUANTUM, and LG_PAGE to 230 * be defined prior to inclusion, and it in turn defines: 231 * 232 * LG_SIZE_CLASS_GROUP: Lg of size class count for each size doubling. 233 * SIZE_CLASSES: Complete table of SC(index, lg_grp, lg_delta, ndelta, psz, 234 * bin, lg_delta_lookup) tuples. 235 * index: Size class index. 236 * lg_grp: Lg group base size (no deltas added). 237 * lg_delta: Lg delta to previous size class. 238 * ndelta: Delta multiplier. size == 1<<lg_grp + ndelta<<lg_delta 239 * psz: 'yes' if a multiple of the page size, 'no' otherwise. 240 * bin: 'yes' if a small bin size class, 'no' otherwise. 241 * lg_delta_lookup: Same as lg_delta if a lookup table size class, 'no' 242 * otherwise. 243 * NTBINS: Number of tiny bins. 244 * NLBINS: Number of bins supported by the lookup table. 245 * NBINS: Number of small size class bins. 246 * NSIZES: Number of size classes. 247 * NPSIZES: Number of size classes that are a multiple of (1U << LG_PAGE). 248 * LG_TINY_MAXCLASS: Lg of maximum tiny size class. 249 * LOOKUP_MAXCLASS: Maximum size class included in lookup table. 250 * SMALL_MAXCLASS: Maximum small size class. 251 * LG_LARGE_MINCLASS: Lg of minimum large size class. 252 * HUGE_MAXCLASS: Maximum (huge) size class. 253 */ 254 255#define LG_SIZE_CLASS_GROUP ${lg_g} 256 257EOF 258 259for lg_z in ${lg_zarr} ; do 260 for lg_q in ${lg_qarr} ; do 261 lg_t=${lg_tmin} 262 while [ ${lg_t} -le ${lg_q} ] ; do 263 # Iterate through page sizes and compute how many bins there are. 264 for lg_p in ${lg_parr} ; do 265 echo "#if (LG_SIZEOF_PTR == ${lg_z} && LG_TINY_MIN == ${lg_t} && LG_QUANTUM == ${lg_q} && LG_PAGE == ${lg_p})" 266 size_classes ${lg_z} ${lg_q} ${lg_t} ${lg_p} ${lg_g} 267 echo "#define SIZE_CLASSES_DEFINED" 268 echo "#define NTBINS ${ntbins}" 269 echo "#define NLBINS ${nlbins}" 270 echo "#define NBINS ${nbins}" 271 echo "#define NSIZES ${nsizes}" 272 echo "#define NPSIZES ${npsizes}" 273 echo "#define LG_TINY_MAXCLASS ${lg_tiny_maxclass}" 274 echo "#define LOOKUP_MAXCLASS ${lookup_maxclass}" 275 echo "#define SMALL_MAXCLASS ${small_maxclass}" 276 echo "#define LG_LARGE_MINCLASS ${lg_large_minclass}" 277 echo "#define HUGE_MAXCLASS ${huge_maxclass}" 278 echo "#endif" 279 echo 280 done 281 lg_t=$((${lg_t} + 1)) 282 done 283 done 284done 285 286cat <<EOF 287#ifndef SIZE_CLASSES_DEFINED 288# error "No size class definitions match configuration" 289#endif 290#undef SIZE_CLASSES_DEFINED 291/* 292 * The size2index_tab lookup table uses uint8_t to encode each bin index, so we 293 * cannot support more than 256 small size classes. Further constrain NBINS to 294 * 255 since all small size classes, plus a "not small" size class must be 295 * stored in 8 bits of arena_chunk_map_bits_t's bits field. 296 */ 297#if (NBINS > 255) 298# error "Too many small size classes" 299#endif 300 301#endif /* JEMALLOC_H_TYPES */ 302/******************************************************************************/ 303#ifdef JEMALLOC_H_STRUCTS 304 305 306#endif /* JEMALLOC_H_STRUCTS */ 307/******************************************************************************/ 308#ifdef JEMALLOC_H_EXTERNS 309 310 311#endif /* JEMALLOC_H_EXTERNS */ 312/******************************************************************************/ 313#ifdef JEMALLOC_H_INLINES 314 315 316#endif /* JEMALLOC_H_INLINES */ 317/******************************************************************************/ 318EOF 319