pg_query 2.0.3 → 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 +165 -0
- data/README.md +67 -29
- data/Rakefile +8 -23
- data/ext/pg_query/extconf.rb +21 -3
- data/ext/pg_query/include/pg_query.h +29 -4
- data/ext/pg_query/include/pg_query_enum_defs.c +551 -272
- data/ext/pg_query/include/pg_query_fingerprint_conds.c +563 -470
- data/ext/pg_query/include/pg_query_fingerprint_defs.c +5403 -3945
- data/ext/pg_query/include/pg_query_outfuncs_conds.c +402 -330
- data/ext/pg_query/include/pg_query_outfuncs_defs.c +1319 -1059
- data/ext/pg_query/include/pg_query_readfuncs_conds.c +141 -118
- data/ext/pg_query/include/pg_query_readfuncs_defs.c +1685 -1379
- data/ext/pg_query/include/{access → postgres/access}/amapi.h +47 -1
- data/ext/pg_query/include/{access → postgres/access}/attmap.h +5 -3
- data/ext/pg_query/include/{access → postgres/access}/attnum.h +2 -2
- data/ext/pg_query/include/{access → postgres/access}/clog.h +4 -2
- data/ext/pg_query/include/{access → postgres/access}/commit_ts.h +6 -9
- data/ext/pg_query/include/{access → postgres/access}/detoast.h +1 -11
- data/ext/pg_query/include/{access → postgres/access}/genam.h +21 -16
- data/ext/pg_query/include/{access → postgres/access}/gin.h +17 -4
- data/ext/pg_query/include/{access → postgres/access}/htup.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/htup_details.h +80 -88
- data/ext/pg_query/include/{access → postgres/access}/itup.h +61 -52
- 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 +17 -2
- data/ext/pg_query/include/postgres/access/rmgr.h +62 -0
- data/ext/pg_query/include/{access → postgres/access}/rmgrlist.h +24 -24
- 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 +4 -2
- data/ext/pg_query/include/{access → postgres/access}/sysattr.h +1 -1
- data/ext/pg_query/include/{access → postgres/access}/table.h +2 -1
- data/ext/pg_query/include/{access → postgres/access}/tableam.h +337 -62
- data/ext/pg_query/include/postgres/access/toast_compression.h +73 -0
- data/ext/pg_query/include/{access → postgres/access}/transam.h +123 -13
- 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 +60 -100
- data/ext/pg_query/include/{access → postgres/access}/twophase.h +5 -1
- data/ext/pg_query/include/{access → postgres/access}/xact.h +99 -32
- data/ext/pg_query/include/{access → postgres/access}/xlog.h +69 -165
- data/ext/pg_query/include/{access → postgres/access}/xlog_internal.h +147 -73
- data/ext/pg_query/include/postgres/access/xlogbackup.h +41 -0
- data/ext/pg_query/include/{access → postgres/access}/xlogdefs.h +13 -40
- data/ext/pg_query/include/postgres/access/xlogprefetcher.h +55 -0
- data/ext/pg_query/include/{access → postgres/access}/xlogreader.h +154 -37
- data/ext/pg_query/include/{access → postgres/access}/xlogrecord.h +34 -13
- data/ext/pg_query/include/postgres/access/xlogrecovery.h +158 -0
- data/ext/pg_query/include/postgres/archive/archive_module.h +59 -0
- data/ext/pg_query/include/{c.h → postgres/c.h} +245 -188
- data/ext/pg_query/include/{catalog → postgres/catalog}/catalog.h +6 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/catversion.h +6 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/dependency.h +14 -19
- data/ext/pg_query/include/postgres/catalog/genbki.h +143 -0
- data/ext/pg_query/include/{catalog → postgres/catalog}/index.h +20 -5
- data/ext/pg_query/include/postgres/catalog/indexing.h +54 -0
- data/ext/pg_query/include/{catalog → postgres/catalog}/namespace.h +5 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/objectaccess.h +73 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/objectaddress.h +12 -7
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate.h +14 -10
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_aggregate_d.h +2 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am.h +4 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_am_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute.h +45 -26
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_attribute_d.h +19 -16
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid.h +7 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_authid_d.h +19 -9
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class.h +45 -15
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_class_d.h +31 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation.h +35 -8
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_collation_d.h +21 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint.h +39 -13
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_constraint_d.h +10 -4
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_control.h +13 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion.h +8 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_conversion_d.h +4 -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 +11 -7
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_depend_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger.h +9 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_event_trigger_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index.h +17 -7
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_index_d.h +20 -17
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language.h +10 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_language_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace.h +7 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_namespace_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass.h +8 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opclass_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator.h +21 -16
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_operator_d.h +37 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily.h +8 -4
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_opfamily_d.h +6 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table.h +20 -9
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_partitioned_table_d.h +2 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc.h +20 -11
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_proc_d.h +10 -8
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication.h +49 -6
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_publication_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin.h +6 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_replication_origin_d.h +5 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic.h +19 -12
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_d.h +2 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext.h +19 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_statistic_ext_d.h +7 -2
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform.h +8 -5
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_transform_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger.h +24 -8
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_trigger_d.h +4 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config.h +6 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_config_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict.h +8 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_dict_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser.h +6 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_parser_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template.h +6 -3
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_ts_template_d.h +3 -1
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type.h +56 -24
- data/ext/pg_query/include/{catalog → postgres/catalog}/pg_type_d.h +70 -31
- data/ext/pg_query/include/{catalog → postgres/catalog}/storage.h +9 -7
- data/ext/pg_query/include/{commands → postgres/commands}/async.h +4 -5
- data/ext/pg_query/include/{commands → postgres/commands}/dbcommands.h +3 -1
- data/ext/pg_query/include/{commands → postgres/commands}/defrem.h +12 -24
- data/ext/pg_query/include/{commands → postgres/commands}/event_trigger.h +2 -2
- 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 +6 -4
- data/ext/pg_query/include/{commands → postgres/commands}/trigger.h +36 -25
- data/ext/pg_query/include/{commands → postgres/commands}/user.h +10 -4
- data/ext/pg_query/include/{commands → postgres/commands}/vacuum.h +140 -47
- data/ext/pg_query/include/postgres/common/cryptohash.h +39 -0
- data/ext/pg_query/include/{common → postgres/common}/file_perm.h +4 -4
- 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 +2 -6
- data/ext/pg_query/include/{common → postgres/common}/kwlookup.h +2 -2
- data/ext/pg_query/include/postgres/common/pg_prng.h +61 -0
- data/ext/pg_query/include/{common → postgres/common}/relpath.h +21 -14
- 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/postgres/common/string.h +44 -0
- data/ext/pg_query/include/postgres/common/unicode_east_asian_fw_table.h +125 -0
- data/ext/pg_query/include/{common/unicode_combining_table.h → postgres/common/unicode_nonspacing_table.h} +138 -8
- 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 +50 -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 +98 -32
- data/ext/pg_query/include/{executor → postgres/executor}/functions.h +17 -3
- data/ext/pg_query/include/{executor → postgres/executor}/instrument.h +33 -16
- data/ext/pg_query/include/{executor → postgres/executor}/spi.h +42 -4
- 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} +33 -8
- data/ext/pg_query/include/postgres/foreign/fdwapi.h +294 -0
- data/ext/pg_query/include/{funcapi.h → postgres/funcapi.h} +22 -10
- 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 +12 -12
- data/ext/pg_query/include/postgres/kwlist_d.h +1119 -0
- data/ext/pg_query/include/postgres/lib/dshash.h +115 -0
- data/ext/pg_query/include/{lib → postgres/lib}/ilist.h +454 -22
- data/ext/pg_query/include/{lib → postgres/lib}/pairingheap.h +1 -1
- data/ext/pg_query/include/{lib → postgres/lib}/simplehash.h +158 -33
- data/ext/pg_query/include/postgres/lib/sort_template.h +432 -0
- data/ext/pg_query/include/{lib → postgres/lib}/stringinfo.h +3 -3
- data/ext/pg_query/include/{libpq → postgres/libpq}/auth.h +12 -4
- data/ext/pg_query/include/{libpq → postgres/libpq}/crypt.h +5 -4
- data/ext/pg_query/include/{libpq → postgres/libpq}/hba.h +54 -8
- data/ext/pg_query/include/{libpq → postgres/libpq}/libpq-be.h +45 -17
- data/ext/pg_query/include/{libpq → postgres/libpq}/libpq.h +31 -20
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqcomm.h +26 -71
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqformat.h +2 -2
- data/ext/pg_query/include/{libpq → postgres/libpq}/pqsignal.h +25 -13
- 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 +125 -25
- data/ext/pg_query/include/{mb → postgres/mb}/stringinfo_mb.h +1 -1
- data/ext/pg_query/include/{miscadmin.h → postgres/miscadmin.h} +96 -65
- data/ext/pg_query/include/{nodes → postgres/nodes}/bitmapset.h +11 -7
- data/ext/pg_query/include/{nodes → postgres/nodes}/execnodes.h +351 -103
- data/ext/pg_query/include/{nodes → postgres/nodes}/extensible.h +8 -4
- data/ext/pg_query/include/{nodes → postgres/nodes}/lockoptions.h +1 -1
- data/ext/pg_query/include/{nodes → postgres/nodes}/makefuncs.h +19 -6
- data/ext/pg_query/include/{nodes → postgres/nodes}/memnodes.h +11 -6
- 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 +100 -496
- 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 +678 -207
- data/ext/pg_query/include/{nodes → postgres/nodes}/pathnodes.h +1282 -454
- data/ext/pg_query/include/{nodes → postgres/nodes}/pg_list.h +103 -73
- data/ext/pg_query/include/{nodes → postgres/nodes}/plannodes.h +474 -133
- data/ext/pg_query/include/{nodes → postgres/nodes}/primnodes.h +754 -254
- data/ext/pg_query/include/{nodes → postgres/nodes}/print.h +1 -1
- data/ext/pg_query/include/postgres/nodes/queryjumble.h +86 -0
- 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/postgres/nodes/value.h +90 -0
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/cost.h +14 -5
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo.h +9 -7
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/geqo_gene.h +1 -1
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/optimizer.h +31 -28
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/paths.h +29 -12
- data/ext/pg_query/include/{optimizer → postgres/optimizer}/planmain.h +15 -17
- data/ext/pg_query/include/{parser → postgres/parser}/analyze.h +20 -5
- data/ext/pg_query/include/postgres/parser/kwlist.h +498 -0
- data/ext/pg_query/include/{parser → postgres/parser}/parse_agg.h +5 -8
- data/ext/pg_query/include/{parser → postgres/parser}/parse_coerce.h +6 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_expr.h +2 -3
- data/ext/pg_query/include/{parser → postgres/parser}/parse_func.h +2 -1
- data/ext/pg_query/include/{parser → postgres/parser}/parse_node.h +41 -11
- data/ext/pg_query/include/{parser → postgres/parser}/parse_oper.h +3 -5
- data/ext/pg_query/include/{parser → postgres/parser}/parse_relation.h +11 -5
- data/ext/pg_query/include/{parser → postgres/parser}/parse_type.h +4 -3
- data/ext/pg_query/include/postgres/parser/parser.h +68 -0
- 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 +2 -5
- data/ext/pg_query/include/{partitioning → postgres/partitioning}/partdefs.h +1 -1
- data/ext/pg_query/include/{pg_config.h → postgres/pg_config.h} +216 -228
- data/ext/pg_query/include/{pg_config_manual.h → postgres/pg_config_manual.h} +80 -58
- data/ext/pg_query/include/postgres/pg_config_os.h +8 -0
- data/ext/pg_query/include/{pg_getopt.h → postgres/pg_getopt.h} +6 -6
- data/ext/pg_query/include/{pg_trace.h → postgres/pg_trace.h} +1 -1
- data/ext/pg_query/include/postgres/pgstat.h +778 -0
- data/ext/pg_query/include/{pgtime.h → postgres/pgtime.h} +16 -6
- data/ext/pg_query/include/{pl_gram.h → postgres/pl_gram.h} +116 -116
- 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} +10 -10
- data/ext/pg_query/include/{pl_unreserved_kwlist.h → postgres/pl_unreserved_kwlist.h} +3 -3
- data/ext/pg_query/include/{pl_unreserved_kwlist_d.h → postgres/pl_unreserved_kwlist_d.h} +60 -60
- data/ext/pg_query/include/{plerrcodes.h → postgres/plerrcodes.h} +9 -1
- data/ext/pg_query/include/{plpgsql.h → postgres/plpgsql.h} +79 -86
- data/ext/pg_query/include/{port → postgres/port}/atomics/arch-arm.h +9 -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 +3 -3
- 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 +129 -16
- 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} +107 -111
- 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 +17 -20
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker.h +3 -2
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgworker_internals.h +2 -2
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/bgwriter.h +6 -6
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/interrupt.h +1 -1
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/pgarch.h +7 -10
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/postmaster.h +21 -17
- data/ext/pg_query/include/postgres/postmaster/startup.h +41 -0
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/syslogger.h +16 -11
- data/ext/pg_query/include/{postmaster → postgres/postmaster}/walwriter.h +5 -3
- data/ext/pg_query/include/{regex → postgres/regex}/regex.h +27 -22
- data/ext/pg_query/include/{replication → postgres/replication}/logicallauncher.h +8 -5
- data/ext/pg_query/include/postgres/replication/logicalproto.h +274 -0
- data/ext/pg_query/include/postgres/replication/logicalworker.h +32 -0
- data/ext/pg_query/include/{replication → postgres/replication}/origin.h +8 -8
- data/ext/pg_query/include/postgres/replication/reorderbuffer.h +753 -0
- data/ext/pg_query/include/{replication → postgres/replication}/slot.h +42 -12
- data/ext/pg_query/include/{replication → postgres/replication}/syncrep.h +6 -12
- data/ext/pg_query/include/{replication → postgres/replication}/walreceiver.h +158 -20
- data/ext/pg_query/include/{replication → postgres/replication}/walsender.h +20 -20
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/prs2lock.h +1 -1
- data/ext/pg_query/include/{rewrite → postgres/rewrite}/rewriteHandler.h +1 -6
- 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 +3 -3
- data/ext/pg_query/include/{storage → postgres/storage}/block.h +24 -37
- data/ext/pg_query/include/{storage → postgres/storage}/buf.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/bufmgr.h +196 -95
- data/ext/pg_query/include/{storage → postgres/storage}/bufpage.h +152 -101
- data/ext/pg_query/include/{storage → postgres/storage}/condition_variable.h +14 -3
- data/ext/pg_query/include/{storage → postgres/storage}/dsm.h +6 -6
- data/ext/pg_query/include/{storage → postgres/storage}/dsm_impl.h +6 -2
- data/ext/pg_query/include/{storage → postgres/storage}/fd.h +48 -14
- data/ext/pg_query/include/postgres/storage/fileset.h +40 -0
- data/ext/pg_query/include/{storage → postgres/storage}/ipc.h +5 -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 +96 -57
- data/ext/pg_query/include/{storage → postgres/storage}/large_object.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/latch.h +17 -13
- data/ext/pg_query/include/{storage → postgres/storage}/lmgr.h +7 -1
- data/ext/pg_query/include/{storage → postgres/storage}/lock.h +37 -25
- data/ext/pg_query/include/{storage → postgres/storage}/lockdefs.h +4 -4
- data/ext/pg_query/include/{storage → postgres/storage}/lwlock.h +21 -33
- data/ext/pg_query/include/{storage → postgres/storage}/lwlocknames.h +0 -1
- 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 +9 -7
- data/ext/pg_query/include/{storage → postgres/storage}/pmsignal.h +15 -4
- data/ext/pg_query/include/{storage → postgres/storage}/predicate.h +5 -5
- data/ext/pg_query/include/{storage → postgres/storage}/proc.h +200 -67
- data/ext/pg_query/include/postgres/storage/procarray.h +99 -0
- data/ext/pg_query/include/{storage → postgres/storage}/proclist_types.h +1 -1
- data/ext/pg_query/include/{storage → postgres/storage}/procsignal.h +5 -7
- data/ext/pg_query/include/postgres/storage/relfilelocator.h +99 -0
- data/ext/pg_query/include/{storage → postgres/storage}/s_lock.h +118 -298
- data/ext/pg_query/include/{storage → postgres/storage}/sharedfileset.h +3 -11
- data/ext/pg_query/include/{storage → postgres/storage}/shm_mq.h +5 -4
- 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 +5 -5
- data/ext/pg_query/include/{storage → postgres/storage}/sinvaladt.h +4 -2
- data/ext/pg_query/include/{storage → postgres/storage}/smgr.h +21 -17
- data/ext/pg_query/include/{storage → postgres/storage}/spin.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/standby.h +17 -9
- data/ext/pg_query/include/{storage → postgres/storage}/standbydefs.h +2 -2
- data/ext/pg_query/include/{storage → postgres/storage}/sync.h +9 -5
- data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtag.h +7 -2
- data/ext/pg_query/include/{tcop → postgres/tcop}/cmdtaglist.h +3 -2
- 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 -2
- data/ext/pg_query/include/{tcop → postgres/tcop}/pquery.h +7 -1
- data/ext/pg_query/include/{tcop → postgres/tcop}/tcopprot.h +19 -14
- data/ext/pg_query/include/{tcop → postgres/tcop}/utility.h +7 -3
- data/ext/pg_query/include/{tsearch → postgres/tsearch}/ts_cache.h +3 -5
- data/ext/pg_query/include/{utils → postgres/utils}/acl.h +37 -71
- data/ext/pg_query/include/{utils → postgres/utils}/aclchk_internal.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/array.h +26 -2
- data/ext/pg_query/include/postgres/utils/backend_progress.h +45 -0
- data/ext/pg_query/include/postgres/utils/backend_status.h +342 -0
- data/ext/pg_query/include/{utils → postgres/utils}/builtins.h +20 -11
- data/ext/pg_query/include/{utils → postgres/utils}/bytea.h +3 -2
- 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 +48 -27
- data/ext/pg_query/include/{utils → postgres/utils}/datum.h +9 -1
- data/ext/pg_query/include/{utils → postgres/utils}/dsa.h +5 -1
- data/ext/pg_query/include/{utils → postgres/utils}/elog.h +154 -48
- data/ext/pg_query/include/{utils → postgres/utils}/errcodes.h +2 -0
- 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 +13 -12
- data/ext/pg_query/include/{utils → postgres/utils}/fmgroids.h +1353 -696
- data/ext/pg_query/include/{utils → postgres/utils}/fmgrprotos.h +243 -18
- data/ext/pg_query/include/{utils → postgres/utils}/fmgrtab.h +6 -5
- data/ext/pg_query/include/{utils → postgres/utils}/guc.h +120 -121
- data/ext/pg_query/include/postgres/utils/guc_hooks.h +163 -0
- data/ext/pg_query/include/{utils → postgres/utils}/guc_tables.h +71 -21
- data/ext/pg_query/include/{utils → postgres/utils}/hsearch.h +15 -11
- data/ext/pg_query/include/{utils → postgres/utils}/inval.h +7 -3
- data/ext/pg_query/include/postgres/utils/logtape.h +77 -0
- data/ext/pg_query/include/{utils → postgres/utils}/lsyscache.h +16 -1
- data/ext/pg_query/include/{utils → postgres/utils}/memdebug.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/memutils.h +14 -53
- 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 +38 -9
- data/ext/pg_query/include/{utils → postgres/utils}/palloc.h +33 -4
- data/ext/pg_query/include/{utils → postgres/utils}/partcache.h +3 -2
- data/ext/pg_query/include/{utils → postgres/utils}/pg_locale.h +37 -21
- data/ext/pg_query/include/postgres/utils/pgstat_internal.h +814 -0
- data/ext/pg_query/include/{utils → postgres/utils}/plancache.h +6 -5
- data/ext/pg_query/include/{utils → postgres/utils}/portal.h +12 -1
- data/ext/pg_query/include/{utils → postgres/utils}/probes.h +59 -59
- 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/postgres/utils/regproc.h +39 -0
- data/ext/pg_query/include/{utils → postgres/utils}/rel.h +129 -61
- data/ext/pg_query/include/{utils → postgres/utils}/relcache.h +21 -14
- 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 +9 -1
- data/ext/pg_query/include/{utils → postgres/utils}/sharedtuplestore.h +1 -1
- data/ext/pg_query/include/{utils → postgres/utils}/snapmgr.h +38 -15
- data/ext/pg_query/include/{utils → postgres/utils}/snapshot.h +14 -1
- data/ext/pg_query/include/{utils → postgres/utils}/sortsupport.h +117 -2
- data/ext/pg_query/include/{utils → postgres/utils}/syscache.h +9 -1
- data/ext/pg_query/include/{utils → postgres/utils}/timeout.h +11 -4
- data/ext/pg_query/include/{utils → postgres/utils}/timestamp.h +46 -15
- data/ext/pg_query/include/{utils → postgres/utils}/tuplesort.h +209 -41
- data/ext/pg_query/include/{utils → postgres/utils}/tuplestore.h +2 -2
- data/ext/pg_query/include/{utils → postgres/utils}/typcache.h +24 -17
- data/ext/pg_query/include/{utils → postgres/utils}/varlena.h +17 -3
- data/ext/pg_query/include/postgres/utils/wait_event.h +294 -0
- data/ext/pg_query/include/{utils → postgres/utils}/xml.h +18 -8
- data/ext/pg_query/include/{postgres.h → postgres/varatt.h} +65 -471
- data/ext/pg_query/include/protobuf/pg_query.pb-c.h +7494 -6382
- data/ext/pg_query/include/protobuf/pg_query.pb.h +116922 -84792
- data/ext/pg_query/include/protobuf-c/protobuf-c.h +7 -3
- data/ext/pg_query/include/protobuf-c.h +7 -3
- data/ext/pg_query/pg_query.c +10 -1
- data/ext/pg_query/pg_query.pb-c.c +21026 -17002
- data/ext/pg_query/pg_query_deparse.c +1 -9896
- data/ext/pg_query/pg_query_fingerprint.c +162 -50
- data/ext/pg_query/pg_query_fingerprint.h +3 -1
- data/ext/pg_query/pg_query_internal.h +1 -1
- data/ext/pg_query/pg_query_json_plpgsql.c +56 -12
- data/ext/pg_query/pg_query_normalize.c +259 -64
- data/ext/pg_query/pg_query_outfuncs.h +1 -0
- data/ext/pg_query/pg_query_outfuncs_json.c +71 -16
- data/ext/pg_query/pg_query_outfuncs_protobuf.c +73 -12
- data/ext/pg_query/pg_query_parse.c +47 -5
- data/ext/pg_query/pg_query_parse_plpgsql.c +86 -21
- data/ext/pg_query/pg_query_readfuncs_protobuf.c +43 -8
- data/ext/pg_query/pg_query_ruby.c +6 -1
- data/ext/pg_query/pg_query_ruby_freebsd.sym +2 -0
- data/ext/pg_query/pg_query_scan.c +3 -2
- data/ext/pg_query/pg_query_split.c +6 -5
- data/ext/pg_query/postgres_deparse.c +11067 -0
- data/ext/pg_query/postgres_deparse.h +9 -0
- data/ext/pg_query/protobuf-c.c +34 -27
- data/ext/pg_query/src_backend_catalog_namespace.c +27 -10
- data/ext/pg_query/src_backend_catalog_pg_proc.c +4 -1
- data/ext/pg_query/src_backend_commands_define.c +11 -1
- data/ext/pg_query/src_backend_nodes_bitmapset.c +13 -70
- data/ext/pg_query/src_backend_nodes_copyfuncs.c +103 -5894
- data/ext/pg_query/src_backend_nodes_equalfuncs.c +102 -3830
- data/ext/pg_query/src_backend_nodes_extensible.c +6 -29
- data/ext/pg_query/src_backend_nodes_list.c +99 -12
- data/ext/pg_query/src_backend_nodes_makefuncs.c +99 -4
- data/ext/pg_query/src_backend_nodes_nodeFuncs.c +325 -131
- data/ext/pg_query/src_backend_nodes_nodes.c +38 -0
- data/ext/pg_query/src_backend_nodes_value.c +28 -19
- data/ext/pg_query/src_backend_parser_gram.c +36104 -32074
- data/ext/pg_query/src_backend_parser_parser.c +53 -8
- data/ext/pg_query/src_backend_parser_scan.c +4893 -3701
- data/ext/pg_query/src_backend_parser_scansup.c +4 -28
- data/ext/pg_query/src_backend_storage_ipc_ipc.c +13 -4
- data/ext/pg_query/src_backend_tcop_postgres.c +133 -105
- data/ext/pg_query/src_backend_utils_activity_pgstat_database.c +140 -0
- data/ext/pg_query/src_backend_utils_adt_datum.c +17 -7
- data/ext/pg_query/src_backend_utils_adt_expandeddatum.c +1 -1
- data/ext/pg_query/src_backend_utils_adt_format_type.c +6 -2
- data/ext/pg_query/src_backend_utils_adt_numutils.c +489 -0
- data/ext/pg_query/src_backend_utils_adt_ruleutils.c +187 -19
- data/ext/pg_query/src_backend_utils_error_assert.c +17 -18
- data/ext/pg_query/src_backend_utils_error_elog.c +513 -318
- data/ext/pg_query/src_backend_utils_fmgr_fmgr.c +44 -17
- data/ext/pg_query/src_backend_utils_init_globals.c +9 -6
- data/ext/pg_query/src_backend_utils_mb_mbutils.c +74 -131
- 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 +453 -314
- data/ext/pg_query/src_backend_utils_mmgr_generation.c +1039 -0
- data/ext/pg_query/src_backend_utils_mmgr_mcxt.c +549 -76
- 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 +420 -0
- data/ext/pg_query/src_common_keywords.c +15 -2
- data/ext/pg_query/src_common_kwlist_d.h +545 -498
- 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 +717 -113
- data/ext/pg_query/src_pl_plpgsql_src_pl_comp.c +49 -22
- data/ext/pg_query/src_pl_plpgsql_src_pl_funcs.c +3 -18
- data/ext/pg_query/src_pl_plpgsql_src_pl_gram.c +1136 -1195
- 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 +10 -10
- data/ext/pg_query/src_pl_plpgsql_src_pl_scanner.c +2 -2
- data/ext/pg_query/src_pl_plpgsql_src_pl_unreserved_kwlist_d.h +60 -60
- data/ext/pg_query/src_port_pg_bitutils.c +103 -40
- data/ext/pg_query/src_port_pgstrcasecmp.c +29 -1
- data/ext/pg_query/src_port_qsort.c +12 -224
- data/ext/pg_query/src_port_snprintf.c +51 -29
- data/ext/pg_query/src_port_strerror.c +9 -19
- data/ext/pg_query/src_port_strlcpy.c +79 -0
- data/lib/pg_query/deparse.rb +7 -1
- data/lib/pg_query/filter_columns.rb +7 -5
- data/lib/pg_query/fingerprint.rb +21 -9
- data/lib/pg_query/node.rb +18 -13
- data/lib/pg_query/param_refs.rb +1 -1
- data/lib/pg_query/parse.rb +141 -50
- data/lib/pg_query/pg_query_pb.rb +175 -3031
- data/lib/pg_query/treewalker.rb +26 -2
- data/lib/pg_query/truncate.rb +54 -8
- data/lib/pg_query/version.rb +1 -1
- data/lib/pg_query.rb +0 -1
- metadata +443 -380
- data/ext/pg_query/guc-file.c +0 -0
- data/ext/pg_query/include/access/rmgr.h +0 -35
- data/ext/pg_query/include/access/xloginsert.h +0 -64
- data/ext/pg_query/include/bootstrap/bootstrap.h +0 -62
- data/ext/pg_query/include/catalog/genbki.h +0 -64
- data/ext/pg_query/include/catalog/indexing.h +0 -366
- data/ext/pg_query/include/commands/variable.h +0 -38
- data/ext/pg_query/include/common/ip.h +0 -37
- data/ext/pg_query/include/common/string.h +0 -19
- data/ext/pg_query/include/getaddrinfo.h +0 -162
- data/ext/pg_query/include/kwlist_d.h +0 -1072
- data/ext/pg_query/include/nodes/value.h +0 -61
- data/ext/pg_query/include/parser/gram.h +0 -1067
- data/ext/pg_query/include/parser/kwlist.h +0 -477
- data/ext/pg_query/include/parser/parse_clause.h +0 -54
- data/ext/pg_query/include/parser/parse_collate.h +0 -27
- data/ext/pg_query/include/parser/parse_target.h +0 -46
- data/ext/pg_query/include/parser/parser.h +0 -41
- data/ext/pg_query/include/pg_config_os.h +0 -8
- data/ext/pg_query/include/pgstat.h +0 -1487
- data/ext/pg_query/include/portability/instr_time.h +0 -256
- data/ext/pg_query/include/postmaster/fork_process.h +0 -17
- data/ext/pg_query/include/replication/logicalproto.h +0 -110
- data/ext/pg_query/include/replication/logicalworker.h +0 -19
- data/ext/pg_query/include/replication/reorderbuffer.h +0 -467
- data/ext/pg_query/include/storage/relfilenode.h +0 -99
- data/ext/pg_query/include/utils/dynahash.h +0 -19
- 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/regproc.h +0 -28
- 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_libpq_pqcomm.c +0 -651
- data/ext/pg_query/src_backend_parser_parse_expr.c +0 -313
- data/ext/pg_query/src_backend_postmaster_postmaster.c +0 -2230
- data/ext/pg_query/src_backend_storage_lmgr_s_lock.c +0 -370
- data/ext/pg_query/src_backend_utils_hash_dynahash.c +0 -1086
- data/ext/pg_query/src_backend_utils_misc_guc.c +0 -1831
- data/ext/pg_query/src_common_string.c +0 -86
- data/ext/pg_query/src_port_erand48.c +0 -127
- data/ext/pg_query/src_port_pgsleep.c +0 -69
- data/ext/pg_query/src_port_random.c +0 -31
- data/ext/pg_query/src_port_strnlen.c +0 -39
- data/lib/pg_query/json_field_names.rb +0 -1402
- /data/ext/pg_query/include/{pg_config_ext.h → postgres/pg_config_ext.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,41 +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
|
-
|
|
297
|
-
#ifdef MEMORY_CONTEXT_CHECKING
|
|
298
|
-
static void AllocSetCheck(MemoryContext context);
|
|
299
|
-
#endif
|
|
300
|
-
|
|
301
|
-
/*
|
|
302
|
-
* This is the virtual function table for AllocSet contexts.
|
|
303
|
-
*/
|
|
304
|
-
static const MemoryContextMethods AllocSetMethods = {
|
|
305
|
-
AllocSetAlloc,
|
|
306
|
-
AllocSetFree,
|
|
307
|
-
AllocSetRealloc,
|
|
308
|
-
AllocSetReset,
|
|
309
|
-
AllocSetDelete,
|
|
310
|
-
AllocSetGetChunkSpace,
|
|
311
|
-
AllocSetIsEmpty,
|
|
312
|
-
AllocSetStats
|
|
313
|
-
#ifdef MEMORY_CONTEXT_CHECKING
|
|
314
|
-
,AllocSetCheck
|
|
315
|
-
#endif
|
|
316
|
-
};
|
|
317
|
-
|
|
318
281
|
|
|
319
282
|
/* ----------
|
|
320
283
|
* AllocSetFreeIndex -
|
|
@@ -338,7 +301,7 @@ AllocSetFreeIndex(Size size)
|
|
|
338
301
|
* or equivalently
|
|
339
302
|
* pg_leftmost_one_pos32(size - 1) - ALLOC_MINBITS + 1
|
|
340
303
|
*
|
|
341
|
-
* However,
|
|
304
|
+
* However, for platforms without intrinsic support, we duplicate the
|
|
342
305
|
* logic here, allowing an additional optimization. It's reasonable
|
|
343
306
|
* to assume that ALLOC_CHUNK_LIMIT fits in 16 bits, so we can unroll
|
|
344
307
|
* the byte-at-a-time loop in pg_leftmost_one_pos32 and just handle
|
|
@@ -348,14 +311,14 @@ AllocSetFreeIndex(Size size)
|
|
|
348
311
|
* much trouble.
|
|
349
312
|
*----------
|
|
350
313
|
*/
|
|
351
|
-
#ifdef
|
|
352
|
-
idx =
|
|
314
|
+
#ifdef HAVE_BITSCAN_REVERSE
|
|
315
|
+
idx = pg_leftmost_one_pos32((uint32) size - 1) - ALLOC_MINBITS + 1;
|
|
353
316
|
#else
|
|
354
317
|
uint32 t,
|
|
355
318
|
tsize;
|
|
356
319
|
|
|
357
320
|
/* Statically assert that we only have a 16-bit input value. */
|
|
358
|
-
|
|
321
|
+
StaticAssertDecl(ALLOC_CHUNK_LIMIT < (1 << 16),
|
|
359
322
|
"ALLOC_CHUNK_LIMIT must be less than 64kB");
|
|
360
323
|
|
|
361
324
|
tsize = size - 1;
|
|
@@ -406,18 +369,24 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
406
369
|
AllocSet set;
|
|
407
370
|
AllocBlock block;
|
|
408
371
|
|
|
409
|
-
/*
|
|
410
|
-
|
|
411
|
-
"sizeof(
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
"
|
|
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");
|
|
415
378
|
|
|
416
379
|
/*
|
|
417
380
|
* First, validate allocation parameters. Once these were regular runtime
|
|
418
|
-
*
|
|
419
|
-
* varies their parameters at runtime. We somewhat arbitrarily
|
|
420
|
-
* 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.
|
|
421
390
|
*/
|
|
422
391
|
Assert(initBlockSize == MAXALIGN(initBlockSize) &&
|
|
423
392
|
initBlockSize >= 1024);
|
|
@@ -428,6 +397,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
428
397
|
(minContextSize == MAXALIGN(minContextSize) &&
|
|
429
398
|
minContextSize >= 1024 &&
|
|
430
399
|
minContextSize <= maxBlockSize));
|
|
400
|
+
Assert(maxBlockSize <= MEMORYCHUNK_MAX_BLOCKOFFSET);
|
|
431
401
|
|
|
432
402
|
/*
|
|
433
403
|
* Check whether the parameters match either available freelist. We do
|
|
@@ -462,7 +432,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
462
432
|
/* Reinitialize its header, installing correct name and parent */
|
|
463
433
|
MemoryContextCreate((MemoryContext) set,
|
|
464
434
|
T_AllocSetContext,
|
|
465
|
-
|
|
435
|
+
MCTX_ASET_ID,
|
|
466
436
|
parent,
|
|
467
437
|
name);
|
|
468
438
|
|
|
@@ -536,15 +506,20 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
536
506
|
* requests that are all the maximum chunk size we will waste at most
|
|
537
507
|
* 1/8th of the allocated space.
|
|
538
508
|
*
|
|
539
|
-
* We have to have allocChunkLimit a power of two, because the requested
|
|
540
|
-
* and actually-allocated sizes of any chunk must be on the same side of
|
|
541
|
-
* the limit, else we get confused about whether the chunk is "big".
|
|
542
|
-
*
|
|
543
509
|
* Also, allocChunkLimit must not exceed ALLOCSET_SEPARATE_THRESHOLD.
|
|
544
510
|
*/
|
|
545
511
|
StaticAssertStmt(ALLOC_CHUNK_LIMIT == ALLOCSET_SEPARATE_THRESHOLD,
|
|
546
512
|
"ALLOC_CHUNK_LIMIT != ALLOCSET_SEPARATE_THRESHOLD");
|
|
547
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
|
+
*/
|
|
548
523
|
set->allocChunkLimit = ALLOC_CHUNK_LIMIT;
|
|
549
524
|
while ((Size) (set->allocChunkLimit + ALLOC_CHUNKHDRSZ) >
|
|
550
525
|
(Size) ((maxBlockSize - ALLOC_BLOCKHDRSZ) / ALLOC_CHUNK_FRACTION))
|
|
@@ -553,7 +528,7 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
553
528
|
/* Finally, do the type-independent part of context creation */
|
|
554
529
|
MemoryContextCreate((MemoryContext) set,
|
|
555
530
|
T_AllocSetContext,
|
|
556
|
-
|
|
531
|
+
MCTX_ASET_ID,
|
|
557
532
|
parent,
|
|
558
533
|
name);
|
|
559
534
|
|
|
@@ -574,21 +549,23 @@ AllocSetContextCreateInternal(MemoryContext parent,
|
|
|
574
549
|
* thrash malloc() when a context is repeatedly reset after small allocations,
|
|
575
550
|
* which is typical behavior for per-tuple contexts.
|
|
576
551
|
*/
|
|
577
|
-
|
|
552
|
+
void
|
|
578
553
|
AllocSetReset(MemoryContext context)
|
|
579
554
|
{
|
|
580
555
|
AllocSet set = (AllocSet) context;
|
|
581
556
|
AllocBlock block;
|
|
582
|
-
Size keepersize PG_USED_FOR_ASSERTS_ONLY
|
|
583
|
-
= set->keeper->endptr - ((char *) set);
|
|
557
|
+
Size keepersize PG_USED_FOR_ASSERTS_ONLY;
|
|
584
558
|
|
|
585
|
-
|
|
559
|
+
Assert(AllocSetIsValid(set));
|
|
586
560
|
|
|
587
561
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
588
562
|
/* Check for corruption and leaks before freeing */
|
|
589
563
|
AllocSetCheck(context);
|
|
590
564
|
#endif
|
|
591
565
|
|
|
566
|
+
/* Remember keeper block size for Assert below */
|
|
567
|
+
keepersize = set->keeper->endptr - ((char *) set);
|
|
568
|
+
|
|
592
569
|
/* Clear chunk freelists */
|
|
593
570
|
MemSetAligned(set->freelist, 0, sizeof(set->freelist));
|
|
594
571
|
|
|
@@ -642,21 +619,23 @@ AllocSetReset(MemoryContext context)
|
|
|
642
619
|
*
|
|
643
620
|
* Unlike AllocSetReset, this *must* free all resources of the set.
|
|
644
621
|
*/
|
|
645
|
-
|
|
622
|
+
void
|
|
646
623
|
AllocSetDelete(MemoryContext context)
|
|
647
624
|
{
|
|
648
625
|
AllocSet set = (AllocSet) context;
|
|
649
626
|
AllocBlock block = set->blocks;
|
|
650
|
-
Size keepersize PG_USED_FOR_ASSERTS_ONLY
|
|
651
|
-
= set->keeper->endptr - ((char *) set);
|
|
627
|
+
Size keepersize PG_USED_FOR_ASSERTS_ONLY;
|
|
652
628
|
|
|
653
|
-
|
|
629
|
+
Assert(AllocSetIsValid(set));
|
|
654
630
|
|
|
655
631
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
656
632
|
/* Check for corruption and leaks before freeing */
|
|
657
633
|
AllocSetCheck(context);
|
|
658
634
|
#endif
|
|
659
635
|
|
|
636
|
+
/* Remember keeper block size for Assert below */
|
|
637
|
+
keepersize = set->keeper->endptr - ((char *) set);
|
|
638
|
+
|
|
660
639
|
/*
|
|
661
640
|
* If the context is a candidate for a freelist, put it into that freelist
|
|
662
641
|
* instead of destroying it.
|
|
@@ -736,17 +715,17 @@ AllocSetDelete(MemoryContext context)
|
|
|
736
715
|
* is marked, as mcxt.c will set it to UNDEFINED. In some paths we will
|
|
737
716
|
* return space that is marked NOACCESS - AllocSetRealloc has to beware!
|
|
738
717
|
*/
|
|
739
|
-
|
|
718
|
+
void *
|
|
740
719
|
AllocSetAlloc(MemoryContext context, Size size)
|
|
741
720
|
{
|
|
742
721
|
AllocSet set = (AllocSet) context;
|
|
743
722
|
AllocBlock block;
|
|
744
|
-
|
|
723
|
+
MemoryChunk *chunk;
|
|
745
724
|
int fidx;
|
|
746
725
|
Size chunk_size;
|
|
747
726
|
Size blksize;
|
|
748
727
|
|
|
749
|
-
|
|
728
|
+
Assert(AllocSetIsValid(set));
|
|
750
729
|
|
|
751
730
|
/*
|
|
752
731
|
* If requested size exceeds maximum for chunks, allocate an entire block
|
|
@@ -754,7 +733,13 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
754
733
|
*/
|
|
755
734
|
if (size > set->allocChunkLimit)
|
|
756
735
|
{
|
|
736
|
+
#ifdef MEMORY_CONTEXT_CHECKING
|
|
737
|
+
/* ensure there's always space for the sentinel byte */
|
|
738
|
+
chunk_size = MAXALIGN(size + 1);
|
|
739
|
+
#else
|
|
757
740
|
chunk_size = MAXALIGN(size);
|
|
741
|
+
#endif
|
|
742
|
+
|
|
758
743
|
blksize = chunk_size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
|
|
759
744
|
block = (AllocBlock) malloc(blksize);
|
|
760
745
|
if (block == NULL)
|
|
@@ -765,18 +750,20 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
765
750
|
block->aset = set;
|
|
766
751
|
block->freeptr = block->endptr = ((char *) block) + blksize;
|
|
767
752
|
|
|
768
|
-
chunk = (
|
|
769
|
-
|
|
770
|
-
|
|
753
|
+
chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
|
|
754
|
+
|
|
755
|
+
/* mark the MemoryChunk as externally managed */
|
|
756
|
+
MemoryChunkSetHdrMaskExternal(chunk, MCTX_ASET_ID);
|
|
757
|
+
|
|
771
758
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
772
759
|
chunk->requested_size = size;
|
|
773
760
|
/* set mark to catch clobber of "unused" space */
|
|
774
|
-
|
|
775
|
-
|
|
761
|
+
Assert(size < chunk_size);
|
|
762
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
776
763
|
#endif
|
|
777
764
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
778
765
|
/* fill the allocated space with junk */
|
|
779
|
-
randomize_mem((char *)
|
|
766
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
780
767
|
#endif
|
|
781
768
|
|
|
782
769
|
/*
|
|
@@ -799,13 +786,13 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
799
786
|
}
|
|
800
787
|
|
|
801
788
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
802
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
789
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
803
790
|
chunk_size - size);
|
|
804
791
|
|
|
805
|
-
/* Disallow
|
|
806
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
792
|
+
/* Disallow access to the chunk header. */
|
|
793
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
807
794
|
|
|
808
|
-
return
|
|
795
|
+
return MemoryChunkGetPointer(chunk);
|
|
809
796
|
}
|
|
810
797
|
|
|
811
798
|
/*
|
|
@@ -813,42 +800,54 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
813
800
|
* corresponding free list to see if there is a free chunk we could reuse.
|
|
814
801
|
* If one is found, remove it from the free list, make it again a member
|
|
815
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.
|
|
816
809
|
*/
|
|
817
810
|
fidx = AllocSetFreeIndex(size);
|
|
818
811
|
chunk = set->freelist[fidx];
|
|
819
812
|
if (chunk != NULL)
|
|
820
813
|
{
|
|
821
|
-
|
|
814
|
+
AllocFreeListLink *link = GetFreeListLink(chunk);
|
|
815
|
+
|
|
816
|
+
/* Allow access to the chunk header. */
|
|
817
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
822
818
|
|
|
823
|
-
|
|
819
|
+
Assert(fidx == MemoryChunkGetValue(chunk));
|
|
824
820
|
|
|
825
|
-
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));
|
|
826
825
|
|
|
827
826
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
828
827
|
chunk->requested_size = size;
|
|
829
828
|
/* set mark to catch clobber of "unused" space */
|
|
830
|
-
if (size <
|
|
831
|
-
set_sentinel(
|
|
829
|
+
if (size < GetChunkSizeFromFreeListIdx(fidx))
|
|
830
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
832
831
|
#endif
|
|
833
832
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
834
833
|
/* fill the allocated space with junk */
|
|
835
|
-
randomize_mem((char *)
|
|
834
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
836
835
|
#endif
|
|
837
836
|
|
|
838
837
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
839
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
840
|
-
|
|
838
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
839
|
+
GetChunkSizeFromFreeListIdx(fidx) - size);
|
|
841
840
|
|
|
842
|
-
/* Disallow
|
|
843
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
841
|
+
/* Disallow access to the chunk header. */
|
|
842
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
844
843
|
|
|
845
|
-
return
|
|
844
|
+
return MemoryChunkGetPointer(chunk);
|
|
846
845
|
}
|
|
847
846
|
|
|
848
847
|
/*
|
|
849
848
|
* Choose the actual chunk size to allocate.
|
|
850
849
|
*/
|
|
851
|
-
chunk_size = (
|
|
850
|
+
chunk_size = GetChunkSizeFromFreeListIdx(fidx);
|
|
852
851
|
Assert(chunk_size >= size);
|
|
853
852
|
|
|
854
853
|
/*
|
|
@@ -875,6 +874,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
875
874
|
*/
|
|
876
875
|
while (availspace >= ((1 << ALLOC_MINBITS) + ALLOC_CHUNKHDRSZ))
|
|
877
876
|
{
|
|
877
|
+
AllocFreeListLink *link;
|
|
878
878
|
Size availchunk = availspace - ALLOC_CHUNKHDRSZ;
|
|
879
879
|
int a_fidx = AllocSetFreeIndex(availchunk);
|
|
880
880
|
|
|
@@ -883,29 +883,34 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
883
883
|
* freelist than the one we need to put this chunk on. The
|
|
884
884
|
* exception is when availchunk is exactly a power of 2.
|
|
885
885
|
*/
|
|
886
|
-
if (availchunk != (
|
|
886
|
+
if (availchunk != GetChunkSizeFromFreeListIdx(a_fidx))
|
|
887
887
|
{
|
|
888
888
|
a_fidx--;
|
|
889
889
|
Assert(a_fidx >= 0);
|
|
890
|
-
availchunk = (
|
|
890
|
+
availchunk = GetChunkSizeFromFreeListIdx(a_fidx);
|
|
891
891
|
}
|
|
892
892
|
|
|
893
|
-
chunk = (
|
|
893
|
+
chunk = (MemoryChunk *) (block->freeptr);
|
|
894
894
|
|
|
895
895
|
/* Prepare to initialize the chunk header. */
|
|
896
896
|
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
897
|
-
|
|
898
897
|
block->freeptr += (availchunk + ALLOC_CHUNKHDRSZ);
|
|
899
898
|
availspace -= (availchunk + ALLOC_CHUNKHDRSZ);
|
|
900
899
|
|
|
901
|
-
|
|
900
|
+
/* store the freelist index in the value field */
|
|
901
|
+
MemoryChunkSetHdrMask(chunk, block, a_fidx, MCTX_ASET_ID);
|
|
902
902
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
903
|
-
chunk->requested_size =
|
|
903
|
+
chunk->requested_size = InvalidAllocSize; /* mark it free */
|
|
904
904
|
#endif
|
|
905
|
-
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
|
+
|
|
906
912
|
set->freelist[a_fidx] = chunk;
|
|
907
913
|
}
|
|
908
|
-
|
|
909
914
|
/* Mark that we need to create a new block */
|
|
910
915
|
block = NULL;
|
|
911
916
|
}
|
|
@@ -973,7 +978,7 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
973
978
|
/*
|
|
974
979
|
* OK, do the allocation
|
|
975
980
|
*/
|
|
976
|
-
chunk = (
|
|
981
|
+
chunk = (MemoryChunk *) (block->freeptr);
|
|
977
982
|
|
|
978
983
|
/* Prepare to initialize the chunk header. */
|
|
979
984
|
VALGRIND_MAKE_MEM_UNDEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
@@ -981,69 +986,67 @@ AllocSetAlloc(MemoryContext context, Size size)
|
|
|
981
986
|
block->freeptr += (chunk_size + ALLOC_CHUNKHDRSZ);
|
|
982
987
|
Assert(block->freeptr <= block->endptr);
|
|
983
988
|
|
|
984
|
-
|
|
985
|
-
chunk
|
|
989
|
+
/* store the free list index in the value field */
|
|
990
|
+
MemoryChunkSetHdrMask(chunk, block, fidx, MCTX_ASET_ID);
|
|
991
|
+
|
|
986
992
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
987
993
|
chunk->requested_size = size;
|
|
988
994
|
/* set mark to catch clobber of "unused" space */
|
|
989
|
-
if (size <
|
|
990
|
-
set_sentinel(
|
|
995
|
+
if (size < chunk_size)
|
|
996
|
+
set_sentinel(MemoryChunkGetPointer(chunk), size);
|
|
991
997
|
#endif
|
|
992
998
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
993
999
|
/* fill the allocated space with junk */
|
|
994
|
-
randomize_mem((char *)
|
|
1000
|
+
randomize_mem((char *) MemoryChunkGetPointer(chunk), size);
|
|
995
1001
|
#endif
|
|
996
1002
|
|
|
997
1003
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
998
|
-
VALGRIND_MAKE_MEM_NOACCESS((char *)
|
|
1004
|
+
VALGRIND_MAKE_MEM_NOACCESS((char *) MemoryChunkGetPointer(chunk) + size,
|
|
999
1005
|
chunk_size - size);
|
|
1000
1006
|
|
|
1001
|
-
/* Disallow
|
|
1002
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1007
|
+
/* Disallow access to the chunk header. */
|
|
1008
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1003
1009
|
|
|
1004
|
-
return
|
|
1010
|
+
return MemoryChunkGetPointer(chunk);
|
|
1005
1011
|
}
|
|
1006
1012
|
|
|
1007
1013
|
/*
|
|
1008
1014
|
* AllocSetFree
|
|
1009
1015
|
* Frees allocated memory; memory is removed from the set.
|
|
1010
1016
|
*/
|
|
1011
|
-
|
|
1012
|
-
AllocSetFree(
|
|
1017
|
+
void
|
|
1018
|
+
AllocSetFree(void *pointer)
|
|
1013
1019
|
{
|
|
1014
|
-
AllocSet set
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
/* Allow access to private part of chunk header. */
|
|
1018
|
-
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
|
1020
|
+
AllocSet set;
|
|
1021
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1019
1022
|
|
|
1020
|
-
|
|
1021
|
-
|
|
1022
|
-
if (chunk->requested_size < chunk->size)
|
|
1023
|
-
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1024
|
-
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1025
|
-
set->header.name, chunk);
|
|
1026
|
-
#endif
|
|
1023
|
+
/* Allow access to the chunk header. */
|
|
1024
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1027
1025
|
|
|
1028
|
-
if (chunk
|
|
1026
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1029
1027
|
{
|
|
1030
|
-
/*
|
|
1031
|
-
|
|
1032
|
-
* blocks. Just unlink that block and return it to malloc().
|
|
1033
|
-
*/
|
|
1034
|
-
AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
|
|
1028
|
+
/* Release single-chunk block. */
|
|
1029
|
+
AllocBlock block = ExternalChunkGetBlock(chunk);
|
|
1035
1030
|
|
|
1036
1031
|
/*
|
|
1037
|
-
* Try to verify that we have a sane block pointer:
|
|
1038
|
-
* reference
|
|
1039
|
-
* 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.
|
|
1040
1034
|
*/
|
|
1041
|
-
if (block->
|
|
1042
|
-
block->freeptr != block->endptr ||
|
|
1043
|
-
block->freeptr != ((char *) block) +
|
|
1044
|
-
(chunk->size + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
|
|
1035
|
+
if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
|
|
1045
1036
|
elog(ERROR, "could not find block containing chunk %p", chunk);
|
|
1046
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
|
+
|
|
1047
1050
|
/* OK, remove block from aset's list and free it */
|
|
1048
1051
|
if (block->prev)
|
|
1049
1052
|
block->prev->next = block->next;
|
|
@@ -1052,7 +1055,7 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1052
1055
|
if (block->next)
|
|
1053
1056
|
block->next->prev = block->prev;
|
|
1054
1057
|
|
|
1055
|
-
|
|
1058
|
+
set->header.mem_allocated -= block->endptr - ((char *) block);
|
|
1056
1059
|
|
|
1057
1060
|
#ifdef CLOBBER_FREED_MEMORY
|
|
1058
1061
|
wipe_mem(block, block->freeptr - ((char *) block));
|
|
@@ -1061,20 +1064,48 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1061
1064
|
}
|
|
1062
1065
|
else
|
|
1063
1066
|
{
|
|
1064
|
-
|
|
1065
|
-
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;
|
|
1066
1079
|
|
|
1067
|
-
|
|
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
|
|
1068
1091
|
|
|
1069
1092
|
#ifdef CLOBBER_FREED_MEMORY
|
|
1070
|
-
wipe_mem(pointer,
|
|
1093
|
+
wipe_mem(pointer, GetChunkSizeFromFreeListIdx(fidx));
|
|
1071
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;
|
|
1072
1100
|
|
|
1073
1101
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1074
|
-
|
|
1075
|
-
|
|
1102
|
+
|
|
1103
|
+
/*
|
|
1104
|
+
* Reset requested_size to InvalidAllocSize in chunks that are on free
|
|
1105
|
+
* list.
|
|
1106
|
+
*/
|
|
1107
|
+
chunk->requested_size = InvalidAllocSize;
|
|
1076
1108
|
#endif
|
|
1077
|
-
set->freelist[fidx] = chunk;
|
|
1078
1109
|
}
|
|
1079
1110
|
}
|
|
1080
1111
|
|
|
@@ -1090,57 +1121,56 @@ AllocSetFree(MemoryContext context, void *pointer)
|
|
|
1090
1121
|
* (In principle, we could use VALGRIND_GET_VBITS() to rediscover the old
|
|
1091
1122
|
* request size.)
|
|
1092
1123
|
*/
|
|
1093
|
-
|
|
1094
|
-
AllocSetRealloc(
|
|
1124
|
+
void *
|
|
1125
|
+
AllocSetRealloc(void *pointer, Size size)
|
|
1095
1126
|
{
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOCCHUNK_PRIVATE_LEN);
|
|
1102
|
-
|
|
1103
|
-
oldsize = chunk->size;
|
|
1127
|
+
AllocBlock block;
|
|
1128
|
+
AllocSet set;
|
|
1129
|
+
MemoryChunk *chunk = PointerGetMemoryChunk(pointer);
|
|
1130
|
+
Size oldchksize;
|
|
1131
|
+
int fidx;
|
|
1104
1132
|
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
if (chunk->requested_size < oldsize)
|
|
1108
|
-
if (!sentinel_ok(pointer, chunk->requested_size))
|
|
1109
|
-
elog(WARNING, "detected write past chunk end in %s %p",
|
|
1110
|
-
set->header.name, chunk);
|
|
1111
|
-
#endif
|
|
1133
|
+
/* Allow access to the chunk header. */
|
|
1134
|
+
VALGRIND_MAKE_MEM_DEFINED(chunk, ALLOC_CHUNKHDRSZ);
|
|
1112
1135
|
|
|
1113
|
-
if (
|
|
1136
|
+
if (MemoryChunkIsExternal(chunk))
|
|
1114
1137
|
{
|
|
1115
1138
|
/*
|
|
1116
1139
|
* The chunk must have been allocated as a single-chunk block. Use
|
|
1117
1140
|
* realloc() to make the containing block bigger, or smaller, with
|
|
1118
1141
|
* minimum space wastage.
|
|
1119
1142
|
*/
|
|
1120
|
-
AllocBlock block = (AllocBlock) (((char *) chunk) - ALLOC_BLOCKHDRSZ);
|
|
1121
1143
|
Size chksize;
|
|
1122
1144
|
Size blksize;
|
|
1123
1145
|
Size oldblksize;
|
|
1124
1146
|
|
|
1147
|
+
block = ExternalChunkGetBlock(chunk);
|
|
1148
|
+
|
|
1125
1149
|
/*
|
|
1126
|
-
* Try to verify that we have a sane block pointer:
|
|
1127
|
-
* reference
|
|
1128
|
-
* 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.
|
|
1129
1152
|
*/
|
|
1130
|
-
if (block->
|
|
1131
|
-
block->freeptr != block->endptr ||
|
|
1132
|
-
block->freeptr != ((char *) block) +
|
|
1133
|
-
(oldsize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ))
|
|
1153
|
+
if (!AllocBlockIsValid(block) || block->freeptr != block->endptr)
|
|
1134
1154
|
elog(ERROR, "could not find block containing chunk %p", chunk);
|
|
1135
1155
|
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1141
|
-
|
|
1142
|
-
|
|
1143
|
-
|
|
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
|
|
1144
1174
|
|
|
1145
1175
|
/* Do the realloc */
|
|
1146
1176
|
blksize = chksize + ALLOC_BLOCKHDRSZ + ALLOC_CHUNKHDRSZ;
|
|
@@ -1149,77 +1179,109 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1149
1179
|
block = (AllocBlock) realloc(block, blksize);
|
|
1150
1180
|
if (block == NULL)
|
|
1151
1181
|
{
|
|
1152
|
-
/* Disallow
|
|
1153
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1182
|
+
/* Disallow access to the chunk header. */
|
|
1183
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1154
1184
|
return NULL;
|
|
1155
1185
|
}
|
|
1156
1186
|
|
|
1157
1187
|
/* updated separately, not to underflow when (oldblksize > blksize) */
|
|
1158
|
-
|
|
1159
|
-
|
|
1188
|
+
set->header.mem_allocated -= oldblksize;
|
|
1189
|
+
set->header.mem_allocated += blksize;
|
|
1160
1190
|
|
|
1161
1191
|
block->freeptr = block->endptr = ((char *) block) + blksize;
|
|
1162
1192
|
|
|
1163
1193
|
/* Update pointers since block has likely been moved */
|
|
1164
|
-
chunk = (
|
|
1165
|
-
pointer =
|
|
1194
|
+
chunk = (MemoryChunk *) (((char *) block) + ALLOC_BLOCKHDRSZ);
|
|
1195
|
+
pointer = MemoryChunkGetPointer(chunk);
|
|
1166
1196
|
if (block->prev)
|
|
1167
1197
|
block->prev->next = block;
|
|
1168
1198
|
else
|
|
1169
1199
|
set->blocks = block;
|
|
1170
1200
|
if (block->next)
|
|
1171
1201
|
block->next->prev = block;
|
|
1172
|
-
chunk->size = chksize;
|
|
1173
1202
|
|
|
1174
1203
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1175
1204
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
1176
|
-
|
|
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
|
+
*/
|
|
1177
1210
|
if (size > chunk->requested_size)
|
|
1178
1211
|
randomize_mem((char *) pointer + chunk->requested_size,
|
|
1179
1212
|
size - chunk->requested_size);
|
|
1180
|
-
#
|
|
1213
|
+
#else
|
|
1181
1214
|
|
|
1182
1215
|
/*
|
|
1183
|
-
*
|
|
1184
|
-
* part
|
|
1185
|
-
* 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.
|
|
1186
1222
|
*/
|
|
1187
1223
|
#ifdef USE_VALGRIND
|
|
1188
|
-
if (
|
|
1224
|
+
if (Min(size, oldchksize) > chunk->requested_size)
|
|
1189
1225
|
VALGRIND_MAKE_MEM_UNDEFINED((char *) pointer + chunk->requested_size,
|
|
1190
|
-
|
|
1226
|
+
Min(size, oldchksize) - chunk->requested_size);
|
|
1227
|
+
#endif
|
|
1191
1228
|
#endif
|
|
1192
1229
|
|
|
1193
1230
|
chunk->requested_size = size;
|
|
1194
|
-
|
|
1195
1231
|
/* set mark to catch clobber of "unused" space */
|
|
1196
|
-
|
|
1197
|
-
|
|
1232
|
+
Assert(size < chksize);
|
|
1233
|
+
set_sentinel(pointer, size);
|
|
1198
1234
|
#else /* !MEMORY_CONTEXT_CHECKING */
|
|
1199
1235
|
|
|
1200
1236
|
/*
|
|
1201
|
-
* We
|
|
1202
|
-
*
|
|
1203
|
-
*
|
|
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.
|
|
1204
1243
|
*/
|
|
1205
|
-
VALGRIND_MAKE_MEM_DEFINED(pointer,
|
|
1244
|
+
VALGRIND_MAKE_MEM_DEFINED(pointer, Min(size, oldchksize));
|
|
1206
1245
|
#endif
|
|
1207
1246
|
|
|
1208
1247
|
/* Ensure any padding bytes are marked NOACCESS. */
|
|
1209
1248
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size, chksize - size);
|
|
1210
1249
|
|
|
1211
|
-
/* Disallow
|
|
1212
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1250
|
+
/* Disallow access to the chunk header . */
|
|
1251
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1213
1252
|
|
|
1214
1253
|
return pointer;
|
|
1215
1254
|
}
|
|
1216
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
|
+
|
|
1217
1279
|
/*
|
|
1218
1280
|
* Chunk sizes are aligned to power of 2 in AllocSetAlloc(). Maybe the
|
|
1219
1281
|
* allocated area already is >= the new size. (In particular, we will
|
|
1220
1282
|
* fall out here if the requested size is a decrease.)
|
|
1221
1283
|
*/
|
|
1222
|
-
|
|
1284
|
+
if (oldchksize >= size)
|
|
1223
1285
|
{
|
|
1224
1286
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1225
1287
|
Size oldrequest = chunk->requested_size;
|
|
@@ -1242,10 +1304,10 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1242
1304
|
size - oldrequest);
|
|
1243
1305
|
else
|
|
1244
1306
|
VALGRIND_MAKE_MEM_NOACCESS((char *) pointer + size,
|
|
1245
|
-
|
|
1307
|
+
oldchksize - size);
|
|
1246
1308
|
|
|
1247
1309
|
/* set mark to catch clobber of "unused" space */
|
|
1248
|
-
if (size <
|
|
1310
|
+
if (size < oldchksize)
|
|
1249
1311
|
set_sentinel(pointer, size);
|
|
1250
1312
|
#else /* !MEMORY_CONTEXT_CHECKING */
|
|
1251
1313
|
|
|
@@ -1254,12 +1316,12 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1254
1316
|
* the old request or shrinking it, so we conservatively mark the
|
|
1255
1317
|
* entire new allocation DEFINED.
|
|
1256
1318
|
*/
|
|
1257
|
-
VALGRIND_MAKE_MEM_NOACCESS(pointer,
|
|
1319
|
+
VALGRIND_MAKE_MEM_NOACCESS(pointer, oldchksize);
|
|
1258
1320
|
VALGRIND_MAKE_MEM_DEFINED(pointer, size);
|
|
1259
1321
|
#endif
|
|
1260
1322
|
|
|
1261
|
-
/* Disallow
|
|
1262
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1323
|
+
/* Disallow access to the chunk header. */
|
|
1324
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1263
1325
|
|
|
1264
1326
|
return pointer;
|
|
1265
1327
|
}
|
|
@@ -1277,6 +1339,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1277
1339
|
* memory indefinitely. See pgsql-hackers archives for 2007-08-11.)
|
|
1278
1340
|
*/
|
|
1279
1341
|
AllocPointer newPointer;
|
|
1342
|
+
Size oldsize;
|
|
1280
1343
|
|
|
1281
1344
|
/* allocate new chunk */
|
|
1282
1345
|
newPointer = AllocSetAlloc((MemoryContext) set, size);
|
|
@@ -1284,8 +1347,8 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1284
1347
|
/* leave immediately if request was not completed */
|
|
1285
1348
|
if (newPointer == NULL)
|
|
1286
1349
|
{
|
|
1287
|
-
/* Disallow
|
|
1288
|
-
VALGRIND_MAKE_MEM_NOACCESS(chunk,
|
|
1350
|
+
/* Disallow access to the chunk header. */
|
|
1351
|
+
VALGRIND_MAKE_MEM_NOACCESS(chunk, ALLOC_CHUNKHDRSZ);
|
|
1289
1352
|
return NULL;
|
|
1290
1353
|
}
|
|
1291
1354
|
|
|
@@ -1301,6 +1364,7 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1301
1364
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
1302
1365
|
oldsize = chunk->requested_size;
|
|
1303
1366
|
#else
|
|
1367
|
+
oldsize = oldchksize;
|
|
1304
1368
|
VALGRIND_MAKE_MEM_DEFINED(pointer, oldsize);
|
|
1305
1369
|
#endif
|
|
1306
1370
|
|
|
@@ -1308,36 +1372,84 @@ AllocSetRealloc(MemoryContext context, void *pointer, Size size)
|
|
|
1308
1372
|
memcpy(newPointer, pointer, oldsize);
|
|
1309
1373
|
|
|
1310
1374
|
/* free old chunk */
|
|
1311
|
-
AllocSetFree(
|
|
1375
|
+
AllocSetFree(pointer);
|
|
1312
1376
|
|
|
1313
1377
|
return newPointer;
|
|
1314
1378
|
}
|
|
1315
1379
|
}
|
|
1316
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
|
+
|
|
1317
1409
|
/*
|
|
1318
1410
|
* AllocSetGetChunkSpace
|
|
1319
1411
|
* Given a currently-allocated chunk, determine the total space
|
|
1320
1412
|
* it occupies (including all memory-allocation overhead).
|
|
1321
1413
|
*/
|
|
1322
|
-
|
|
1323
|
-
AllocSetGetChunkSpace(
|
|
1414
|
+
Size
|
|
1415
|
+
AllocSetGetChunkSpace(void *pointer)
|
|
1324
1416
|
{
|
|
1325
|
-
|
|
1326
|
-
|
|
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);
|
|
1327
1426
|
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
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;
|
|
1332
1442
|
}
|
|
1333
1443
|
|
|
1334
1444
|
/*
|
|
1335
1445
|
* AllocSetIsEmpty
|
|
1336
1446
|
* Is an allocset empty of any allocated space?
|
|
1337
1447
|
*/
|
|
1338
|
-
|
|
1448
|
+
bool
|
|
1339
1449
|
AllocSetIsEmpty(MemoryContext context)
|
|
1340
1450
|
{
|
|
1451
|
+
Assert(AllocSetIsValid(context));
|
|
1452
|
+
|
|
1341
1453
|
/*
|
|
1342
1454
|
* For now, we say "empty" only if the context is new or just reset. We
|
|
1343
1455
|
* could examine the freelists to determine if all space has been freed,
|
|
@@ -1356,11 +1468,12 @@ AllocSetIsEmpty(MemoryContext context)
|
|
|
1356
1468
|
* printfunc: if not NULL, pass a human-readable stats string to this.
|
|
1357
1469
|
* passthru: pass this pointer through to printfunc.
|
|
1358
1470
|
* totals: if not NULL, add stats about this context into *totals.
|
|
1471
|
+
* print_to_stderr: print stats to stderr if true, elog otherwise.
|
|
1359
1472
|
*/
|
|
1360
|
-
|
|
1473
|
+
void
|
|
1361
1474
|
AllocSetStats(MemoryContext context,
|
|
1362
1475
|
MemoryStatsPrintFunc printfunc, void *passthru,
|
|
1363
|
-
MemoryContextCounters *totals)
|
|
1476
|
+
MemoryContextCounters *totals, bool print_to_stderr)
|
|
1364
1477
|
{
|
|
1365
1478
|
AllocSet set = (AllocSet) context;
|
|
1366
1479
|
Size nblocks = 0;
|
|
@@ -1370,6 +1483,8 @@ AllocSetStats(MemoryContext context,
|
|
|
1370
1483
|
AllocBlock block;
|
|
1371
1484
|
int fidx;
|
|
1372
1485
|
|
|
1486
|
+
Assert(AllocSetIsValid(set));
|
|
1487
|
+
|
|
1373
1488
|
/* Include context header in totalspace */
|
|
1374
1489
|
totalspace = MAXALIGN(sizeof(AllocSetContext));
|
|
1375
1490
|
|
|
@@ -1381,13 +1496,24 @@ AllocSetStats(MemoryContext context,
|
|
|
1381
1496
|
}
|
|
1382
1497
|
for (fidx = 0; fidx < ALLOCSET_NUM_FREELISTS; fidx++)
|
|
1383
1498
|
{
|
|
1384
|
-
|
|
1499
|
+
Size chksz = GetChunkSizeFromFreeListIdx(fidx);
|
|
1500
|
+
MemoryChunk *chunk = set->freelist[fidx];
|
|
1385
1501
|
|
|
1386
|
-
|
|
1387
|
-
chunk = (AllocChunk) chunk->aset)
|
|
1502
|
+
while (chunk != NULL)
|
|
1388
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
|
+
|
|
1389
1511
|
freechunks++;
|
|
1390
|
-
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));
|
|
1391
1517
|
}
|
|
1392
1518
|
}
|
|
1393
1519
|
|
|
@@ -1396,10 +1522,10 @@ AllocSetStats(MemoryContext context,
|
|
|
1396
1522
|
char stats_string[200];
|
|
1397
1523
|
|
|
1398
1524
|
snprintf(stats_string, sizeof(stats_string),
|
|
1399
|
-
"%zu total in %
|
|
1525
|
+
"%zu total in %zu blocks; %zu free (%zu chunks); %zu used",
|
|
1400
1526
|
totalspace, nblocks, freespace, freechunks,
|
|
1401
1527
|
totalspace - freespace);
|
|
1402
|
-
printfunc(context, passthru, stats_string);
|
|
1528
|
+
printfunc(context, passthru, stats_string, print_to_stderr);
|
|
1403
1529
|
}
|
|
1404
1530
|
|
|
1405
1531
|
if (totals)
|
|
@@ -1422,7 +1548,7 @@ AllocSetStats(MemoryContext context,
|
|
|
1422
1548
|
* find yourself in an infinite loop when trouble occurs, because this
|
|
1423
1549
|
* routine will be entered again when elog cleanup tries to release memory!
|
|
1424
1550
|
*/
|
|
1425
|
-
|
|
1551
|
+
void
|
|
1426
1552
|
AllocSetCheck(MemoryContext context)
|
|
1427
1553
|
{
|
|
1428
1554
|
AllocSet set = (AllocSet) context;
|
|
@@ -1439,6 +1565,7 @@ AllocSetCheck(MemoryContext context)
|
|
|
1439
1565
|
long blk_used = block->freeptr - bpoz;
|
|
1440
1566
|
long blk_data = 0;
|
|
1441
1567
|
long nchunks = 0;
|
|
1568
|
+
bool has_external_chunk = false;
|
|
1442
1569
|
|
|
1443
1570
|
if (set->keeper == block)
|
|
1444
1571
|
total_allocated += block->endptr - ((char *) set);
|
|
@@ -1470,56 +1597,64 @@ AllocSetCheck(MemoryContext context)
|
|
|
1470
1597
|
*/
|
|
1471
1598
|
while (bpoz < block->freeptr)
|
|
1472
1599
|
{
|
|
1473
|
-
|
|
1600
|
+
MemoryChunk *chunk = (MemoryChunk *) bpoz;
|
|
1474
1601
|
Size chsize,
|
|
1475
1602
|
dsize;
|
|
1476
1603
|
|
|
1477
|
-
/* Allow access to
|
|
1478
|
-
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 */
|
|
1479
1626
|
|
|
1480
|
-
|
|
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
|
+
}
|
|
1481
1635
|
dsize = chunk->requested_size; /* real data */
|
|
1482
1636
|
|
|
1483
|
-
/*
|
|
1484
|
-
|
|
1485
|
-
*/
|
|
1486
|
-
if (dsize > chsize)
|
|
1637
|
+
/* an allocated chunk's requested size must be <= the chsize */
|
|
1638
|
+
if (dsize != InvalidAllocSize && dsize > chsize)
|
|
1487
1639
|
elog(WARNING, "problem in alloc set %s: req size > alloc size for chunk %p in block %p",
|
|
1488
1640
|
name, chunk, block);
|
|
1641
|
+
|
|
1642
|
+
/* chsize must not be smaller than the first freelist's size */
|
|
1489
1643
|
if (chsize < (1 << ALLOC_MINBITS))
|
|
1490
1644
|
elog(WARNING, "problem in alloc set %s: bad size %zu for chunk %p in block %p",
|
|
1491
1645
|
name, chsize, chunk, block);
|
|
1492
1646
|
|
|
1493
|
-
/* single-chunk block? */
|
|
1494
|
-
if (chsize > set->allocChunkLimit &&
|
|
1495
|
-
chsize + ALLOC_CHUNKHDRSZ != blk_used)
|
|
1496
|
-
elog(WARNING, "problem in alloc set %s: bad single-chunk %p in block %p",
|
|
1497
|
-
name, chunk, block);
|
|
1498
|
-
|
|
1499
|
-
/*
|
|
1500
|
-
* If chunk is allocated, check for correct aset pointer. (If it's
|
|
1501
|
-
* free, the aset is the freelist pointer, which we can't check as
|
|
1502
|
-
* easily...) Note this is an incomplete test, since palloc(0)
|
|
1503
|
-
* produces an allocated chunk with requested_size == 0.
|
|
1504
|
-
*/
|
|
1505
|
-
if (dsize > 0 && chunk->aset != (void *) set)
|
|
1506
|
-
elog(WARNING, "problem in alloc set %s: bogus aset link in block %p, chunk %p",
|
|
1507
|
-
name, block, chunk);
|
|
1508
|
-
|
|
1509
1647
|
/*
|
|
1510
1648
|
* Check for overwrite of padding space in an allocated chunk.
|
|
1511
1649
|
*/
|
|
1512
|
-
if (
|
|
1650
|
+
if (dsize != InvalidAllocSize && dsize < chsize &&
|
|
1513
1651
|
!sentinel_ok(chunk, ALLOC_CHUNKHDRSZ + dsize))
|
|
1514
1652
|
elog(WARNING, "problem in alloc set %s: detected write past chunk end in block %p, chunk %p",
|
|
1515
1653
|
name, block, chunk);
|
|
1516
1654
|
|
|
1517
|
-
/*
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
*/
|
|
1521
|
-
if (chunk->aset == (void *) set)
|
|
1522
|
-
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);
|
|
1523
1658
|
|
|
1524
1659
|
blk_data += chsize;
|
|
1525
1660
|
nchunks++;
|
|
@@ -1530,6 +1665,10 @@ AllocSetCheck(MemoryContext context)
|
|
|
1530
1665
|
if ((blk_data + (nchunks * ALLOC_CHUNKHDRSZ)) != blk_used)
|
|
1531
1666
|
elog(WARNING, "problem in alloc set %s: found inconsistent memory block %p",
|
|
1532
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);
|
|
1533
1672
|
}
|
|
1534
1673
|
|
|
1535
1674
|
Assert(total_allocated == context->mem_allocated);
|