Skip to content

Commit e0aa98a

Browse files
committed
mem: HG_MALLOC - slab allocator with elastic arenas
A new shared- and private-memory allocator, selected at runtime with -a HG_MALLOC (or -s/-k for one memory type); no behaviour change for existing configurations. - 21 size classes (64 B - 64 KB) served from per-process free lists, so the common allocation and free take no lock; cells move between processes through a shared per-class pool, in batches. Larger requests go to a coalescing large tier. - A transfer cache in each shared arena parks a donated private chain whole and hands it whole to a refill, a pointer swap under the arena lock instead of a per-cell walk; up to 64 chains per class, 1/128 of the arena and at most 32 MB. An idle class gives one chain back to its blocks per GC cycle; a carve at exhaustion drains them all. - Blocks are carved from a buddy allocator over a grid of pages the size of the host's huge page (2 MB on x86-64; 256 KB for small arenas on 4 KB memory), whichever tier backs them; a block whose cells are all free returns to the buddy and can be re-cut for any class. - The arena is acquired through a four-tier ladder - MAP_HUGETLB, THP via MADV_HUGEPAGE, MADV_COLLAPSE, plain 4 KB pages - each tier verified from the kernel's counters. Huge pages are an optimisation, not a requirement. MAP_HUGETLB is for shared arenas only; a private arena starts on THP or 4 KB pages. A refused MAP_HUGETLB is logged with the pool's free pages per NUMA node. On tier 3 a grow done by a worker that ran out of memory is published on 4 KB pages at once and the maintenance process collapses it afterwards, so no worker waits for MADV_COLLAPSE. - Elastic arenas: -m INIT:CAP / -M INIT:CAP (k/m/g suffixes, bare numbers in MB) reserve the cap and commit pages on demand, in a configurable granule (shm_grow_granule / pkg_grow_granule), growing on exhaustion or ahead of it through an auto_scaling_profile (shm_/pkg_auto_scaling_profile), and releasing quiet pages. A maintenance process grows ahead of demand and runs the release with the arena lock dropped. Growth stops at the cap, the backing tier and a host free-memory floor (hg_ram_floor_mb); a sustained refusal by the backing or the floor latches GROW-BLOCKED, raised as E_CORE_SHM_GROW_BLOCKED (reaching the cap is only a notice). - Host memory is checked before anything is committed, on every tier (MemAvailable above hg_ram_floor_mb, the memory cgroup's limit, plus the hugetlb pool for arenas on hugetlb pages): at startup for every process's -M INIT (refuse when the startup processes do not fit, warn for the auto-scaling maximum and for caps beyond MemTotal), before each fork (an auto-scaler fork that does not fit is skipped), and on each arena creation and grow. - On hugetlb pages every grow is an mlock() of the new range, and mlock() checks RLIMIT_MEMLOCK there as well: the arena warns at startup (and under -C) when the limit cannot cover its growth, and a refused grow names the resource that ran out - the limit or the hugetlb pool. On 4 KB and THP pages a limit too low to pin the arena leaves it running and growing unpinned (swappable) instead. - Every cell header carries the cell's state and a check over its address, class and state; a free moves it from live to free in one compare-and-swap, so a double free is refused, also from two processes at once, and a damaged header is refused, not followed. A per-block free map at the pool boundary stops a free-list walk at a scribbled link. Each is counted and logged and the process keeps running. hg_mem_check = 1 adds a tail guard checked at free and realloc, 2 also aborts on the first corruption. HG_MALLOC_DBG adds red zones and a quarantine of freed cells. ASan or Valgrind (-DHG_VALGRIND) is told which bytes of a private arena a caller may touch, ThreadSanitizer about the arena lock. - core:hg_stats (MI) per arena: tier, committed/reserved, per-class carve and reuse, grows/shrinks, the last grow refusal and its cause, whether the arena runs unpinned, transfer-cache puts/gets and parked chains, failed allocations (alloc_failed, out_of_memory), lock hold/wait histograms per reason and the corruption counters; core:hg_advise (MI) recommends -m/-M from the peaks reached; an hgmem: statistics group, including hg_pkg_grow_refused and hg_pkg_grow_blocked summed over every process's private arena; E_CORE_HG_LOCK_STALL for a hold above hg_lock_stall_us. - mem/mem_arena.h: a module may ask for its own HG-managed arena, independent of the core allocator choice (stubs returning NULL when HG is not built). - Unit tests (mem/test) for the allocator and its pkg/shm integration, fork, double free, corruption and growth cases; CI runs the unit tests with HG_MALLOC and HG_MALLOC_DBG as well. - modules/hgstress: a soak and fault-injection test module, excluded from the default build. Every worker churns stamped shm cells across all classes and the large tier and verifies the stamps while the others churn; MI commands park and release memory to drive grow and shrink, and inject a double free, an overrun or a scribbled free-list link. - Two core fixes found on the way: add_stats_group() sized a group's array as sizeof(stat_var) * no + 1, giving the first stat a 1-byte array; and -m/-M sizes are range-checked before the k/m/g suffix is applied, so an overflowing size is refused instead of wrapping. Design, configuration, deployment and test procedures: mem/README.hg_malloc.md.
1 parent 6832fe4 commit e0aa98a

75 files changed

Lines changed: 14438 additions & 47 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎.github/workflows/unittests.yml‎

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,12 +147,35 @@ jobs:
147147
MAKE_TGT: 'test'
148148
run: script -e unit_tests.log -c 'sh -x scripts/build/do_build.sh DEFS_EXTRA_OPTS="-DUNIT_TESTS -fPIE -fPIC"'
149149

150+
# the same tests and the allocator suites with HG_MALLOC; the grep fails
151+
# the step if HG_MALLOC was not actually the allocator under test (not
152+
# anchored: other processes' log lines can share a line with the TAP one)
153+
- name: Run tests with HG_MALLOC
154+
env:
155+
MAKE_TGT: 'test'
156+
UT_ALLOC: 'HG_MALLOC'
157+
UT_MEM: '-m 64:1024 -M 16:256'
158+
run: |
159+
script -e unit_tests_hg.log -c 'sh -x scripts/build/do_build.sh DEFS_EXTRA_OPTS="-DUNIT_TESTS -fPIE -fPIC"'
160+
grep -E 'ok [0-9]+ - HG_MALLOC serves pkg and shm' unit_tests_hg.log | grep -q -v 'not ok'
161+
162+
- name: Run tests with HG_MALLOC_DBG
163+
env:
164+
MAKE_TGT: 'test'
165+
UT_ALLOC: 'HG_MALLOC_DBG'
166+
UT_MEM: '-m 64:1024 -M 16:256'
167+
run: |
168+
script -e unit_tests_hg_dbg.log -c 'sh -x scripts/build/do_build.sh DEFS_EXTRA_OPTS="-DUNIT_TESTS -fPIE -fPIC"'
169+
grep -E 'ok [0-9]+ - HG_MALLOC serves pkg and shm' unit_tests_hg_dbg.log | grep -q -v 'not ok'
170+
150171
- name: Collect test logs
151172
uses: actions/upload-artifact@v7
152173
with:
153174
name: unit_tests-logs_${{ matrix.os }}_${{ matrix.compiler }}
154175
path: |
155176
unit_tests.log
177+
unit_tests_hg.log
178+
unit_tests_hg_dbg.log
156179
157180
all_done:
158181
needs: build_and_test

‎Makefile.conf.template‎

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
#uuid= UUID generator | uuid-dev
7777

7878
# Modules omitted from the default build, generally due to external dependencies.
79-
exclude_modules?= aaa_diameter aaa_radius auth_jwt auth_web3 b2b_logic_xml cachedb_cassandra cachedb_couchbase cachedb_dynamodb cachedb_memcached cachedb_mongodb cachedb_redis carrierroute cgrates compression cpl_c db_berkeley db_http db_mysql db_oracle db_perlvdb db_postgres db_sqlite db_unixodbc dialplan emergency event_rabbitmq event_kafka event_sqs h350 httpd http2d identity jabber json launch_darkly ldap lua mi_xmlrpc mmgeoip opentelemetry osp perl pi_http presence presence_dialoginfo presence_mwi presence_reginfo presence_xml presence_dfks proto_ipsec proto_sctp proto_tls proto_wss pua pua_bla pua_dialoginfo pua_mi pua_reginfo pua_usrloc pua_xmpp python regex rabbitmq_consumer rest_client rls rtp.io siprec sngtc snmpstats stir_shaken tls_mgm tls_openssl tls_wolfssl uuid xcap xcap_client xml xmpp
79+
exclude_modules?= aaa_diameter aaa_radius auth_jwt auth_web3 b2b_logic_xml cachedb_cassandra cachedb_couchbase cachedb_dynamodb cachedb_memcached cachedb_mongodb cachedb_redis carrierroute cgrates compression cpl_c db_berkeley db_http db_mysql db_oracle db_perlvdb db_postgres db_sqlite db_unixodbc dialplan emergency event_rabbitmq event_kafka event_sqs h350 hgstress httpd http2d identity jabber json launch_darkly ldap lua mi_xmlrpc mmgeoip opentelemetry osp perl pi_http presence presence_dialoginfo presence_mwi presence_reginfo presence_xml presence_dfks proto_ipsec proto_sctp proto_tls proto_wss pua pua_bla pua_dialoginfo pua_mi pua_reginfo pua_usrloc pua_xmpp python regex rabbitmq_consumer rest_client rls rtp.io siprec sngtc snmpstats stir_shaken tls_mgm tls_openssl tls_wolfssl uuid xcap xcap_client xml xmpp
8080

8181
# Modules forced into the build, even when also listed in exclude_modules.
8282
include_modules?=
@@ -97,6 +97,12 @@ DEFS+= -DQ_MALLOC #Quality assurance memory allocator with runtime safety checks
9797
DEFS+= -DHP_MALLOC #High performance allocator with fine-grained locking
9898
DEFS+= -DDBG_MALLOC #Include additional, debug-enabled allocator flavors
9999
DEFS+= -DF_PARALLEL_MALLOC #Fast memory allocator with paralel buckets
100+
DEFS+= -DHG_MALLOC #Slab allocator with a lock-free fast path and elastic arenas
101+
# HG_MALLOC: select with -a HG_MALLOC. -m/-M accept INIT:CAP, e.g. -m 128:1024:
102+
# start at 128 MB, grow on demand up to 1 GB, give memory back when idle.
103+
# Uses huge pages when the host has them (hugetlb pool or THP), else 4 KB
104+
# pages. The committed arena is mlock()ed: run with LimitMEMLOCK=infinity.
105+
# See mem/README.hg_malloc.md
100106
#DEFS+= -DQM_DBG_MALLOC_HIST=3 #Size of debug history for Q_MALLOC (default is 1)
101107
#DEFS+= -DNO_DEBUG #Compile out all debug messages
102108
#DEFS+= -DNO_LOG #Compile out all logging

‎Makefile.defs‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,9 @@ MKTAGS=ctags -R .
558558
# decently fast allocator with extra sanity checks + safety buffers
559559
# -DHP_MALLOC
560560
# high performance allocator optimized for shared memory multiprocessing
561+
# -DHG_MALLOC
562+
# slab allocator with a lock-free fast path and elastic arenas
563+
# (-m INIT:CAP), on huge pages when the host provides them
561564
# -DDBG_MALLOC
562565
# will cause each of the enabled allocators to also include a "debugging"
563566
# flavor of itself; by running a debugging version of an allocator, you

‎Makefile.test‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,11 @@ endif
66

77
.PHONY: test unit_tests system_tests
88

9+
# allocator and memory sizes the unit tests run with, e.g.
10+
# make test UT_ALLOC=HG_MALLOC UT_MEM="-m 64:1024 -M 16:256"
11+
UT_ALLOC ?= HP_MALLOC
12+
UT_MEM ?=
13+
914
ifneq (,$(findstring UNIT_TESTS,$(DEFS)))
1015
include Makefile.openssl
1116
misclibs=lib/digest_auth/libdigest_auth.a
@@ -24,7 +29,7 @@ endif
2429

2530
unit_tests: ensure_test_defs $(NAME)
2631
-@echo " ============= Start Unit Tests ============="
27-
./$(NAME) -dd -T $(module) -w . -a HP_MALLOC
32+
./$(NAME) -dd -T $(module) -w . -a $(UT_ALLOC) $(UT_MEM)
2833
-@echo " ================================================"
2934
-@echo " ======== Passed All Tests! ᕦ(ò_óˇ)ᕤ ========"
3035
-@echo " ================================================"

‎cfg.lex‎

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -291,6 +291,18 @@ DB_DEFAULT_URL "db_default_url"
291291
DB_MAX_ASYNC_CONNECTIONS "db_max_async_connections"
292292
DISABLE_503_TRANSLATION "disable_503_translation"
293293
AUTO_SCALING_PROFILE "auto_scaling_profile"
294+
SHM_AUTO_SCALING_PROFILE "shm_auto_scaling_profile"
295+
PKG_AUTO_SCALING_PROFILE "pkg_auto_scaling_profile"
296+
HG_RAM_FLOOR_MB "hg_ram_floor_mb"
297+
HG_AUTOSCALE_DRY_RUN "hg_autoscale_dry_run"
298+
SHM_GROW_GRANULE "shm_grow_granule"
299+
PKG_GROW_GRANULE "pkg_grow_granule"
300+
HG_LOCK_STALL_US "hg_lock_stall_us"
301+
HG_GROW_AHEAD "hg_grow_ahead"
302+
HG_INTERIOR_RELEASE "hg_interior_release"
303+
HG_SCALING_CYCLE "hg_scaling_cycle"
304+
HG_SHRINK_STEP "hg_shrink_step"
305+
HG_MEM_CHECK "hg_mem_check"
294306
AUTO_SCALING_CYCLE "auto_scaling_cycle"
295307
TIMER_WORKERS "timer_workers"
296308

@@ -546,6 +558,30 @@ SPACE [ ]
546558
return DISABLE_503_TRANSLATION; }
547559
<INITIAL>{AUTO_SCALING_PROFILE} { count(); yylval.strval=yytext;
548560
return AUTO_SCALING_PROFILE; }
561+
<INITIAL>{SHM_AUTO_SCALING_PROFILE} { count(); yylval.strval=yytext;
562+
return SHM_AUTO_SCALING_PROFILE; }
563+
<INITIAL>{PKG_AUTO_SCALING_PROFILE} { count(); yylval.strval=yytext;
564+
return PKG_AUTO_SCALING_PROFILE; }
565+
<INITIAL>{HG_RAM_FLOOR_MB} { count(); yylval.strval=yytext;
566+
return HG_RAM_FLOOR_MB; }
567+
<INITIAL>{HG_AUTOSCALE_DRY_RUN} { count(); yylval.strval=yytext;
568+
return HG_AUTOSCALE_DRY_RUN; }
569+
<INITIAL>{SHM_GROW_GRANULE} { count(); yylval.strval=yytext;
570+
return SHM_GROW_GRANULE; }
571+
<INITIAL>{PKG_GROW_GRANULE} { count(); yylval.strval=yytext;
572+
return PKG_GROW_GRANULE; }
573+
<INITIAL>{HG_LOCK_STALL_US} { count(); yylval.strval=yytext;
574+
return HG_LOCK_STALL_US; }
575+
<INITIAL>{HG_GROW_AHEAD} { count(); yylval.strval=yytext;
576+
return HG_GROW_AHEAD; }
577+
<INITIAL>{HG_INTERIOR_RELEASE} { count(); yylval.strval=yytext;
578+
return HG_INTERIOR_RELEASE; }
579+
<INITIAL>{HG_SCALING_CYCLE} { count(); yylval.strval=yytext;
580+
return HG_SCALING_CYCLE; }
581+
<INITIAL>{HG_SHRINK_STEP} { count(); yylval.strval=yytext;
582+
return HG_SHRINK_STEP; }
583+
<INITIAL>{HG_MEM_CHECK} { count(); yylval.strval=yytext;
584+
return HG_MEM_CHECK; }
549585
<INITIAL>{AUTO_SCALING_CYCLE} { count(); yylval.strval=yytext;
550586
return AUTO_SCALING_CYCLE; }
551587
<INITIAL>{TIMER_WORKERS} { count(); yylval.strval=yytext;

‎cfg.y‎

Lines changed: 161 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@
101101
#include "name_alias.h"
102102
#include "ut.h"
103103
#include "pt_scaling.h"
104+
#include <limits.h>
104105
#include "dset.h"
105106
#include "pvar.h"
106107
#include "blacklists.h"
@@ -197,6 +198,56 @@ union route_name_var {
197198
void *data;
198199
} rn_tmp;
199200

201+
/* A profile size number with an optional k/m/g suffix. A suffix-less
202+
* number passes through POSITIVE, keeping the profile's legacy unit
203+
* (process count for the worker scaler, MB for the memory arenas); a
204+
* suffixed number is normalized to KB and carried NEGATED, so the two
205+
* kinds survive yacc's plain-int value stack without a union member the
206+
* lexer's cfg.tab.h could not see the type of. scale_suffix_kb() encodes,
207+
* create_scaling_profile_units() decodes. */
208+
static long scale_suffix_kb(long num, const char *suf)
209+
{
210+
if (!suf || !suf[0] || suf[1] || num <= 0)
211+
return 0;
212+
switch (suf[0]) {
213+
case 'k': case 'K': return -num;
214+
case 'm': case 'M':
215+
return num > LONG_MAX / 1024 ? 0 : -(num * 1024);
216+
case 'g': case 'G':
217+
return num > LONG_MAX / (1024 * 1024) ? 0 :
218+
-(num * 1024 * 1024);
219+
}
220+
return 0;
221+
}
222+
223+
/* wraps create_auto_scaling_profile(): when either size carries a suffix
224+
* (arrives negated, in KB), normalize BOTH to KB (a bare number is then
225+
* read as MB) and flag the profile, so hg_autoscale_apply() knows the
226+
* unit. Suffix-less profiles take the untouched legacy path - the worker
227+
* scaler never sees a change. */
228+
static int create_scaling_profile_units(char *name,
229+
long up, int u_pct, int u_need, int u_win,
230+
long down, int d_pct, int d_cyc, int d_delay)
231+
{
232+
struct scaling_profile *p;
233+
int kb = up < 0 || down < 0;
234+
235+
if (kb) {
236+
up = up < 0 ? -up : up * 1024;
237+
down = down < 0 ? -down : down * 1024;
238+
}
239+
if (create_auto_scaling_profile(name, up, u_pct, u_need, u_win,
240+
down, d_pct, d_cyc, d_delay) < 0)
241+
return -1;
242+
if (kb) {
243+
p = get_scaling_profile(name);
244+
if (!p)
245+
return -1;
246+
p->mem_kb_units = 1;
247+
}
248+
return 0;
249+
}
250+
200251
#ifndef SHM_EXTRA_STATS
201252
struct multi_str{
202253
char *s;
@@ -408,6 +459,18 @@ extern int cfg_parse_only_routes;
408459
%token ASYNC_TOKEN
409460
%token LAUNCH_TOKEN
410461
%token AUTO_SCALING_PROFILE
462+
%token SHM_AUTO_SCALING_PROFILE
463+
%token PKG_AUTO_SCALING_PROFILE
464+
%token HG_RAM_FLOOR_MB
465+
%token HG_AUTOSCALE_DRY_RUN
466+
%token SHM_GROW_GRANULE
467+
%token PKG_GROW_GRANULE
468+
%token HG_LOCK_STALL_US
469+
%token HG_GROW_AHEAD
470+
%token HG_INTERIOR_RELEASE
471+
%token HG_SCALING_CYCLE
472+
%token HG_SHRINK_STEP
473+
%token HG_MEM_CHECK
411474
%token AUTO_SCALING_CYCLE
412475
%token TIMER_WORKERS
413476

@@ -505,6 +568,7 @@ extern int cfg_parse_only_routes;
505568
%type <sockid> listen_id_def
506569
%type <sockid> phostport phostportrange
507570
%type <bondlst> socket_bond_elems
571+
%type <intval> scale_size
508572
%type <intval> proto port any_proto
509573
%type <strval> host_sep
510574
%type <intval> equalop compop matchop strop intop
@@ -925,32 +989,40 @@ mpath_def_list: mpath_def_list COLON STRING {IFOR(); add_mpath($3);}
925989
| STRING { IFOR(); add_mpath($1);}
926990
;
927991

992+
scale_size: NUMBER { $$ = $1; }
993+
| NUMBER ID {
994+
$$ = scale_suffix_kb($1, $2);
995+
if ($$ == 0)
996+
yyerror("bad size suffix - use k, m or g");
997+
}
998+
;
999+
9281000
auto_scale_profile_def:
929-
ID SCALE_UP_TO NUMBER ON NUMBER MODULO FOR
1001+
ID SCALE_UP_TO scale_size ON NUMBER MODULO FOR
9301002
NUMBER CYCLES_WITHIN NUMBER
931-
SCALE_DOWN_TO NUMBER ON NUMBER MODULO FOR
1003+
SCALE_DOWN_TO scale_size ON NUMBER MODULO FOR
9321004
NUMBER CYCLES { IFOR();
933-
if (create_auto_scaling_profile($1,$3,$5,$8,$10,
1005+
if (create_scaling_profile_units($1,$3,$5,$8,$10,
9341006
$12, $14, $17,10*$17)<0)
9351007
yyerror("failed to create auto scaling profile");
9361008
}
937-
| ID SCALE_UP_TO NUMBER ON NUMBER MODULO FOR
1009+
| ID SCALE_UP_TO scale_size ON NUMBER MODULO FOR
9381010
NUMBER CYCLES
939-
SCALE_DOWN_TO NUMBER ON NUMBER MODULO FOR
1011+
SCALE_DOWN_TO scale_size ON NUMBER MODULO FOR
9401012
NUMBER CYCLES { IFOR();
941-
if (create_auto_scaling_profile($1,$3,$5,$8,$8,
1013+
if (create_scaling_profile_units($1,$3,$5,$8,$8,
9421014
$11, $13, $16, 10*$16)<0)
9431015
yyerror("failed to create auto scaling profile");
9441016
}
945-
| ID SCALE_UP_TO NUMBER ON NUMBER MODULO FOR
1017+
| ID SCALE_UP_TO scale_size ON NUMBER MODULO FOR
9461018
NUMBER CYCLES_WITHIN NUMBER { IFOR();
947-
if (create_auto_scaling_profile($1,$3,$5,$8,$10,
1019+
if (create_scaling_profile_units($1,$3,$5,$8,$10,
9481020
0, 0, 0, 0)<0)
9491021
yyerror("failed to create auto scaling profile");
9501022
}
951-
| ID SCALE_UP_TO NUMBER ON NUMBER MODULO FOR
1023+
| ID SCALE_UP_TO scale_size ON NUMBER MODULO FOR
9521024
NUMBER CYCLES { IFOR();
953-
if (create_auto_scaling_profile($1,$3,$5,$8,$8,
1025+
if (create_scaling_profile_units($1,$3,$5,$8,$8,
9541026
0, 0, 0, 0)<0)
9551027
yyerror("failed to create auto scaling profile");
9561028
}
@@ -1649,6 +1721,85 @@ assign_stm: LOGLEVEL EQUAL snumber { IFOR();
16491721
| AUTO_SCALING_PROFILE EQUAL error {
16501722
yyerror("bad auto-scaling profile definition");
16511723
}
1724+
| SHM_AUTO_SCALING_PROFILE EQUAL ID { IFOR();
1725+
hg_shm_profile_name=$3; }
1726+
| SHM_AUTO_SCALING_PROFILE EQUAL error {
1727+
yyerror("profile name expected");
1728+
}
1729+
| PKG_AUTO_SCALING_PROFILE EQUAL ID { IFOR();
1730+
hg_pkg_profile_name=$3; }
1731+
| PKG_AUTO_SCALING_PROFILE EQUAL error {
1732+
yyerror("profile name expected");
1733+
}
1734+
| HG_RAM_FLOOR_MB EQUAL NUMBER { IFOR();
1735+
hg_ram_floor_mb=$3; }
1736+
| HG_RAM_FLOOR_MB EQUAL error {
1737+
yyerror("integer value expected");
1738+
}
1739+
| HG_AUTOSCALE_DRY_RUN EQUAL NUMBER { IFOR();
1740+
hg_autoscale_dry_run=$3; }
1741+
| HG_AUTOSCALE_DRY_RUN EQUAL error {
1742+
yyerror("integer value expected");
1743+
}
1744+
| SHM_GROW_GRANULE EQUAL scale_size { IFOR();
1745+
/* scale_size: positive = MB, negated = KB */
1746+
hg_shm_grow_granule = $3 < 0 ?
1747+
(unsigned long)(-$3) << 10 :
1748+
(unsigned long)$3 << 20;
1749+
}
1750+
| SHM_GROW_GRANULE EQUAL error {
1751+
yyerror("size expected (number, optional k/m/g)");
1752+
}
1753+
| PKG_GROW_GRANULE EQUAL scale_size { IFOR();
1754+
hg_pkg_grow_granule = $3 < 0 ?
1755+
(unsigned long)(-$3) << 10 :
1756+
(unsigned long)$3 << 20;
1757+
}
1758+
| PKG_GROW_GRANULE EQUAL error {
1759+
yyerror("size expected (number, optional k/m/g)");
1760+
}
1761+
| HG_LOCK_STALL_US EQUAL NUMBER { IFOR();
1762+
hg_lock_stall_us=$3; }
1763+
| HG_LOCK_STALL_US EQUAL error {
1764+
yyerror("integer value expected");
1765+
}
1766+
| HG_GROW_AHEAD EQUAL NUMBER { IFOR();
1767+
hg_grow_ahead=$3; }
1768+
| HG_GROW_AHEAD EQUAL error {
1769+
yyerror("integer value expected");
1770+
}
1771+
| HG_INTERIOR_RELEASE EQUAL NUMBER { IFOR();
1772+
hg_interior_release=$3; }
1773+
| HG_INTERIOR_RELEASE EQUAL error {
1774+
yyerror("integer value expected");
1775+
}
1776+
| HG_SCALING_CYCLE EQUAL NUMBER { IFOR();
1777+
if ($3 < 1) {
1778+
yyerror("hg_scaling_cycle must be at least 1 second");
1779+
YYABORT;
1780+
}
1781+
hg_scaling_cycle=$3; }
1782+
| HG_SCALING_CYCLE EQUAL error {
1783+
yyerror("integer value expected");
1784+
}
1785+
| HG_SHRINK_STEP EQUAL scale_size { IFOR();
1786+
/* scale_size: positive = MB, negated = KB */
1787+
hg_shrink_step = $3 < 0 ?
1788+
(unsigned long)(-$3) << 10 :
1789+
(unsigned long)$3 << 20;
1790+
}
1791+
| HG_SHRINK_STEP EQUAL error {
1792+
yyerror("size expected (number, optional k/m/g)");
1793+
}
1794+
| HG_MEM_CHECK EQUAL NUMBER { IFOR();
1795+
if ($3 < 0 || $3 > 2) {
1796+
yyerror("hg_mem_check must be 0, 1 or 2");
1797+
YYABORT;
1798+
}
1799+
hg_mem_check=$3; }
1800+
| HG_MEM_CHECK EQUAL error {
1801+
yyerror("integer value expected");
1802+
}
16521803
| AUTO_SCALING_CYCLE EQUAL NUMBER { IFOR();
16531804
auto_scaling_cycle=$3; }
16541805
| AUTO_SCALING_CYCLE EQUAL error {

0 commit comments

Comments
 (0)