pg_query 4.2.1 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -0
- data/README.md +6 -8
- data/Rakefile +5 -6
- data/ext/pg_query/extconf.rb +14 -4
- data/ext/pg_query/include/pg_query.h +27 -3
- data/ext/pg_query/include/pg_query_enum_defs.c +311 -149
- data/ext/pg_query/include/pg_query_fingerprint_conds.c +545 -489
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +5092 -4432
- data/ext/pg_query/include/pg_query_outfuncs_conds.c +385 -343
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +1294 -1161
- data/ext/pg_query/include/pg_query_readfuncs_conds.c +137 -123
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +1657 -1496
- data/ext/pg_query/include/{access → postgres/access}/amapi.h +3 -1
- data/ext/pg_query/include/{access → postgres/access}/attmap.h +5 -3
- data/ext/pg_query/include/{access → postgres/access}/attnum.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/clog.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/commit_ts.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/detoast.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/genam.h +7 -5
- data/ext/pg_query/include/{access → postgres/access}/gin.h +16 -3
- data/ext/pg_query/include/{access → postgres/access}/htup.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/htup_details.h +6 -2
- data/ext/pg_query/include/{access → postgres/access}/itup.h +61 -58
- data/ext/pg_query/include/{access → postgres/access}/parallel.h +2 -2
- data/ext/pg_query/include/{access → postgres/access}/printtup.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/relation.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/relscan.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/rmgrlist.h +2 -2
- data/ext/pg_query/include/{access → postgres/access}/sdir.h +12 -3
- data/ext/pg_query/include/{access → postgres/access}/skey.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/stratnum.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/sysattr.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/table.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/tableam.h +68 -45
- data/ext/pg_query/include/{access → postgres/access}/toast_compression.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/transam.h +1 -1
- data/ext/pg_query/include/postgres/access/tsmapi.h +82 -0
- data/ext/pg_query/include/{access → postgres/access}/tupconvert.h +5 -2
- data/ext/pg_query/include/{access → postgres/access}/tupdesc.h +2 -2
- data/ext/pg_query/include/{access → postgres/access}/tupmacs.h +58 -98
- data/ext/pg_query/include/{access → postgres/access}/twophase.h +2 -2
- data/ext/pg_query/include/{access → postgres/access}/xact.h +25 -18
- data/ext/pg_query/include/{access → postgres/access}/xlog.h +15 -16
- data/ext/pg_query/include/{access → postgres/access}/xlog_internal.h +100 -62
- data/ext/pg_query/include/postgres/access/xlogbackup.h +41 -0
- data/ext/pg_query/include/{access → postgres/access}/xlogdefs.h +6 -25
- data/ext/pg_query/include/{access → postgres/access}/xlogprefetcher.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/xlogreader.h +7 -6
- data/ext/pg_query/include/{access → postgres/access}/xlogrecord.h +17 -5
- data/ext/pg_query/include/{access → postgres/access}/xlogrecovery.h +4 -3
- data/ext/pg_query/include/postgres/archive/archive_module.h +59 -0
- data/ext/pg_query/include/{c.h → postgres/c.h} +144 -156
- data/ext/pg_query/include/{catalog → postgres/catalog}/catalog.h +4 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/catversion.h +6 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/dependency.h +5 -4
- data/ext/pg_query/include/{catalog → postgres/catalog}/genbki.h +7 -6
- data/ext/pg_query/include/{catalog → postgres/catalog}/index.h +4 -4
- data/ext/pg_query/include/{catalog → postgres/catalog}/indexing.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/namespace.h +2 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/objectaccess.h +10 -8
- data/ext/pg_query/include/{catalog → postgres/catalog}/objectaddress.h +3 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute.h +19 -17
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute_d.h +19 -19
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation_d.h +4 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint.h +2 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_control.h +9 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion.h +2 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion_d.h +1 -1
- data/ext/pg_query/include/postgres/catalog/pg_database.h +124 -0
- data/ext/pg_query/include/postgres/catalog/pg_database_d.h +52 -0
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily.h +3 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily_d.h +4 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication.h +2 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type_d.h +1 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/storage.h +6 -6
- data/ext/pg_query/include/{commands → postgres/commands}/async.h +1 -1
- data/ext/pg_query/include/{commands → postgres/commands}/dbcommands.h +2 -1
- data/ext/pg_query/include/{commands → postgres/commands}/defrem.h +2 -1
- data/ext/pg_query/include/{commands → postgres/commands}/event_trigger.h +1 -1
- data/ext/pg_query/include/{commands → postgres/commands}/explain.h +3 -1
- data/ext/pg_query/include/{commands → postgres/commands}/prepare.h +1 -1
- data/ext/pg_query/include/{commands → postgres/commands}/tablespace.h +4 -4
- data/ext/pg_query/include/{commands → postgres/commands}/trigger.h +15 -14
- data/ext/pg_query/include/{commands → postgres/commands}/user.h +9 -3
- data/ext/pg_query/include/{commands → postgres/commands}/vacuum.h +60 -14
- data/ext/pg_query/include/postgres/common/cryptohash.h +39 -0
- data/ext/pg_query/include/{common → postgres/common}/file_perm.h +1 -1
- data/ext/pg_query/include/{common → postgres/common}/hashfn.h +1 -1
- data/ext/pg_query/include/postgres/common/int.h +437 -0
- data/ext/pg_query/include/{common → postgres/common}/keywords.h +1 -1
- data/ext/pg_query/include/{common → postgres/common}/kwlookup.h +2 -2
- data/ext/pg_query/include/{common → postgres/common}/pg_prng.h +3 -2
- data/ext/pg_query/include/{common → postgres/common}/relpath.h +20 -13
- data/ext/pg_query/include/postgres/common/scram-common.h +70 -0
- data/ext/pg_query/include/postgres/common/sha2.h +32 -0
- data/ext/pg_query/include/{common → postgres/common}/string.h +5 -3
- data/ext/pg_query/include/{common → postgres/common}/unicode_east_asian_fw_table.h +10 -10
- data/ext/pg_query/include/{common/unicode_combining_table.h → postgres/common/unicode_nonspacing_table.h} +31 -13
- data/ext/pg_query/include/postgres/copyfuncs.funcs.c +5013 -0
- data/ext/pg_query/include/postgres/copyfuncs.switch.c +938 -0
- data/ext/pg_query/include/{datatype → postgres/datatype}/timestamp.h +11 -4
- data/ext/pg_query/include/postgres/equalfuncs.funcs.c +3097 -0
- data/ext/pg_query/include/postgres/equalfuncs.switch.c +785 -0
- data/ext/pg_query/include/{executor → postgres/executor}/execdesc.h +1 -1
- data/ext/pg_query/include/{executor → postgres/executor}/executor.h +34 -17
- data/ext/pg_query/include/{executor → postgres/executor}/functions.h +1 -1
- data/ext/pg_query/include/{executor → postgres/executor}/instrument.h +1 -1
- data/ext/pg_query/include/{executor → postgres/executor}/spi.h +2 -2
- data/ext/pg_query/include/{executor → postgres/executor}/tablefunc.h +1 -1
- data/ext/pg_query/include/{executor → postgres/executor}/tuptable.h +18 -11
- data/ext/pg_query/include/{fmgr.h → postgres/fmgr.h} +21 -2
- data/ext/pg_query/include/postgres/foreign/fdwapi.h +294 -0
- data/ext/pg_query/include/{funcapi.h → postgres/funcapi.h} +12 -12
- data/ext/pg_query/include/postgres/gram.h +1127 -0
- data/ext/pg_query/include/{parser → postgres}/gramparse.h +4 -4
- data/ext/pg_query/include/{jit → postgres/jit}/jit.h +2 -2
- data/ext/pg_query/include/postgres/kwlist_d.h +1119 -0
- data/ext/pg_query/include/{lib → postgres/lib}/dshash.h +4 -1
- data/ext/pg_query/include/{lib → postgres/lib}/ilist.h +435 -22
- data/ext/pg_query/include/{lib → postgres/lib}/pairingheap.h +1 -1
- data/ext/pg_query/include/{lib → postgres/lib}/simplehash.h +9 -9
- data/ext/pg_query/include/{lib → postgres/lib}/sort_template.h +1 -1
- data/ext/pg_query/include/{lib → postgres/lib}/stringinfo.h +3 -3
- data/ext/pg_query/include/{libpq → postgres/libpq}/auth.h +8 -2
- data/ext/pg_query/include/{libpq → postgres/libpq}/crypt.h +1 -1
- data/ext/pg_query/include/{libpq → postgres/libpq}/hba.h +24 -17
- data/ext/pg_query/include/{libpq → postgres/libpq}/libpq-be.h +36 -25
- data/ext/pg_query/include/{libpq → postgres/libpq}/libpq.h +1 -1
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqcomm.h +10 -41
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqformat.h +2 -2
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqsignal.h +22 -10
- data/ext/pg_query/include/postgres/libpq/sasl.h +136 -0
- data/ext/pg_query/include/postgres/libpq/scram.h +37 -0
- data/ext/pg_query/include/{mb → postgres/mb}/pg_wchar.h +35 -18
- data/ext/pg_query/include/{mb → postgres/mb}/stringinfo_mb.h +1 -1
- data/ext/pg_query/include/{miscadmin.h → postgres/miscadmin.h} +27 -15
- data/ext/pg_query/include/{nodes → postgres/nodes}/bitmapset.h +11 -7
- data/ext/pg_query/include/{nodes → postgres/nodes}/execnodes.h +83 -30
- data/ext/pg_query/include/{nodes → postgres/nodes}/extensible.h +5 -3
- data/ext/pg_query/include/{nodes → postgres/nodes}/lockoptions.h +1 -1
- data/ext/pg_query/include/{nodes → postgres/nodes}/makefuncs.h +14 -2
- data/ext/pg_query/include/{nodes → postgres/nodes}/memnodes.h +7 -4
- data/ext/pg_query/include/postgres/nodes/miscnodes.h +56 -0
- data/ext/pg_query/include/{nodes → postgres/nodes}/nodeFuncs.h +89 -29
- data/ext/pg_query/include/{nodes → postgres/nodes}/nodes.h +96 -511
- data/ext/pg_query/include/postgres/nodes/nodetags.h +471 -0
- data/ext/pg_query/include/{nodes → postgres/nodes}/params.h +3 -3
- data/ext/pg_query/include/{nodes → postgres/nodes}/parsenodes.h +377 -139
- data/ext/pg_query/include/{nodes → postgres/nodes}/pathnodes.h +1090 -440
- data/ext/pg_query/include/{nodes → postgres/nodes}/pg_list.h +30 -7
- data/ext/pg_query/include/{nodes → postgres/nodes}/plannodes.h +367 -124
- data/ext/pg_query/include/{nodes → postgres/nodes}/primnodes.h +670 -222
- data/ext/pg_query/include/{nodes → postgres/nodes}/print.h +1 -1
- data/ext/pg_query/include/{utils → postgres/nodes}/queryjumble.h +5 -7
- data/ext/pg_query/include/postgres/nodes/replnodes.h +111 -0
- data/ext/pg_query/include/postgres/nodes/supportnodes.h +346 -0
- data/ext/pg_query/include/{nodes → postgres/nodes}/tidbitmap.h +1 -1
- data/ext/pg_query/include/{nodes → postgres/nodes}/value.h +12 -2
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/cost.h +6 -4
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo.h +1 -1
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo_gene.h +1 -1
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/optimizer.h +8 -8
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/paths.h +16 -7
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/planmain.h +3 -6
- data/ext/pg_query/include/{parser → postgres/parser}/analyze.h +4 -3
- data/ext/pg_query/include/{parser → postgres/parser}/kwlist.h +12 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_agg.h +4 -2
- data/ext/pg_query/include/{parser → postgres/parser}/parse_coerce.h +3 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_expr.h +1 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_func.h +1 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_node.h +22 -4
- data/ext/pg_query/include/{parser → postgres/parser}/parse_oper.h +3 -3
- data/ext/pg_query/include/{parser → postgres/parser}/parse_relation.h +8 -3
- data/ext/pg_query/include/{parser → postgres/parser}/parse_type.h +4 -3
- data/ext/pg_query/include/{parser → postgres/parser}/parser.h +4 -4
- data/ext/pg_query/include/{parser → postgres/parser}/parsetree.h +1 -1
- data/ext/pg_query/include/{parser → postgres/parser}/scanner.h +2 -2
- data/ext/pg_query/include/{parser → postgres/parser}/scansup.h +1 -1
- data/ext/pg_query/include/{partitioning → postgres/partitioning}/partdefs.h +1 -1
- data/ext/pg_query/include/{pg_config.h → postgres/pg_config.h} +158 -218
- data/ext/pg_query/include/{pg_config_manual.h → postgres/pg_config_manual.h} +8 -46
- data/ext/pg_query/include/postgres/pg_config_os.h +8 -0
- data/ext/pg_query/include/{pg_getopt.h → postgres/pg_getopt.h} +1 -1
- data/ext/pg_query/include/{pg_trace.h → postgres/pg_trace.h} +1 -1
- data/ext/pg_query/include/{pgstat.h → postgres/pgstat.h} +173 -94
- data/ext/pg_query/include/{pgtime.h → postgres/pgtime.h} +3 -3
- data/ext/pg_query/include/{pl_gram.h → postgres/pl_gram.h} +66 -64
- data/ext/pg_query/include/{pl_reserved_kwlist.h → postgres/pl_reserved_kwlist.h} +1 -1
- data/ext/pg_query/include/{pl_reserved_kwlist_d.h → postgres/pl_reserved_kwlist_d.h} +1 -1
- data/ext/pg_query/include/{pl_unreserved_kwlist.h → postgres/pl_unreserved_kwlist.h} +2 -1
- data/ext/pg_query/include/{pl_unreserved_kwlist_d.h → postgres/pl_unreserved_kwlist_d.h} +48 -46
- data/ext/pg_query/include/{plpgsql.h → postgres/plpgsql.h} +28 -33
- data/ext/pg_query/include/{port → postgres/port}/atomics/arch-arm.h +3 -3
- data/ext/pg_query/include/postgres/port/atomics/arch-hppa.h +17 -0
- data/ext/pg_query/include/{port → postgres/port}/atomics/arch-ppc.h +21 -21
- data/ext/pg_query/include/{port → postgres/port}/atomics/arch-x86.h +2 -2
- data/ext/pg_query/include/{port → postgres/port}/atomics/fallback.h +3 -3
- data/ext/pg_query/include/{port → postgres/port}/atomics/generic-gcc.h +1 -1
- data/ext/pg_query/include/postgres/port/atomics/generic-msvc.h +101 -0
- data/ext/pg_query/include/postgres/port/atomics/generic-sunpro.h +106 -0
- data/ext/pg_query/include/{port → postgres/port}/atomics/generic.h +1 -1
- data/ext/pg_query/include/{port → postgres/port}/atomics.h +2 -7
- data/ext/pg_query/include/{port → postgres/port}/pg_bitutils.h +62 -25
- data/ext/pg_query/include/{port → postgres/port}/pg_bswap.h +1 -1
- data/ext/pg_query/include/{port → postgres/port}/pg_crc32c.h +1 -1
- data/ext/pg_query/include/postgres/port/simd.h +375 -0
- data/ext/pg_query/include/postgres/port/win32/arpa/inet.h +3 -0
- data/ext/pg_query/include/postgres/port/win32/dlfcn.h +1 -0
- data/ext/pg_query/include/postgres/port/win32/grp.h +1 -0
- data/ext/pg_query/include/postgres/port/win32/netdb.h +7 -0
- data/ext/pg_query/include/postgres/port/win32/netinet/in.h +3 -0
- data/ext/pg_query/include/postgres/port/win32/netinet/tcp.h +7 -0
- data/ext/pg_query/include/postgres/port/win32/pwd.h +3 -0
- data/ext/pg_query/include/postgres/port/win32/sys/resource.h +20 -0
- data/ext/pg_query/include/postgres/port/win32/sys/select.h +3 -0
- data/ext/pg_query/include/postgres/port/win32/sys/socket.h +26 -0
- data/ext/pg_query/include/postgres/port/win32/sys/un.h +17 -0
- data/ext/pg_query/include/postgres/port/win32/sys/wait.h +3 -0
- data/ext/pg_query/include/postgres/port/win32.h +59 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/dirent.h +34 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/sys/file.h +1 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/sys/param.h +1 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/sys/time.h +1 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/unistd.h +9 -0
- data/ext/pg_query/include/postgres/port/win32_msvc/utime.h +3 -0
- data/ext/pg_query/include/postgres/port/win32_port.h +594 -0
- data/ext/pg_query/include/{port.h → postgres/port.h} +42 -75
- data/ext/pg_query/include/postgres/portability/instr_time.h +197 -0
- data/ext/pg_query/include/postgres/postgres.h +579 -0
- data/ext/pg_query/include/{postgres_ext.h → postgres/postgres_ext.h} +0 -1
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/autovacuum.h +1 -4
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker.h +2 -2
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker_internals.h +1 -1
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgwriter.h +2 -2
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/interrupt.h +1 -1
- data/ext/pg_query/include/postgres/postmaster/pgarch.h +36 -0
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/postmaster.h +6 -3
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/startup.h +3 -1
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/syslogger.h +2 -2
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/walwriter.h +3 -1
- data/ext/pg_query/include/{regex → postgres/regex}/regex.h +9 -6
- data/ext/pg_query/include/{replication → postgres/replication}/logicallauncher.h +6 -1
- data/ext/pg_query/include/{replication → postgres/replication}/logicalproto.h +30 -10
- data/ext/pg_query/include/postgres/replication/logicalworker.h +32 -0
- data/ext/pg_query/include/{replication → postgres/replication}/origin.h +4 -4
- data/ext/pg_query/include/{replication → postgres/replication}/reorderbuffer.h +113 -45
- data/ext/pg_query/include/{replication → postgres/replication}/slot.h +25 -6
- data/ext/pg_query/include/{replication → postgres/replication}/syncrep.h +2 -8
- data/ext/pg_query/include/{replication → postgres/replication}/walreceiver.h +15 -9
- data/ext/pg_query/include/{replication → postgres/replication}/walsender.h +13 -13
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/prs2lock.h +1 -1
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteHandler.h +1 -4
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteManip.h +11 -2
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteSupport.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/backendid.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/block.h +24 -31
- data/ext/pg_query/include/{storage → postgres/storage}/buf.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/bufmgr.h +183 -87
- data/ext/pg_query/include/{storage → postgres/storage}/bufpage.h +146 -93
- data/ext/pg_query/include/{storage → postgres/storage}/condition_variable.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/dsm.h +3 -6
- data/ext/pg_query/include/{storage → postgres/storage}/dsm_impl.h +4 -1
- data/ext/pg_query/include/{storage → postgres/storage}/fd.h +24 -20
- data/ext/pg_query/include/{storage → postgres/storage}/fileset.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/ipc.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/item.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/itemid.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/itemptr.h +94 -57
- data/ext/pg_query/include/{storage → postgres/storage}/large_object.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/latch.h +9 -1
- data/ext/pg_query/include/{storage → postgres/storage}/lmgr.h +6 -1
- data/ext/pg_query/include/{storage → postgres/storage}/lock.h +21 -13
- data/ext/pg_query/include/{storage → postgres/storage}/lockdefs.h +3 -3
- data/ext/pg_query/include/{storage → postgres/storage}/lwlock.h +16 -2
- data/ext/pg_query/include/{storage → postgres/storage}/off.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/pg_sema.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/pg_shmem.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/pmsignal.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/predicate.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/proc.h +22 -17
- data/ext/pg_query/include/{storage → postgres/storage}/procarray.h +3 -2
- data/ext/pg_query/include/{storage → postgres/storage}/proclist_types.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/procsignal.h +3 -1
- data/ext/pg_query/include/postgres/storage/relfilelocator.h +99 -0
- data/ext/pg_query/include/{storage → postgres/storage}/s_lock.h +66 -309
- data/ext/pg_query/include/{storage → postgres/storage}/sharedfileset.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/shm_mq.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/shm_toc.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/shmem.h +1 -23
- data/ext/pg_query/include/{storage → postgres/storage}/sinval.h +3 -3
- data/ext/pg_query/include/{storage → postgres/storage}/sinvaladt.h +4 -2
- data/ext/pg_query/include/{storage → postgres/storage}/smgr.h +12 -10
- data/ext/pg_query/include/{storage → postgres/storage}/spin.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/standby.h +9 -8
- data/ext/pg_query/include/{storage → postgres/storage}/standbydefs.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/sync.h +3 -3
- data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtag.h +7 -2
- data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtaglist.h +1 -1
- data/ext/pg_query/include/{tcop → postgres/tcop}/deparse_utility.h +1 -1
- data/ext/pg_query/include/{tcop → postgres/tcop}/dest.h +1 -3
- data/ext/pg_query/include/{tcop → postgres/tcop}/fastpath.h +1 -1
- data/ext/pg_query/include/{tcop → postgres/tcop}/pquery.h +1 -1
- data/ext/pg_query/include/{tcop → postgres/tcop}/tcopprot.h +3 -6
- data/ext/pg_query/include/{tcop → postgres/tcop}/utility.h +1 -1
- data/ext/pg_query/include/{tsearch → postgres/tsearch}/ts_cache.h +2 -4
- data/ext/pg_query/include/{utils → postgres/utils}/acl.h +26 -81
- data/ext/pg_query/include/{utils → postgres/utils}/aclchk_internal.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/array.h +19 -1
- data/ext/pg_query/include/{utils → postgres/utils}/backend_progress.h +2 -1
- data/ext/pg_query/include/{utils → postgres/utils}/backend_status.h +24 -3
- data/ext/pg_query/include/{utils → postgres/utils}/builtins.h +15 -6
- data/ext/pg_query/include/{utils → postgres/utils}/bytea.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/catcache.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/date.h +37 -9
- data/ext/pg_query/include/{utils → postgres/utils}/datetime.h +41 -21
- data/ext/pg_query/include/{utils → postgres/utils}/datum.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/dsa.h +5 -1
- data/ext/pg_query/include/{utils → postgres/utils}/elog.h +104 -29
- data/ext/pg_query/include/{utils → postgres/utils}/expandeddatum.h +14 -3
- data/ext/pg_query/include/{utils → postgres/utils}/expandedrecord.h +14 -4
- data/ext/pg_query/include/{utils → postgres/utils}/float.h +7 -6
- data/ext/pg_query/include/{utils → postgres/utils}/fmgroids.h +54 -1
- data/ext/pg_query/include/{utils → postgres/utils}/fmgrprotos.h +45 -3
- data/ext/pg_query/include/{utils → postgres/utils}/fmgrtab.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/guc.h +59 -86
- data/ext/pg_query/include/postgres/utils/guc_hooks.h +163 -0
- data/ext/pg_query/include/{utils → postgres/utils}/guc_tables.h +49 -3
- data/ext/pg_query/include/{utils → postgres/utils}/hsearch.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/inval.h +3 -3
- data/ext/pg_query/include/postgres/utils/logtape.h +77 -0
- data/ext/pg_query/include/{utils → postgres/utils}/lsyscache.h +5 -1
- data/ext/pg_query/include/{utils → postgres/utils}/memdebug.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/memutils.h +7 -51
- data/ext/pg_query/include/postgres/utils/memutils_internal.h +136 -0
- data/ext/pg_query/include/postgres/utils/memutils_memorychunk.h +237 -0
- data/ext/pg_query/include/{utils → postgres/utils}/numeric.h +20 -5
- data/ext/pg_query/include/{utils → postgres/utils}/palloc.h +9 -2
- data/ext/pg_query/include/{utils → postgres/utils}/partcache.h +3 -2
- data/ext/pg_query/include/{utils → postgres/utils}/pg_locale.h +22 -14
- data/ext/pg_query/include/{utils → postgres/utils}/pgstat_internal.h +37 -7
- data/ext/pg_query/include/{utils → postgres/utils}/plancache.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/portal.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/probes.h +6 -6
- data/ext/pg_query/include/postgres/utils/ps_status.h +47 -0
- data/ext/pg_query/include/{utils → postgres/utils}/queryenvironment.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/regproc.h +3 -3
- data/ext/pg_query/include/{utils → postgres/utils}/rel.h +60 -43
- data/ext/pg_query/include/{utils → postgres/utils}/relcache.h +13 -8
- data/ext/pg_query/include/{utils → postgres/utils}/reltrigger.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/resowner.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/ruleutils.h +6 -1
- data/ext/pg_query/include/{utils → postgres/utils}/sharedtuplestore.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/snapmgr.h +4 -2
- data/ext/pg_query/include/{utils → postgres/utils}/snapshot.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/sortsupport.h +2 -2
- data/ext/pg_query/include/{utils → postgres/utils}/syscache.h +4 -1
- data/ext/pg_query/include/{utils → postgres/utils}/timeout.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/timestamp.h +41 -11
- data/ext/pg_query/include/{utils → postgres/utils}/tuplesort.h +189 -35
- data/ext/pg_query/include/{utils → postgres/utils}/tuplestore.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/typcache.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/varlena.h +13 -1
- data/ext/pg_query/include/{utils → postgres/utils}/wait_event.h +9 -4
- data/ext/pg_query/include/{utils → postgres/utils}/xml.h +15 -5
- data/ext/pg_query/include/{postgres.h → postgres/varatt.h} +7 -457
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +6186 -5585
- data/ext/pg_query/include/protobuf/pg_query.pb.h +112443 -91222
- data/ext/pg_query/pg_query.c +10 -1
- data/ext/pg_query/pg_query.pb-c.c +19755 -17757
- data/ext/pg_query/pg_query_deparse.c +1 -10635
- data/ext/pg_query/pg_query_fingerprint.c +12 -8
- data/ext/pg_query/pg_query_fingerprint.h +1 -1
- data/ext/pg_query/pg_query_internal.h +1 -1
- data/ext/pg_query/pg_query_json_plpgsql.c +1 -0
- data/ext/pg_query/pg_query_normalize.c +1 -1
- data/ext/pg_query/pg_query_outfuncs_json.c +6 -0
- data/ext/pg_query/pg_query_outfuncs_protobuf.c +3 -2
- data/ext/pg_query/pg_query_parse.c +47 -5
- data/ext/pg_query/pg_query_parse_plpgsql.c +7 -5
- data/ext/pg_query/pg_query_readfuncs_protobuf.c +1 -0
- data/ext/pg_query/pg_query_ruby.c +5 -0
- data/ext/pg_query/pg_query_ruby_freebsd.sym +2 -0
- data/ext/pg_query/pg_query_scan.c +1 -1
- data/ext/pg_query/pg_query_split.c +3 -3
- data/ext/pg_query/postgres_deparse.c +11067 -0
- data/ext/pg_query/postgres_deparse.h +9 -0
- data/ext/pg_query/src_backend_catalog_namespace.c +7 -2
- data/ext/pg_query/src_backend_catalog_pg_proc.c +1 -1
- data/ext/pg_query/src_backend_commands_define.c +1 -1
- data/ext/pg_query/src_backend_nodes_bitmapset.c +11 -70
- data/ext/pg_query/src_backend_nodes_copyfuncs.c +96 -6202
- data/ext/pg_query/src_backend_nodes_equalfuncs.c +95 -4068
- data/ext/pg_query/src_backend_nodes_extensible.c +6 -29
- data/ext/pg_query/src_backend_nodes_list.c +14 -2
- data/ext/pg_query/src_backend_nodes_makefuncs.c +95 -1
- data/ext/pg_query/src_backend_nodes_nodeFuncs.c +283 -132
- data/ext/pg_query/src_backend_nodes_nodes.c +38 -0
- data/ext/pg_query/src_backend_nodes_value.c +1 -1
- data/ext/pg_query/src_backend_parser_gram.c +33208 -31806
- data/ext/pg_query/src_backend_parser_parser.c +28 -2
- data/ext/pg_query/src_backend_parser_scan.c +4318 -3329
- data/ext/pg_query/src_backend_parser_scansup.c +1 -1
- data/ext/pg_query/src_backend_storage_ipc_ipc.c +1 -1
- data/ext/pg_query/src_backend_tcop_postgres.c +66 -87
- data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_datum.c +5 -7
- data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_format_type.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_numutils.c +489 -0
- data/ext/pg_query/src_backend_utils_adt_ruleutils.c +79 -5
- data/ext/pg_query/src_backend_utils_error_assert.c +4 -7
- data/ext/pg_query/src_backend_utils_error_elog.c +371 -249
- data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +33 -1
- data/ext/pg_query/src_backend_utils_init_globals.c +6 -3
- data/ext/pg_query/src_backend_utils_mb_mbutils.c +21 -67
- data/ext/pg_query/src_backend_utils_misc_guc_tables.c +492 -0
- data/ext/pg_query/src_backend_utils_mmgr_alignedalloc.c +163 -0
- data/ext/pg_query/src_backend_utils_mmgr_aset.c +449 -312
- data/ext/pg_query/src_backend_utils_mmgr_generation.c +1039 -0
- data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +398 -49
- data/ext/pg_query/src_backend_utils_mmgr_slab.c +1021 -0
- data/ext/pg_query/src_common_encnames.c +4 -1
- data/ext/pg_query/src_common_hashfn.c +1 -1
- data/ext/pg_query/src_common_keywords.c +1 -1
- data/ext/pg_query/src_common_kwlist_d.h +534 -510
- data/ext/pg_query/src_common_kwlookup.c +1 -1
- data/ext/pg_query/src_common_psprintf.c +1 -1
- data/ext/pg_query/src_common_stringinfo.c +4 -4
- data/ext/pg_query/src_common_wchar.c +9 -8
- data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +3 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +661 -694
- data/ext/pg_query/src_pl_plpgsql_src_pl_handler.c +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_reserved_kwlist_d.h +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +1 -1
- data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +48 -46
- data/ext/pg_query/src_port_pg_bitutils.c +79 -5
- data/ext/pg_query/src_port_pgstrcasecmp.c +29 -1
- data/ext/pg_query/src_port_snprintf.c +6 -10
- data/ext/pg_query/src_port_strerror.c +1 -1
- data/ext/pg_query/src_port_strlcpy.c +79 -0
- data/lib/pg_query/fingerprint.rb +2 -3
- data/lib/pg_query/node.rb +16 -11
- data/lib/pg_query/parse.rb +1 -1
- data/lib/pg_query/pg_query_pb.rb +166 -3191
- data/lib/pg_query/treewalker.rb +23 -5
- data/lib/pg_query/version.rb +1 -1
- metadata +432 -380
- data/ext/pg_query/guc-file.c +0 -0
- data/ext/pg_query/include/catalog/pg_parameter_acl.h +0 -60
- data/ext/pg_query/include/catalog/pg_parameter_acl_d.h +0 -34
- data/ext/pg_query/include/commands/variable.h +0 -38
- data/ext/pg_query/include/common/ip.h +0 -31
- data/ext/pg_query/include/getaddrinfo.h +0 -162
- data/ext/pg_query/include/kwlist_d.h +0 -1095
- data/ext/pg_query/include/parser/gram.h +0 -1101
- data/ext/pg_query/include/pg_config_os.h +0 -8
- data/ext/pg_query/include/portability/instr_time.h +0 -256
- data/ext/pg_query/include/postmaster/auxprocess.h +0 -20
- data/ext/pg_query/include/postmaster/fork_process.h +0 -17
- data/ext/pg_query/include/postmaster/pgarch.h +0 -73
- data/ext/pg_query/include/replication/logicalworker.h +0 -19
- data/ext/pg_query/include/storage/relfilenode.h +0 -99
- data/ext/pg_query/include/utils/dynahash.h +0 -20
- data/ext/pg_query/include/utils/pg_lsn.h +0 -29
- data/ext/pg_query/include/utils/pidfile.h +0 -56
- data/ext/pg_query/include/utils/ps_status.h +0 -25
- data/ext/pg_query/include/utils/rls.h +0 -50
- data/ext/pg_query/include/utils/tzparser.h +0 -39
- data/ext/pg_query/src_backend_postmaster_postmaster.c +0 -2201
- data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +0 -371
- data/ext/pg_query/src_backend_utils_hash_dynahash.c +0 -1116
- data/ext/pg_query/src_backend_utils_misc_guc.c +0 -1993
- data/ext/pg_query/src_common_pg_prng.c +0 -152
- data/ext/pg_query/src_common_string.c +0 -92
- data/ext/pg_query/src_port_pgsleep.c +0 -69
- data/ext/pg_query/src_port_strnlen.c +0 -39
- /data/ext/pg_query/include/{access → postgres/access}/rmgr.h +0 -0
- /data/ext/pg_query/include/{pg_config_ext.h → postgres/pg_config_ext.h} +0 -0
- /data/ext/pg_query/include/{plerrcodes.h → postgres/plerrcodes.h} +0 -0
- /data/ext/pg_query/include/{storage → postgres/storage}/lwlocknames.h +0 -0
- /data/ext/pg_query/include/{utils → postgres/utils}/errcodes.h +0 -0
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
/*--------------------------------------------------------------------
|
|
2
2
|
* Symbols referenced in this file:
|
|
3
|
-
* - AllocSetContextCreateInternal
|
|
4
|
-
* - context_freelists
|
|
5
|
-
* - AllocSetMethods
|
|
6
3
|
* - AllocSetAlloc
|
|
7
4
|
* - AllocSetFreeIndex
|
|
8
5
|
* - AllocSetFree
|
|
9
6
|
* - AllocSetRealloc
|
|
10
7
|
* - AllocSetReset
|
|
11
8
|
* - AllocSetDelete
|
|
9
|
+
* - context_freelists
|
|
10
|
+
* - AllocSetGetChunkContext
|
|
12
11
|
* - AllocSetGetChunkSpace
|
|
13
12
|
* - AllocSetIsEmpty
|
|
14
13
|
* - AllocSetStats
|
|
15
14
|
* - AllocSetCheck
|
|
15
|
+
* - AllocSetContextCreateInternal
|
|
16
16
|
* - AllocSetDeleteFreeList
|
|
17
17
|
*--------------------------------------------------------------------
|
|
18
18
|
*/
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
* type.
|
|
27
27
|
*
|
|
28
28
|
*
|
|
29
|
-
* Portions Copyright (c) 1996-
|
|
29
|
+
* Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
|
|
30
30
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
31
31
|
*
|
|
32
32
|
* IDENTIFICATION
|
|
@@ -68,6 +68,8 @@
|
|
|
68
68
|
#include "port/pg_bitutils.h"
|
|
69
69
|
#include "utils/memdebug.h"
|
|
70
70
|
#include "utils/memutils.h"
|
|
71
|
+
#include "utils/memutils_memorychunk.h"
|
|
72
|
+
#include "utils/memutils_internal.h"
|
|
71
73
|
|
|
72
74
|
/*--------------------
|
|
73
75
|
* Chunk freelist k holds chunks of size 1 << (k + ALLOC_MINBITS),
|
|
@@ -85,7 +87,9 @@
|
|
|
85
87
|
* CAUTION: ALLOC_MINBITS must be large enough so that
|
|
86
88
|
* 1<<ALLOC_MINBITS is at least MAXALIGN,
|
|
87
89
|
* or we may fail to align the smallest chunks adequately.
|
|
88
|
-
* 8-byte alignment is enough on all currently known machines.
|
|
90
|
+
* 8-byte alignment is enough on all currently known machines. This 8-byte
|
|
91
|
+
* minimum also allows us to store a pointer to the next freelist item within
|
|
92
|
+
* the chunk of memory itself.
|
|
89
93
|
*
|
|
90
94
|
* With the current parameters, request sizes up to 8K are treated as chunks,
|
|
91
95
|
* larger requests go into dedicated blocks. Change ALLOCSET_NUM_FREELISTS
|
|
@@ -117,10 +121,9 @@
|
|
|
117
121
|
*/
|
|
118
122
|
|
|
119
123
|
#define ALLOC_BLOCKHDRSZ MAXALIGN(sizeof(AllocBlockData))
|
|
120
|
-
#define ALLOC_CHUNKHDRSZ sizeof(
|
|
124
|
+
#define ALLOC_CHUNKHDRSZ sizeof(MemoryChunk)
|
|
121
125
|
|
|
122
126
|
typedef struct AllocBlockData *AllocBlock; /* forward reference */
|
|
123
|
-
typedef struct AllocChunkData *AllocChunk;
|
|
124
127
|
|
|
125
128
|
/*
|
|
126
129
|
* AllocPointer
|
|
@@ -128,6 +131,34 @@ typedef struct AllocChunkData *AllocChunk;
|
|
|
128
131
|
*/
|
|
129
132
|
typedef void *AllocPointer;
|
|
130
133
|
|
|
134
|
+
/*
|
|
135
|
+
* AllocFreeListLink
|
|
136
|
+
* When pfreeing memory, if we maintain a freelist for the given chunk's
|
|
137
|
+
* size then we use a AllocFreeListLink to point to the current item in
|
|
138
|
+
* the AllocSetContext's freelist and then set the given freelist element
|
|
139
|
+
* to point to the chunk being freed.
|
|
140
|
+
*/
|
|
141
|
+
typedef struct AllocFreeListLink
|
|
142
|
+
{
|
|
143
|
+
MemoryChunk *next;
|
|
144
|
+
} AllocFreeListLink;
|
|
145
|
+
|
|
146
|
+
/*
|
|
147
|
+
* Obtain a AllocFreeListLink for the given chunk. Allocation sizes are
|
|
148
|
+
* always at least sizeof(AllocFreeListLink), so we reuse the pointer's memory
|
|
149
|
+
* itself to store the freelist link.
|
|
150
|
+
*/
|
|
151
|
+
#define GetFreeListLink(chkptr) \
|
|
152
|
+
(AllocFreeListLink *) ((char *) (chkptr) + ALLOC_CHUNKHDRSZ)
|
|
153
|
+
|
|
154
|
+
/* Validate a freelist index retrieved from a chunk header */
|
|
155
|
+
#define FreeListIdxIsValid(fidx) \
|
|
156
|
+
((fidx) >= 0 && (fidx) < ALLOCSET_NUM_FREELISTS)
|
|
157
|
+
|
|
158
|
+
/* Determine the size of the chunk based on the freelist index */
|
|
159
|
+
#define GetChunkSizeFromFreeListIdx(fidx) \
|
|
160
|
+
((((Size) 1) << ALLOC_MINBITS) << (fidx))
|
|
161
|
+
|
|
131
162
|
/*
|
|
132
163
|
* AllocSetContext is our standard implementation of MemoryContext.
|
|
133
164
|
*
|
|
@@ -142,7 +173,7 @@ typedef struct AllocSetContext
|
|
|
142
173
|
MemoryContextData header; /* Standard memory-context fields */
|
|
143
174
|
/* Info about storage allocated in this context: */
|
|
144
175
|
AllocBlock blocks; /* head of list of blocks in this set */
|
|
145
|
-
|
|
176
|
+
MemoryChunk *freelist[ALLOCSET_NUM_FREELISTS]; /* free chunk lists */
|
|
146
177
|
/* Allocation parameters for this context: */
|
|
147
178
|
Size initBlockSize; /* initial block size */
|
|
148
179
|
Size maxBlockSize; /* maximum block size */
|
|
@@ -158,8 +189,8 @@ typedef AllocSetContext *AllocSet;
|
|
|
158
189
|
/*
|
|
159
190
|
* AllocBlock
|
|
160
191
|
* An AllocBlock is the unit of memory that is obtained by aset.c
|
|
161
|
-
* from malloc(). It contains one or more
|
|
162
|
-
* the units requested by palloc() and freed by pfree().
|
|
192
|
+
* from malloc(). It contains one or more MemoryChunks, which are
|
|
193
|
+
* the units requested by palloc() and freed by pfree(). MemoryChunks
|
|
163
194
|
* cannot be returned to malloc() individually, instead they are put
|
|
164
195
|
* on freelists by pfree() and re-used by the next palloc() that has
|
|
165
196
|
* a matching request size.
|
|
@@ -176,50 +207,6 @@ typedef struct AllocBlockData
|
|
|
176
207
|
char *endptr; /* end of space in this block */
|
|
177
208
|
} AllocBlockData;
|
|
178
209
|
|
|
179
|
-
/*
|
|
180
|
-
* AllocChunk
|
|
181
|
-
* The prefix of each piece of memory in an AllocBlock
|
|
182
|
-
*
|
|
183
|
-
* Note: to meet the memory context APIs, the payload area of the chunk must
|
|
184
|
-
* be maxaligned, and the "aset" link must be immediately adjacent to the
|
|
185
|
-
* payload area (cf. GetMemoryChunkContext). We simplify matters for this
|
|
186
|
-
* module by requiring sizeof(AllocChunkData) to be maxaligned, and then
|
|
187
|
-
* we can ensure things work by adding any required alignment padding before
|
|
188
|
-
* the "aset" field. There is a static assertion below that the alignment
|
|
189
|
-
* is done correctly.
|
|
190
|
-
*/
|
|
191
|
-
typedef struct AllocChunkData
|
|
192
|
-
{
|
|
193
|
-
/* size is always the size of the usable space in the chunk */
|
|
194
|
-
Size size;
|
|
195
|
-
#ifdef MEMORY_CONTEXT_CHECKING
|
|
196
|
-
/* when debugging memory usage, also store actual requested size */
|
|
197
|
-
/* this is zero in a free chunk */
|
|
198
|
-
Size requested_size;
|
|
199
|
-
|
|
200
|
-
#define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T * 2 + SIZEOF_VOID_P)
|
|
201
|
-
#else
|
|
202
|
-
#define ALLOCCHUNK_RAWSIZE (SIZEOF_SIZE_T + SIZEOF_VOID_P)
|
|
203
|
-
#endif /* MEMORY_CONTEXT_CHECKING */
|
|
204
|
-
|
|
205
|
-
/* ensure proper alignment by adding padding if needed */
|
|
206
|
-
#if (ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF) != 0
|
|
207
|
-
char padding[MAXIMUM_ALIGNOF - ALLOCCHUNK_RAWSIZE % MAXIMUM_ALIGNOF];
|
|
208
|
-
#endif
|
|
209
|
-
|
|
210
|
-
/* aset is the owning aset if allocated, or the freelist link if free */
|
|
211
|
-
void *aset;
|
|
212
|
-
/* there must not be any padding to reach a MAXALIGN boundary here! */
|
|
213
|
-
} AllocChunkData;
|
|
214
|
-
|
|
215
|
-
/*
|
|
216
|
-
* Only the "aset" field should be accessed outside this module.
|
|
217
|
-
* We keep the rest of an allocated chunk's header marked NOACCESS when using
|
|
218
|
-
* valgrind. But note that chunk headers that are in a freelist are kept
|
|
219
|
-
* accessible, for simplicity.
|
|
220
|
-
*/
|
|
221
|
-
#define ALLOCCHUNK_PRIVATE_LEN offsetof(AllocChunkData, aset)
|
|
222
|
-
|
|
223
210
|
/*
|
|
224
211
|
* AllocPointerIsValid
|
|
225
212
|
* True iff pointer is valid allocation pointer.
|
|
@@ -230,12 +217,23 @@ typedef struct AllocChunkData
|
|
|
230
217
|
* AllocSetIsValid
|
|
231
218
|
* True iff set is valid allocation set.
|
|
232
219
|
*/
|
|
233
|
-
#define AllocSetIsValid(set)
|
|
220
|
+
#define AllocSetIsValid(set) \
|
|
221
|
+
(PointerIsValid(set) && IsA(set, AllocSetContext))
|
|
234
222
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
223
|
+
/*
|
|
224
|
+
* AllocBlockIsValid
|
|
225
|
+
* True iff block is valid block of allocation set.
|
|
226
|
+
*/
|
|
227
|
+
#define AllocBlockIsValid(block) \
|
|
228
|
+
(PointerIsValid(block) && AllocSetIsValid((block)->aset))
|
|
229
|
+
|
|
230
|
+
/*
|
|
231
|
+
* We always store external chunks on a dedicated block. This makes fetching
|
|
232
|
+
* the block from an external chunk easy since it's always the first and only
|
|
233
|
+
* chunk on the block.
|
|
234
|
+
*/
|
|
235
|
+
#define ExternalChunkGetBlock(chunk) \
|
|
236
|
+
(AllocBlock) ((char *) chunk - ALLOC_BLOCKHDRSZ)
|
|
239
237
|
|
|
240
238
|
/*
|
|
241
239
|
* Rather than repeatedly creating and deleting memory contexts, we keep some
|
|
@@ -280,42 +278,6 @@ static __thread AllocSetFreeList context_freelists[2] =
|
|
|
280
278
|
};
|
|
281
279
|
|
|
282
280
|
|
|
283
|
-
/*
|
|
284
|
-
* These functions implement the MemoryContext API for AllocSet contexts.
|
|
285
|
-
*/
|
|
286
|
-
static void *AllocSetAlloc(MemoryContext context, Size size);
|
|
287
|
-
static void AllocSetFree(MemoryContext context, void *pointer);
|
|
288
|
-
static void *AllocSetRealloc(MemoryContext context, void *pointer, Size size);
|
|
289
|
-
static void AllocSetReset(MemoryContext context);
|
|
290
|
-
static void AllocSetDelete(MemoryContext context);
|
|
291
|
-
static Size AllocSetGetChunkSpace(MemoryContext context, void *pointer);
|
|
292
|
-
static bool AllocSetIsEmpty(MemoryContext context);
|
|
293
|
-
static void AllocSetStats(MemoryContext context,
|
|
294
|
-
MemoryStatsPrintFunc printfunc, void *passthru,
|
|
295
|
-
MemoryContextCounters *totals,
|
|
296
|
-
bool print_to_stderr);
|
|
297
|
-
|
|
298
|
-
#ifdef MEMORY_CONTEXT_CHECKING
|
|
299
|
-
static void AllocSetCheck(MemoryContext context);
|
|
300
|
-
#endif
|
|
301
|
-
|
|
302
|
-
/*
|
|
303
|
-
* This is the virtual function table for AllocSet contexts.
|
|
304
|
-
*/
|
|
305
|
-
static const MemoryContextMethods AllocSetMethods = {
|
|
306
|
-
AllocSetAlloc,
|
|
307
|
-
AllocSetFree,
|
|
308
|
-
AllocSetRealloc,
|
|
309
|
-
AllocSetReset,
|
|
310
|
-
AllocSetDelete,
|
|
311
|
-
AllocSetGetChunkSpace,
|
|
312
|
-
AllocSetIsEmpty,
|
|
313
|
-
AllocSetStats
|
|
314
|
-
#ifdef MEMORY_CONTEXT_CHECKING
|
|
315
|
-
,AllocSetCheck
|
|
316
|
-
#endif
|
|
317
|
-
};
|
|
318
|
-
|
|
319
281
|
|
|
320
282
|
/* ----------
|
|
321
283
|
* AllocSetFreeIndex -
|
|
@@ -339,7 +301,7 @@ AllocSetFreeIndex(Size size)
|
|
|
339
301
|
* or equivalently
|
|
340
302
|
* pg_leftmost_one_pos32(size - 1) - ALLOC_MINBITS + 1
|
|
341
303
|
*
|
|
342
|
-
* However,
|
|
304
|
+
* However, for platforms without intrinsic support, we duplicate the
|
|
343
305
|
* logic here, allowing an additional optimization. It's reasonable
|
|
344
306
|
* to assume that ALLOC_CHUNK_LIMIT fits in 16 bits, so we can unroll
|
|
345
307
|
* the byte-at-a-time loop in pg_leftmost_one_pos32 and just handle
|
|
@@ -349,14 +311,14 @@ AllocSetFreeIndex(Size size)
|
|
|
349
311
|
* much trouble.
|
|
350
312
|
*----------
|
|
351
313
|
*/
|
|
352
|
-
#ifdef
|
|
353
|
-
idx =
|
|
314
|
+
#ifdef HAVE_BITSCAN_REVERSE
|
|
315
|
+
idx = pg_leftmost_one_pos32((uint32) size - 1) - ALLOC_MINBITS + 1;
|
|
354
316
|
#else
|
|
355
317
|
uint32 t,
|
|
356
318
|
tsize;
|
|
357
319
|
|
|
358
320
|
/* Statically assert that we only have a 16-bit input value. */
|
|
359
|
-
|
|
321
|
+
StaticAssertDecl(ALLOC_CHUNK_LIMIT < (1 << 16),
|
|
360
322
|
"ALLOC_CHUNK_LIMIT must be less than 64kB");
|
|
361
323
|
|
|
362
324
|
tsize = size - 1;
|
|
@@ -407,18 +369,24 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
407
369
|
AllocSet set;
|
|
408
370
|
AllocBlock block;
|
|
409
371
|
|
|
410
|
-
/*
|
|
411
|
-
|
|
412
|
-
"sizeof(
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
"
|
|
372
|
+
/* ensure MemoryChunk's size is properly maxaligned */
|
|
373
|
+
StaticAssertDecl(ALLOC_CHUNKHDRSZ == MAXALIGN(ALLOC_CHUNKHDRSZ),
|
|
374
|
+
"sizeof(MemoryChunk) is not maxaligned");
|
|
375
|
+
/* check we have enough space to store the freelist link */
|
|
376
|
+
StaticAssertDecl(sizeof(AllocFreeListLink) <= (1 << ALLOC_MINBITS),
|
|
377
|
+
"sizeof(AllocFreeListLink) larger than minimum allocation size");
|
|
416
378
|
|
|
417
379
|
/*
|
|
418
380
|
* First, validate allocation parameters. Once these were regular runtime
|
|
419
|
-
*
|
|
420
|
-
* varies their parameters at runtime. We somewhat arbitrarily
|
|
421
|
-
* minimum 1K block size.
|
|
381
|
+
* tests and elog's, but in practice Asserts seem sufficient because
|
|
382
|
+
* nobody varies their parameters at runtime. We somewhat arbitrarily
|
|
383
|
+
* enforce a minimum 1K block size. We restrict the maximum block size to
|
|
384
|
+
* MEMORYCHUNK_MAX_BLOCKOFFSET as MemoryChunks are limited to this in
|
|
385
|
+
* regards to addressing the offset between the chunk and the block that
|
|
386
|
+
* the chunk is stored on. We would be unable to store the offset between
|
|
387
|
+
* the chunk and block for any chunks that were beyond
|
|
388
|
+
* MEMORYCHUNK_MAX_BLOCKOFFSET bytes into the block if the block was to be
|
|
389
|
+
* larger than this.
|
|
422
390
|
*/
|
|
423
391
|
Assert(initBlockSize == MAXALIGN(initBlockSize) &&
|
|
424
392
|
initBlockSize >= 1024);
|
|
@@ -429,6 +397,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
429
397
|
(minContextSize == MAXALIGN(minContextSize) &&
|
|
430
398
|
minContextSize >= 1024 &&
|
|
431
399
|
minContextSize <= maxBlockSize));
|
|
400
|
+
Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
|
|
432
401
|
|
|
433
402
|
/*
|
|
434
403
|
* Check whether the parameters match either available freelist. We do
|
|
@@ -463,7 +432,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
463
432
|
/* Reinitialize its header, installing correct name and parent */
|
|
464
433
|
MemoryContextCreate((MemoryContext) set,
|
|
465
434
|
T_AllocSetContext,
|
|
466
|
-
|
|
435
|
+
MCTX_ASET_ID,
|
|
467
436
|
parent,
|
|
468
437
|
name);
|
|
469
438
|
|
|
@@ -537,15 +506,20 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
537
506
|
* requests that are all the maximum chunk size we will waste at most
|
|
538
507
|
* 1/8th of the allocated space.
|
|
539
508
|
*
|
|
540
|
-
* We have to have allocChunkLimit a power of two, because the requested
|
|
541
|
-
* and actually-allocated sizes of any chunk must be on the same side of
|
|
542
|
-
* the limit, else we get confused about whether the chunk is "big".
|
|
543
|
-
*
|
|
544
509
|
* Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD.
|
|
545
510
|
*/
|
|
546
511
|
StaticAssertStmt(ALLOC_CHUNK_LIMIT == ALLOCSET_SEPARATE_THRESHOLD,
|
|
547
512
|
"ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
|
|
548
513
|
|
|
514
|
+
/*
|
|
515
|
+
* Determine the maximum size that a chunk can be before we allocate an
|
|
516
|
+
* entire AllocBlock dedicated for that chunk. We set the absolute limit
|
|
517
|
+
* of that size as ALLOC_CHUNK_LIMIT but we reduce it further so that we
|
|
518
|
+
* can fit about ALLOC_CHUNK_FRACTION chunks this size on a maximally
|
|
519
|
+
* sized block. (We opt to keep allocChunkLimit a power-of-2 value
|
|
520
|
+
* primarily for legacy reasons rather than calculating it so that exactly
|
|
521
|
+
* ALLOC_CHUNK_FRACTION chunks fit on a maximally sized block.)
|
|
522
|
+
*/
|
|
549
523
|
set->allocChunkLimit = ALLOC_CHUNK_LIMIT;
|
|
550
524
|
while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
|
|
551
525
|
(Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))
|
|
@@ -554,7 +528,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
554
528
|
/* Finally, do the type-independent part of context creation */
|
|
555
529
|
MemoryContextCreate((MemoryContext) set,
|
|
556
530
|
T_AllocSetContext,
|
|
557
|
-
|
|
531
|
+
MCTX_ASET_ID,
|
|
558
532
|
parent,
|
|
559
533
|
name);
|
|
560
534
|
|
|
@@ -575,21 +549,23 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
575
549
|
* thrash malloc() when a context is repeatedly reset after small allocations,
|
|
576
550
|
* which is typical behavior for per-tuple contexts.
|
|
577
551
|
*/
|
|
578
|
-
|
|
552
|
+
void
|
|
579
553
|
AllocSetReset(MemoryContext context)
|
|
580
554
|
{
|
|
581
555
|
AllocSet set = (AllocSet) context;
|
|
582
556
|
AllocBlock block;
|
|
583
|
-
Size keepersize PG_USED_FOR_ASSERTS_ONLY
|
|
584
|
-
= set->keeper->endptr - ((char *) set);
|
|
557
|
+
Size keepersize PG_USED_FOR_ASSERTS_ONLY;
|
|
585
558
|
|
|
586
|
-
|
|
559
|
+
Assert(AllocSetIsValid(set));
|
|
587
560
|
|
|
588
561
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
589
562
|
/* Check for corruption and leaks before freeing */
|
|
590
563
|
AllocSetCheck(context);
|
|
591
564
|
#endif
|
|
592
565
|
|
|
566
|
+
/* Remember keeper block size for Assert below */
|
|
567
|
+
keepersize = set->keeper->endptr - ((char *) set);
|
|
568
|
+
|
|
593
569
|
/* Clear chunk freelists */
|
|
594
570
|
MemSetAligned(set->freelist, 0, sizeof(set->freelist));
|
|
595
571
|
|
|
@@ -643,21 +619,23 @@ AllocSetReset(MemoryContext context)
|
|
|
643
619
|
*
|
|
644
620
|
* Unlike AllocSetReset, this *must* free all resources of the set.
|
|
645
621
|
*/
|
|
646
|
-
|
|
622
|
+
void
|
|
647
623
|
AllocSetDelete(MemoryContext context)
|
|
648
624
|
{
|
|
649
625
|
AllocSet set = (AllocSet) context;
|
|
650
626
|
AllocBlock block = set->blocks;
|
|
651
|
-
Size keepersize PG_USED_FOR_ASSERTS_ONLY
|
|
652
|
-
= set->keeper->endptr - ((char *) set);
|
|
627
|
+
Size keepersize PG_USED_FOR_ASSERTS_ONLY;
|
|
653
628
|
|
|
654
|
-
|
|
629
|
+
Assert(AllocSetIsValid(set));
|
|
655
630
|
|
|
656
631
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
657
632
|
/* Check for corruption and leaks before freeing */
|
|
658
633
|
AllocSetCheck(context);
|
|
659
634
|
#endif
|
|
660
635
|
|
|
636
|
+
/* Remember keeper block size for Assert below */
|
|
637
|
+
keepersize = set->keeper->endptr - ((char *) set);
|
|
638
|
+
|
|
661
639
|
/*
|
|
662
640
|
* If the context is a candidate for a freelist, put it into that freelist
|
|
663
641
|
* instead of destroying it.
|
|
@@ -737,17 +715,17 @@ AllocSetDelete(MemoryContext context)
|
|
|
737
715
|
* is marked, as mcxt.c will set it to UNDEFINED. In some paths we will
|
|
738
716
|
* return space that is marked NOACCESS - AllocSetRealloc has to beware!
|
|
739
717
|
*/
|
|
740
|
-
|
|
718
|
+
void *
|
|
741
719
|
AllocSetAlloc(MemoryContext context, Size size)
|
|
742
720
|
{
|
|
743
721
|
AllocSet set = (AllocSet) context;
|
|
744
722
|
AllocBlock block;
|
|
745
|
-
|
|
723
|
+
MemoryChunk *chunk;
|
|
746
724
|
int fidx;
|
|
747
725
|
Size chunk_size;
|
|
748
726
|
Size blksize;
|
|
749
727
|
|
|
750
|
-
|
|
728
|
+
Assert(AllocSetIsValid(set));
|
|
751
729
|
|
|
752
730
|
/*
|
|
753
731
|
* If requested size exceeds maximum for chunks, allocate an entire block
|
|
@@ -755,7 +733,13 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
755
733
|
*/
|
|
756
734
|
if (size > set->allocChunkLimit)
|
|
757
735
|
{
|
|
736
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
737
|
+
/* ensure there's always space for the sentinel byte */
|
|
738
|
+
chunk_size = MAXALIGN(size + 1);
|
|
739
|
+
#else
|
|
758
740
|
chunk_size = MAXALIGN(size);
|
|
741
|
+
#endif
|
|
742
|
+
|
|
759
743
|
blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
|
|
760
744
|
block = (AllocBlock) malloc(blksize);
|
|
761
745
|
if (block == NULL)
|
|
@@ -766,18 +750,20 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
766
750
|
block->aset = set;
|
|
767
751
|
block->freeptr = block->endptr = ((char *) block) + blksize;
|
|
768
752
|
|
|
769
|
-
chunk = (
|
|
770
|
-
|
|
771
|
-
|
|
753
|
+
chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
|
|
754
|
+
|
|
755
|
+
/* mark the MemoryChunk as externally managed */
|
|
756
|
+
MemoryChunkSetHdrMaskExternal(chunk, MCTX_ASET_ID);
|
|
757
|
+
|
|
772
758
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
773
759
|
chunk->requested_size = size;
|
|
774
760
|
/* set mark to catch clobber of "unused" space */
|
|
775
|
-
|
|
776
|
-
|
|
761
|
+
Assert(size < chunk_size);
|
|
762
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
777
763
|
#endif
|
|
778
764
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
779
765
|
/* fill the allocated space with junk */
|
|
780
|
-
randomize_mem((char *)
|
|
766
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
781
767
|
#endif
|
|
782
768
|
|
|
783
769
|
/*
|
|
@@ -800,13 +786,13 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
800
786
|
}
|
|
801
787
|
|
|
802
788
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
803
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
789
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
804
790
|
chunk_size - size);
|
|
805
791
|
|
|
806
|
-
/* Disallow
|
|
807
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
792
|
+
/* Disallow access to the chunk header. */
|
|
793
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
808
794
|
|
|
809
|
-
return
|
|
795
|
+
return MemoryChunkGetPointer(chunk);
|
|
810
796
|
}
|
|
811
797
|
|
|
812
798
|
/*
|
|
@@ -814,42 +800,54 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
814
800
|
* corresponding free list to see if there is a free chunk we could reuse.
|
|
815
801
|
* If one is found, remove it from the free list, make it again a member
|
|
816
802
|
* of the alloc set and return its data address.
|
|
803
|
+
*
|
|
804
|
+
* Note that we don't attempt to ensure there's space for the sentinel
|
|
805
|
+
* byte here. We expect a large proportion of allocations to be for sizes
|
|
806
|
+
* which are already a power of 2. If we were to always make space for a
|
|
807
|
+
* sentinel byte in MEMORY_CONTEXT_CHECKING builds, then we'd end up
|
|
808
|
+
* doubling the memory requirements for such allocations.
|
|
817
809
|
*/
|
|
818
810
|
fidx = AllocSetFreeIndex(size);
|
|
819
811
|
chunk = set->freelist[fidx];
|
|
820
812
|
if (chunk != NULL)
|
|
821
813
|
{
|
|
822
|
-
|
|
814
|
+
AllocFreeListLink *link = GetFreeListLink(chunk);
|
|
815
|
+
|
|
816
|
+
/* Allow access to the chunk header. */
|
|
817
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
823
818
|
|
|
824
|
-
|
|
819
|
+
Assert(fidx == MemoryChunkGetValue(chunk));
|
|
825
820
|
|
|
826
|
-
chunk
|
|
821
|
+
/* pop this chunk off the freelist */
|
|
822
|
+
VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
|
|
823
|
+
set->freelist[fidx] = link->next;
|
|
824
|
+
VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
|
|
827
825
|
|
|
828
826
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
829
827
|
chunk->requested_size = size;
|
|
830
828
|
/* set mark to catch clobber of "unused" space */
|
|
831
|
-
if (size <
|
|
832
|
-
set_sentinel(
|
|
829
|
+
if (size < GetChunkSizeFromFreeListIdx(fidx))
|
|
830
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
833
831
|
#endif
|
|
834
832
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
835
833
|
/* fill the allocated space with junk */
|
|
836
|
-
randomize_mem((char *)
|
|
834
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
837
835
|
#endif
|
|
838
836
|
|
|
839
837
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
840
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
841
|
-
|
|
838
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
839
|
+
GetChunkSizeFromFreeListIdx(fidx) - size);
|
|
842
840
|
|
|
843
|
-
/* Disallow
|
|
844
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
841
|
+
/* Disallow access to the chunk header. */
|
|
842
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
845
843
|
|
|
846
|
-
return
|
|
844
|
+
return MemoryChunkGetPointer(chunk);
|
|
847
845
|
}
|
|
848
846
|
|
|
849
847
|
/*
|
|
850
848
|
* Choose the actual chunk size to allocate.
|
|
851
849
|
*/
|
|
852
|
-
chunk_size = (
|
|
850
|
+
chunk_size = GetChunkSizeFromFreeListIdx(fidx);
|
|
853
851
|
Assert(chunk_size >= size);
|
|
854
852
|
|
|
855
853
|
/*
|
|
@@ -876,6 +874,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
876
874
|
*/
|
|
877
875
|
while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))
|
|
878
876
|
{
|
|
877
|
+
AllocFreeListLink *link;
|
|
879
878
|
Size availchunk = availspace - ALLOC_CHUNKHDRSZ;
|
|
880
879
|
int a_fidx = AllocSetFreeIndex(availchunk);
|
|
881
880
|
|
|
@@ -884,29 +883,34 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
884
883
|
* freelist than the one we need to put this chunk on. The
|
|
885
884
|
* exception is when availchunk is exactly a power of 2.
|
|
886
885
|
*/
|
|
887
|
-
if (availchunk != (
|
|
886
|
+
if (availchunk != GetChunkSizeFromFreeListIdx(a_fidx))
|
|
888
887
|
{
|
|
889
888
|
a_fidx--;
|
|
890
889
|
Assert(a_fidx >= 0);
|
|
891
|
-
availchunk = (
|
|
890
|
+
availchunk = GetChunkSizeFromFreeListIdx(a_fidx);
|
|
892
891
|
}
|
|
893
892
|
|
|
894
|
-
chunk = (
|
|
893
|
+
chunk = (MemoryChunk *) (block->freeptr);
|
|
895
894
|
|
|
896
895
|
/* Prepare to initialize the chunk header. */
|
|
897
896
|
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
898
|
-
|
|
899
897
|
block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
|
|
900
898
|
availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
|
|
901
899
|
|
|
902
|
-
|
|
900
|
+
/* store the freelist index in the value field */
|
|
901
|
+
MemoryChunkSetHdrMask(chunk, block, a_fidx, MCTX_ASET_ID);
|
|
903
902
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
904
|
-
chunk->requested_size =
|
|
903
|
+
chunk->requested_size = InvalidAllocSize; /* mark it free */
|
|
905
904
|
#endif
|
|
906
|
-
chunk
|
|
905
|
+
/* push this chunk onto the free list */
|
|
906
|
+
link = GetFreeListLink(chunk);
|
|
907
|
+
|
|
908
|
+
VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
|
|
909
|
+
link->next = set->freelist[a_fidx];
|
|
910
|
+
VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
|
|
911
|
+
|
|
907
912
|
set->freelist[a_fidx] = chunk;
|
|
908
913
|
}
|
|
909
|
-
|
|
910
914
|
/* Mark that we need to create a new block */
|
|
911
915
|
block = NULL;
|
|
912
916
|
}
|
|
@@ -974,7 +978,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
974
978
|
/*
|
|
975
979
|
* OK, do the allocation
|
|
976
980
|
*/
|
|
977
|
-
chunk = (
|
|
981
|
+
chunk = (MemoryChunk *) (block->freeptr);
|
|
978
982
|
|
|
979
983
|
/* Prepare to initialize the chunk header. */
|
|
980
984
|
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
@@ -982,69 +986,67 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
982
986
|
block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
|
|
983
987
|
Assert(block->freeptr <= block->endptr);
|
|
984
988
|
|
|
985
|
-
|
|
986
|
-
chunk
|
|
989
|
+
/* store the free list index in the value field */
|
|
990
|
+
MemoryChunkSetHdrMask(chunk, block, fidx, MCTX_ASET_ID);
|
|
991
|
+
|
|
987
992
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
988
993
|
chunk->requested_size = size;
|
|
989
994
|
/* set mark to catch clobber of "unused" space */
|
|
990
|
-
if (size <
|
|
991
|
-
set_sentinel(
|
|
995
|
+
if (size < chunk_size)
|
|
996
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
992
997
|
#endif
|
|
993
998
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
994
999
|
/* fill the allocated space with junk */
|
|
995
|
-
randomize_mem((char *)
|
|
1000
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
996
1001
|
#endif
|
|
997
1002
|
|
|
998
1003
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
999
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
1004
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
1000
1005
|
chunk_size - size);
|
|
1001
1006
|
|
|
1002
|
-
/* Disallow
|
|
1003
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1007
|
+
/* Disallow access to the chunk header. */
|
|
1008
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1004
1009
|
|
|
1005
|
-
return
|
|
1010
|
+
return MemoryChunkGetPointer(chunk);
|
|
1006
1011
|
}
|
|
1007
1012
|
|
|
1008
1013
|
/*
|
|
1009
1014
|
* AllocSetFree
|
|
1010
1015
|
* Frees allocated memory; memory is removed from the set.
|
|
1011
1016
|
*/
|
|
1012
|
-
|
|
1013
|
-
AllocSetFree(
|
|
1017
|
+
void
|
|
1018
|
+
AllocSetFree(void *pointer)
|
|
1014
1019
|
{
|
|
1015
|
-
AllocSet set
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
/* Allow access to private part of chunk header. */
|
|
1019
|
-
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
|
1020
|
+
AllocSet set;
|
|
1021
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1020
1022
|
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
if (chunk->requested_size < chunk->size)
|
|
1024
|
-
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1025
|
-
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1026
|
-
set->header.name, chunk);
|
|
1027
|
-
#endif
|
|
1023
|
+
/* Allow access to the chunk header. */
|
|
1024
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1028
1025
|
|
|
1029
|
-
if (chunk
|
|
1026
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1030
1027
|
{
|
|
1031
|
-
/*
|
|
1032
|
-
|
|
1033
|
-
* blocks. Just unlink that block and return it to malloc().
|
|
1034
|
-
*/
|
|
1035
|
-
AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
|
|
1028
|
+
/* Release single-chunk block. */
|
|
1029
|
+
AllocBlock block = ExternalChunkGetBlock(chunk);
|
|
1036
1030
|
|
|
1037
1031
|
/*
|
|
1038
|
-
* Try to verify that we have a sane block pointer:
|
|
1039
|
-
* reference
|
|
1040
|
-
* just past the chunk.
|
|
1032
|
+
* Try to verify that we have a sane block pointer: the block header
|
|
1033
|
+
* should reference an aset and the freeptr should match the endptr.
|
|
1041
1034
|
*/
|
|
1042
|
-
if (block->
|
|
1043
|
-
block->freeptr != block->endptr ||
|
|
1044
|
-
block->freeptr != ((char *) block) +
|
|
1045
|
-
(chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
|
|
1035
|
+
if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
|
|
1046
1036
|
elog(ERROR, "could not find block containing chunk %p", chunk);
|
|
1047
1037
|
|
|
1038
|
+
set = block->aset;
|
|
1039
|
+
|
|
1040
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1041
|
+
{
|
|
1042
|
+
/* Test for someone scribbling on unused space in chunk */
|
|
1043
|
+
Assert(chunk->requested_size < (block->endptr - (char *) pointer));
|
|
1044
|
+
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1045
|
+
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1046
|
+
set->header.name, chunk);
|
|
1047
|
+
}
|
|
1048
|
+
#endif
|
|
1049
|
+
|
|
1048
1050
|
/* OK, remove block from aset's list and free it */
|
|
1049
1051
|
if (block->prev)
|
|
1050
1052
|
block->prev->next = block->next;
|
|
@@ -1053,7 +1055,7 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1053
1055
|
if (block->next)
|
|
1054
1056
|
block->next->prev = block->prev;
|
|
1055
1057
|
|
|
1056
|
-
|
|
1058
|
+
set->header.mem_allocated -= block->endptr - ((char *) block);
|
|
1057
1059
|
|
|
1058
1060
|
#ifdef CLOBBER_FREED_MEMORY
|
|
1059
1061
|
wipe_mem(block, block->freeptr - ((char *) block));
|
|
@@ -1062,20 +1064,48 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1062
1064
|
}
|
|
1063
1065
|
else
|
|
1064
1066
|
{
|
|
1065
|
-
|
|
1066
|
-
int fidx
|
|
1067
|
+
AllocBlock block = MemoryChunkGetBlock(chunk);
|
|
1068
|
+
int fidx;
|
|
1069
|
+
AllocFreeListLink *link;
|
|
1070
|
+
|
|
1071
|
+
/*
|
|
1072
|
+
* In this path, for speed reasons we just Assert that the referenced
|
|
1073
|
+
* block is good. We can also Assert that the value field is sane.
|
|
1074
|
+
* Future field experience may show that these Asserts had better
|
|
1075
|
+
* become regular runtime test-and-elog checks.
|
|
1076
|
+
*/
|
|
1077
|
+
Assert(AllocBlockIsValid(block));
|
|
1078
|
+
set = block->aset;
|
|
1067
1079
|
|
|
1068
|
-
|
|
1080
|
+
fidx = MemoryChunkGetValue(chunk);
|
|
1081
|
+
Assert(FreeListIdxIsValid(fidx));
|
|
1082
|
+
link = GetFreeListLink(chunk);
|
|
1083
|
+
|
|
1084
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1085
|
+
/* Test for someone scribbling on unused space in chunk */
|
|
1086
|
+
if (chunk->requested_size < GetChunkSizeFromFreeListIdx(fidx))
|
|
1087
|
+
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1088
|
+
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1089
|
+
set->header.name, chunk);
|
|
1090
|
+
#endif
|
|
1069
1091
|
|
|
1070
1092
|
#ifdef CLOBBER_FREED_MEMORY
|
|
1071
|
-
wipe_mem(pointer,
|
|
1093
|
+
wipe_mem(pointer, GetChunkSizeFromFreeListIdx(fidx));
|
|
1072
1094
|
#endif
|
|
1095
|
+
/* push this chunk onto the top of the free list */
|
|
1096
|
+
VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
|
|
1097
|
+
link->next = set->freelist[fidx];
|
|
1098
|
+
VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
|
|
1099
|
+
set->freelist[fidx] = chunk;
|
|
1073
1100
|
|
|
1074
1101
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1075
|
-
|
|
1076
|
-
|
|
1102
|
+
|
|
1103
|
+
/*
|
|
1104
|
+
* Reset requested_size to InvalidAllocSize in chunks that are on free
|
|
1105
|
+
* list.
|
|
1106
|
+
*/
|
|
1107
|
+
chunk->requested_size = InvalidAllocSize;
|
|
1077
1108
|
#endif
|
|
1078
|
-
set->freelist[fidx] = chunk;
|
|
1079
1109
|
}
|
|
1080
1110
|
}
|
|
1081
1111
|
|
|
@@ -1091,57 +1121,56 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1091
1121
|
* (In principle, we could use VALGRIND_GET_VBITS() to rediscover the old
|
|
1092
1122
|
* request size.)
|
|
1093
1123
|
*/
|
|
1094
|
-
|
|
1095
|
-
AllocSetRealloc(
|
|
1124
|
+
void *
|
|
1125
|
+
AllocSetRealloc(void *pointer, Size size)
|
|
1096
1126
|
{
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
|
1103
|
-
|
|
1104
|
-
oldsize = chunk->size;
|
|
1127
|
+
AllocBlock block;
|
|
1128
|
+
AllocSet set;
|
|
1129
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1130
|
+
Size oldchksize;
|
|
1131
|
+
int fidx;
|
|
1105
1132
|
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
if (chunk->requested_size < oldsize)
|
|
1109
|
-
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1110
|
-
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1111
|
-
set->header.name, chunk);
|
|
1112
|
-
#endif
|
|
1133
|
+
/* Allow access to the chunk header. */
|
|
1134
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1113
1135
|
|
|
1114
|
-
if (
|
|
1136
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1115
1137
|
{
|
|
1116
1138
|
/*
|
|
1117
1139
|
* The chunk must have been allocated as a single-chunk block. Use
|
|
1118
1140
|
* realloc() to make the containing block bigger, or smaller, with
|
|
1119
1141
|
* minimum space wastage.
|
|
1120
1142
|
*/
|
|
1121
|
-
AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
|
|
1122
1143
|
Size chksize;
|
|
1123
1144
|
Size blksize;
|
|
1124
1145
|
Size oldblksize;
|
|
1125
1146
|
|
|
1147
|
+
block = ExternalChunkGetBlock(chunk);
|
|
1148
|
+
|
|
1126
1149
|
/*
|
|
1127
|
-
* Try to verify that we have a sane block pointer:
|
|
1128
|
-
* reference
|
|
1129
|
-
* just past the chunk.
|
|
1150
|
+
* Try to verify that we have a sane block pointer: the block header
|
|
1151
|
+
* should reference an aset and the freeptr should match the endptr.
|
|
1130
1152
|
*/
|
|
1131
|
-
if (block->
|
|
1132
|
-
block->freeptr != block->endptr ||
|
|
1133
|
-
block->freeptr != ((char *) block) +
|
|
1134
|
-
(oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
|
|
1153
|
+
if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
|
|
1135
1154
|
elog(ERROR, "could not find block containing chunk %p", chunk);
|
|
1136
1155
|
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1156
|
+
set = block->aset;
|
|
1157
|
+
|
|
1158
|
+
oldchksize = block->endptr - (char *) pointer;
|
|
1159
|
+
|
|
1160
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1161
|
+
/* Test for someone scribbling on unused space in chunk */
|
|
1162
|
+
Assert(chunk->requested_size < oldchksize);
|
|
1163
|
+
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1164
|
+
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1165
|
+
set->header.name, chunk);
|
|
1166
|
+
#endif
|
|
1167
|
+
|
|
1168
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1169
|
+
/* ensure there's always space for the sentinel byte */
|
|
1170
|
+
chksize = MAXALIGN(size + 1);
|
|
1171
|
+
#else
|
|
1172
|
+
chksize = MAXALIGN(size);
|
|
1173
|
+
#endif
|
|
1145
1174
|
|
|
1146
1175
|
/* Do the realloc */
|
|
1147
1176
|
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
|
|
@@ -1150,77 +1179,109 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1150
1179
|
block = (AllocBlock) realloc(block, blksize);
|
|
1151
1180
|
if (block == NULL)
|
|
1152
1181
|
{
|
|
1153
|
-
/* Disallow
|
|
1154
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1182
|
+
/* Disallow access to the chunk header. */
|
|
1183
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1155
1184
|
return NULL;
|
|
1156
1185
|
}
|
|
1157
1186
|
|
|
1158
1187
|
/* updated separately, not to underflow when (oldblksize > blksize) */
|
|
1159
|
-
|
|
1160
|
-
|
|
1188
|
+
set->header.mem_allocated -= oldblksize;
|
|
1189
|
+
set->header.mem_allocated += blksize;
|
|
1161
1190
|
|
|
1162
1191
|
block->freeptr = block->endptr = ((char *) block) + blksize;
|
|
1163
1192
|
|
|
1164
1193
|
/* Update pointers since block has likely been moved */
|
|
1165
|
-
chunk = (
|
|
1166
|
-
pointer =
|
|
1194
|
+
chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
|
|
1195
|
+
pointer = MemoryChunkGetPointer(chunk);
|
|
1167
1196
|
if (block->prev)
|
|
1168
1197
|
block->prev->next = block;
|
|
1169
1198
|
else
|
|
1170
1199
|
set->blocks = block;
|
|
1171
1200
|
if (block->next)
|
|
1172
1201
|
block->next->prev = block;
|
|
1173
|
-
chunk->size = chksize;
|
|
1174
1202
|
|
|
1175
1203
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1176
1204
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
1177
|
-
|
|
1205
|
+
|
|
1206
|
+
/*
|
|
1207
|
+
* We can only randomize the extra space if we know the prior request.
|
|
1208
|
+
* When using Valgrind, randomize_mem() also marks memory UNDEFINED.
|
|
1209
|
+
*/
|
|
1178
1210
|
if (size > chunk->requested_size)
|
|
1179
1211
|
randomize_mem((char *) pointer + chunk->requested_size,
|
|
1180
1212
|
size - chunk->requested_size);
|
|
1181
|
-
#
|
|
1213
|
+
#else
|
|
1182
1214
|
|
|
1183
1215
|
/*
|
|
1184
|
-
*
|
|
1185
|
-
* part
|
|
1186
|
-
* old allocation
|
|
1216
|
+
* If this is an increase, realloc() will have marked any
|
|
1217
|
+
* newly-allocated part (from oldchksize to chksize) UNDEFINED, but we
|
|
1218
|
+
* also need to adjust trailing bytes from the old allocation (from
|
|
1219
|
+
* chunk->requested_size to oldchksize) as they are marked NOACCESS.
|
|
1220
|
+
* Make sure not to mark too many bytes in case chunk->requested_size
|
|
1221
|
+
* < size < oldchksize.
|
|
1187
1222
|
*/
|
|
1188
1223
|
#ifdef USE_VALGRIND
|
|
1189
|
-
if (
|
|
1224
|
+
if (Min(size, oldchksize) > chunk->requested_size)
|
|
1190
1225
|
VALGRIND_MAKE_MEM_UNDEFINED((char *) pointer + chunk->requested_size,
|
|
1191
|
-
|
|
1226
|
+
Min(size, oldchksize) - chunk->requested_size);
|
|
1227
|
+
#endif
|
|
1192
1228
|
#endif
|
|
1193
1229
|
|
|
1194
1230
|
chunk->requested_size = size;
|
|
1195
|
-
|
|
1196
1231
|
/* set mark to catch clobber of "unused" space */
|
|
1197
|
-
|
|
1198
|
-
|
|
1232
|
+
Assert(size < chksize);
|
|
1233
|
+
set_sentinel(pointer, size);
|
|
1199
1234
|
#else /* !MEMORY_CONTEXT_CHECKING */
|
|
1200
1235
|
|
|
1201
1236
|
/*
|
|
1202
|
-
* We
|
|
1203
|
-
*
|
|
1204
|
-
*
|
|
1237
|
+
* We may need to adjust marking of bytes from the old allocation as
|
|
1238
|
+
* some of them may be marked NOACCESS. We don't know how much of the
|
|
1239
|
+
* old chunk size was the requested size; it could have been as small
|
|
1240
|
+
* as one byte. We have to be conservative and just mark the entire
|
|
1241
|
+
* old portion DEFINED. Make sure not to mark memory beyond the new
|
|
1242
|
+
* allocation in case it's smaller than the old one.
|
|
1205
1243
|
*/
|
|
1206
|
-
VALGRIND_MAKE_MEM_DEFINED(pointer,
|
|
1244
|
+
VALGRIND_MAKE_MEM_DEFINED(pointer, Min(size, oldchksize));
|
|
1207
1245
|
#endif
|
|
1208
1246
|
|
|
1209
1247
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
1210
1248
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
|
|
1211
1249
|
|
|
1212
|
-
/* Disallow
|
|
1213
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1250
|
+
/* Disallow access to the chunk header . */
|
|
1251
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1214
1252
|
|
|
1215
1253
|
return pointer;
|
|
1216
1254
|
}
|
|
1217
1255
|
|
|
1256
|
+
block = MemoryChunkGetBlock(chunk);
|
|
1257
|
+
|
|
1258
|
+
/*
|
|
1259
|
+
* In this path, for speed reasons we just Assert that the referenced
|
|
1260
|
+
* block is good. We can also Assert that the value field is sane. Future
|
|
1261
|
+
* field experience may show that these Asserts had better become regular
|
|
1262
|
+
* runtime test-and-elog checks.
|
|
1263
|
+
*/
|
|
1264
|
+
Assert(AllocBlockIsValid(block));
|
|
1265
|
+
set = block->aset;
|
|
1266
|
+
|
|
1267
|
+
fidx = MemoryChunkGetValue(chunk);
|
|
1268
|
+
Assert(FreeListIdxIsValid(fidx));
|
|
1269
|
+
oldchksize = GetChunkSizeFromFreeListIdx(fidx);
|
|
1270
|
+
|
|
1271
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1272
|
+
/* Test for someone scribbling on unused space in chunk */
|
|
1273
|
+
if (chunk->requested_size < oldchksize)
|
|
1274
|
+
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1275
|
+
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1276
|
+
set->header.name, chunk);
|
|
1277
|
+
#endif
|
|
1278
|
+
|
|
1218
1279
|
/*
|
|
1219
1280
|
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
|
|
1220
1281
|
* allocated area already is >= the new size. (In particular, we will
|
|
1221
1282
|
* fall out here if the requested size is a decrease.)
|
|
1222
1283
|
*/
|
|
1223
|
-
|
|
1284
|
+
if (oldchksize >= size)
|
|
1224
1285
|
{
|
|
1225
1286
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1226
1287
|
Size oldrequest = chunk->requested_size;
|
|
@@ -1243,10 +1304,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1243
1304
|
size - oldrequest);
|
|
1244
1305
|
else
|
|
1245
1306
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size,
|
|
1246
|
-
|
|
1307
|
+
oldchksize - size);
|
|
1247
1308
|
|
|
1248
1309
|
/* set mark to catch clobber of "unused" space */
|
|
1249
|
-
if (size <
|
|
1310
|
+
if (size < oldchksize)
|
|
1250
1311
|
set_sentinel(pointer, size);
|
|
1251
1312
|
#else /* !MEMORY_CONTEXT_CHECKING */
|
|
1252
1313
|
|
|
@@ -1255,12 +1316,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1255
1316
|
* the old request or shrinking it, so we conservatively mark the
|
|
1256
1317
|
* entire new allocation DEFINED.
|
|
1257
1318
|
*/
|
|
1258
|
-
VALGRIND_MAKE_MEM_NOACCESS(pointer,
|
|
1319
|
+
VALGRIND_MAKE_MEM_NOACCESS(pointer, oldchksize);
|
|
1259
1320
|
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
|
1260
1321
|
#endif
|
|
1261
1322
|
|
|
1262
|
-
/* Disallow
|
|
1263
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1323
|
+
/* Disallow access to the chunk header. */
|
|
1324
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1264
1325
|
|
|
1265
1326
|
return pointer;
|
|
1266
1327
|
}
|
|
@@ -1278,6 +1339,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1278
1339
|
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
|
|
1279
1340
|
*/
|
|
1280
1341
|
AllocPointer newPointer;
|
|
1342
|
+
Size oldsize;
|
|
1281
1343
|
|
|
1282
1344
|
/* allocate new chunk */
|
|
1283
1345
|
newPointer = AllocSetAlloc((MemoryContext) set, size);
|
|
@@ -1285,8 +1347,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1285
1347
|
/* leave immediately if request was not completed */
|
|
1286
1348
|
if (newPointer == NULL)
|
|
1287
1349
|
{
|
|
1288
|
-
/* Disallow
|
|
1289
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1350
|
+
/* Disallow access to the chunk header. */
|
|
1351
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1290
1352
|
return NULL;
|
|
1291
1353
|
}
|
|
1292
1354
|
|
|
@@ -1302,6 +1364,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1302
1364
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1303
1365
|
oldsize = chunk->requested_size;
|
|
1304
1366
|
#else
|
|
1367
|
+
oldsize = oldchksize;
|
|
1305
1368
|
VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
|
|
1306
1369
|
#endif
|
|
1307
1370
|
|
|
@@ -1309,36 +1372,84 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1309
1372
|
memcpy(newPointer, pointer, oldsize);
|
|
1310
1373
|
|
|
1311
1374
|
/* free old chunk */
|
|
1312
|
-
AllocSetFree(
|
|
1375
|
+
AllocSetFree(pointer);
|
|
1313
1376
|
|
|
1314
1377
|
return newPointer;
|
|
1315
1378
|
}
|
|
1316
1379
|
}
|
|
1317
1380
|
|
|
1381
|
+
/*
|
|
1382
|
+
* AllocSetGetChunkContext
|
|
1383
|
+
* Return the MemoryContext that 'pointer' belongs to.
|
|
1384
|
+
*/
|
|
1385
|
+
MemoryContext
|
|
1386
|
+
AllocSetGetChunkContext(void *pointer)
|
|
1387
|
+
{
|
|
1388
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1389
|
+
AllocBlock block;
|
|
1390
|
+
AllocSet set;
|
|
1391
|
+
|
|
1392
|
+
/* Allow access to the chunk header. */
|
|
1393
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1394
|
+
|
|
1395
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1396
|
+
block = ExternalChunkGetBlock(chunk);
|
|
1397
|
+
else
|
|
1398
|
+
block = (AllocBlock) MemoryChunkGetBlock(chunk);
|
|
1399
|
+
|
|
1400
|
+
/* Disallow access to the chunk header. */
|
|
1401
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1402
|
+
|
|
1403
|
+
Assert(AllocBlockIsValid(block));
|
|
1404
|
+
set = block->aset;
|
|
1405
|
+
|
|
1406
|
+
return &set->header;
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1318
1409
|
/*
|
|
1319
1410
|
* AllocSetGetChunkSpace
|
|
1320
1411
|
* Given a currently-allocated chunk, determine the total space
|
|
1321
1412
|
* it occupies (including all memory-allocation overhead).
|
|
1322
1413
|
*/
|
|
1323
|
-
|
|
1324
|
-
AllocSetGetChunkSpace(
|
|
1414
|
+
Size
|
|
1415
|
+
AllocSetGetChunkSpace(void *pointer)
|
|
1325
1416
|
{
|
|
1326
|
-
|
|
1327
|
-
|
|
1417
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1418
|
+
int fidx;
|
|
1419
|
+
|
|
1420
|
+
/* Allow access to the chunk header. */
|
|
1421
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1422
|
+
|
|
1423
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1424
|
+
{
|
|
1425
|
+
AllocBlock block = ExternalChunkGetBlock(chunk);
|
|
1328
1426
|
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1427
|
+
/* Disallow access to the chunk header. */
|
|
1428
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1429
|
+
|
|
1430
|
+
Assert(AllocBlockIsValid(block));
|
|
1431
|
+
|
|
1432
|
+
return block->endptr - (char *) chunk;
|
|
1433
|
+
}
|
|
1434
|
+
|
|
1435
|
+
fidx = MemoryChunkGetValue(chunk);
|
|
1436
|
+
Assert(FreeListIdxIsValid(fidx));
|
|
1437
|
+
|
|
1438
|
+
/* Disallow access to the chunk header. */
|
|
1439
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1440
|
+
|
|
1441
|
+
return GetChunkSizeFromFreeListIdx(fidx) + ALLOC_CHUNKHDRSZ;
|
|
1333
1442
|
}
|
|
1334
1443
|
|
|
1335
1444
|
/*
|
|
1336
1445
|
* AllocSetIsEmpty
|
|
1337
1446
|
* Is an allocset empty of any allocated space?
|
|
1338
1447
|
*/
|
|
1339
|
-
|
|
1448
|
+
bool
|
|
1340
1449
|
AllocSetIsEmpty(MemoryContext context)
|
|
1341
1450
|
{
|
|
1451
|
+
Assert(AllocSetIsValid(context));
|
|
1452
|
+
|
|
1342
1453
|
/*
|
|
1343
1454
|
* For now, we say "empty" only if the context is new or just reset. We
|
|
1344
1455
|
* could examine the freelists to determine if all space has been freed,
|
|
@@ -1359,7 +1470,7 @@ AllocSetIsEmpty(MemoryContext context)
|
|
|
1359
1470
|
* totals: if not NULL, add stats about this context into *totals.
|
|
1360
1471
|
* print_to_stderr: print stats to stderr if true, elog otherwise.
|
|
1361
1472
|
*/
|
|
1362
|
-
|
|
1473
|
+
void
|
|
1363
1474
|
AllocSetStats(MemoryContext context,
|
|
1364
1475
|
MemoryStatsPrintFunc printfunc, void *passthru,
|
|
1365
1476
|
MemoryContextCounters *totals, bool print_to_stderr)
|
|
@@ -1372,6 +1483,8 @@ AllocSetStats(MemoryContext context,
|
|
|
1372
1483
|
AllocBlock block;
|
|
1373
1484
|
int fidx;
|
|
1374
1485
|
|
|
1486
|
+
Assert(AllocSetIsValid(set));
|
|
1487
|
+
|
|
1375
1488
|
/* Include context header in totalspace */
|
|
1376
1489
|
totalspace = MAXALIGN(sizeof(AllocSetContext));
|
|
1377
1490
|
|
|
@@ -1383,13 +1496,24 @@ AllocSetStats(MemoryContext context,
|
|
|
1383
1496
|
}
|
|
1384
1497
|
for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)
|
|
1385
1498
|
{
|
|
1386
|
-
|
|
1499
|
+
Size chksz = GetChunkSizeFromFreeListIdx(fidx);
|
|
1500
|
+
MemoryChunk *chunk = set->freelist[fidx];
|
|
1387
1501
|
|
|
1388
|
-
|
|
1389
|
-
chunk = (AllocChunk) chunk->aset)
|
|
1502
|
+
while (chunk != NULL)
|
|
1390
1503
|
{
|
|
1504
|
+
AllocFreeListLink *link = GetFreeListLink(chunk);
|
|
1505
|
+
|
|
1506
|
+
/* Allow access to the chunk header. */
|
|
1507
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1508
|
+
Assert(MemoryChunkGetValue(chunk) == fidx);
|
|
1509
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1510
|
+
|
|
1391
1511
|
freechunks++;
|
|
1392
|
-
freespace +=
|
|
1512
|
+
freespace += chksz + ALLOC_CHUNKHDRSZ;
|
|
1513
|
+
|
|
1514
|
+
VALGRIND_MAKE_MEM_DEFINED(link, sizeof(AllocFreeListLink));
|
|
1515
|
+
chunk = link->next;
|
|
1516
|
+
VALGRIND_MAKE_MEM_NOACCESS(link, sizeof(AllocFreeListLink));
|
|
1393
1517
|
}
|
|
1394
1518
|
}
|
|
1395
1519
|
|
|
@@ -1424,7 +1548,7 @@ AllocSetStats(MemoryContext context,
|
|
|
1424
1548
|
* find yourself in an infinite loop when trouble occurs, because this
|
|
1425
1549
|
* routine will be entered again when elog cleanup tries to release memory!
|
|
1426
1550
|
*/
|
|
1427
|
-
|
|
1551
|
+
void
|
|
1428
1552
|
AllocSetCheck(MemoryContext context)
|
|
1429
1553
|
{
|
|
1430
1554
|
AllocSet set = (AllocSet) context;
|
|
@@ -1441,6 +1565,7 @@ AllocSetCheck(MemoryContext context)
|
|
|
1441
1565
|
long blk_used = block->freeptr - bpoz;
|
|
1442
1566
|
long blk_data = 0;
|
|
1443
1567
|
long nchunks = 0;
|
|
1568
|
+
bool has_external_chunk = false;
|
|
1444
1569
|
|
|
1445
1570
|
if (set->keeper == block)
|
|
1446
1571
|
total_allocated += block->endptr - ((char *) set);
|
|
@@ -1472,56 +1597,64 @@ AllocSetCheck(MemoryContext context)
|
|
|
1472
1597
|
*/
|
|
1473
1598
|
while (bpoz < block->freeptr)
|
|
1474
1599
|
{
|
|
1475
|
-
|
|
1600
|
+
MemoryChunk *chunk = (MemoryChunk *) bpoz;
|
|
1476
1601
|
Size chsize,
|
|
1477
1602
|
dsize;
|
|
1478
1603
|
|
|
1479
|
-
/* Allow access to
|
|
1480
|
-
VALGRIND_MAKE_MEM_DEFINED(chunk,
|
|
1604
|
+
/* Allow access to the chunk header. */
|
|
1605
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1606
|
+
|
|
1607
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1608
|
+
{
|
|
1609
|
+
chsize = block->endptr - (char *) MemoryChunkGetPointer(chunk); /* aligned chunk size */
|
|
1610
|
+
has_external_chunk = true;
|
|
1611
|
+
|
|
1612
|
+
/* make sure this chunk consumes the entire block */
|
|
1613
|
+
if (chsize + ALLOC_CHUNKHDRSZ != blk_used)
|
|
1614
|
+
elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
|
|
1615
|
+
name, chunk, block);
|
|
1616
|
+
}
|
|
1617
|
+
else
|
|
1618
|
+
{
|
|
1619
|
+
int fidx = MemoryChunkGetValue(chunk);
|
|
1620
|
+
|
|
1621
|
+
if (!FreeListIdxIsValid(fidx))
|
|
1622
|
+
elog(WARNING, "problem in alloc set %s: bad chunk size for chunk %p in block %p",
|
|
1623
|
+
name, chunk, block);
|
|
1624
|
+
|
|
1625
|
+
chsize = GetChunkSizeFromFreeListIdx(fidx); /* aligned chunk size */
|
|
1481
1626
|
|
|
1482
|
-
|
|
1627
|
+
/*
|
|
1628
|
+
* Check the stored block offset correctly references this
|
|
1629
|
+
* block.
|
|
1630
|
+
*/
|
|
1631
|
+
if (block != MemoryChunkGetBlock(chunk))
|
|
1632
|
+
elog(WARNING, "problem in alloc set %s: bad block offset for chunk %p in block %p",
|
|
1633
|
+
name, chunk, block);
|
|
1634
|
+
}
|
|
1483
1635
|
dsize = chunk->requested_size; /* real data */
|
|
1484
1636
|
|
|
1485
|
-
/*
|
|
1486
|
-
|
|
1487
|
-
*/
|
|
1488
|
-
if (dsize > chsize)
|
|
1637
|
+
/* an allocated chunk's requested size must be <= the chsize */
|
|
1638
|
+
if (dsize != InvalidAllocSize && dsize > chsize)
|
|
1489
1639
|
elog(WARNING, "problem in alloc set %s: req size > alloc size for chunk %p in block %p",
|
|
1490
1640
|
name, chunk, block);
|
|
1641
|
+
|
|
1642
|
+
/* chsize must not be smaller than the first freelist's size */
|
|
1491
1643
|
if (chsize < (1 << ALLOC_MINBITS))
|
|
1492
1644
|
elog(WARNING, "problem in alloc set %s: bad size %zu for chunk %p in block %p",
|
|
1493
1645
|
name, chsize, chunk, block);
|
|
1494
1646
|
|
|
1495
|
-
/* single-chunk block? */
|
|
1496
|
-
if (chsize > set->allocChunkLimit &&
|
|
1497
|
-
chsize + ALLOC_CHUNKHDRSZ != blk_used)
|
|
1498
|
-
elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
|
|
1499
|
-
name, chunk, block);
|
|
1500
|
-
|
|
1501
|
-
/*
|
|
1502
|
-
* If chunk is allocated, check for correct aset pointer. (If it's
|
|
1503
|
-
* free, the aset is the freelist pointer, which we can't check as
|
|
1504
|
-
* easily...) Note this is an incomplete test, since palloc(0)
|
|
1505
|
-
* produces an allocated chunk with requested_size == 0.
|
|
1506
|
-
*/
|
|
1507
|
-
if (dsize > 0 && chunk->aset != (void *) set)
|
|
1508
|
-
elog(WARNING, "problem in alloc set %s: bogus aset link in block %p, chunk %p",
|
|
1509
|
-
name, block, chunk);
|
|
1510
|
-
|
|
1511
1647
|
/*
|
|
1512
1648
|
* Check for overwrite of padding space in an allocated chunk.
|
|
1513
1649
|
*/
|
|
1514
|
-
if (
|
|
1650
|
+
if (dsize != InvalidAllocSize && dsize < chsize &&
|
|
1515
1651
|
!sentinel_ok(chunk, ALLOC_CHUNKHDRSZ + dsize))
|
|
1516
1652
|
elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
|
|
1517
1653
|
name, block, chunk);
|
|
1518
1654
|
|
|
1519
|
-
/*
|
|
1520
|
-
|
|
1521
|
-
|
|
1522
|
-
*/
|
|
1523
|
-
if (chunk->aset == (void *) set)
|
|
1524
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
|
1655
|
+
/* if chunk is allocated, disallow access to the chunk header */
|
|
1656
|
+
if (dsize != InvalidAllocSize)
|
|
1657
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1525
1658
|
|
|
1526
1659
|
blk_data += chsize;
|
|
1527
1660
|
nchunks++;
|
|
@@ -1532,6 +1665,10 @@ AllocSetCheck(MemoryContext context)
|
|
|
1532
1665
|
if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used)
|
|
1533
1666
|
elog(WARNING, "problem in alloc set %s: found inconsistent memory block %p",
|
|
1534
1667
|
name, block);
|
|
1668
|
+
|
|
1669
|
+
if (has_external_chunk && nchunks > 1)
|
|
1670
|
+
elog(WARNING, "problem in alloc set %s: external chunk on non-dedicated block %p",
|
|
1671
|
+
name, block);
|
|
1535
1672
|
}
|
|
1536
1673
|
|
|
1537
1674
|
Assert(total_allocated == context->mem_allocated);
|