• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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