PostgreSQL Source Code: src/backend/utils/mmgr/mcxt.c Source File (original) (raw)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
23
35
36
37static void BogusFree(void *pointer);
38static void *BogusRealloc(void *pointer, Size size, int flags);
41
42
43
44
45#define BOGUS_MCTX(id) \
46 [id].free_p = BogusFree, \
47 [id].realloc = BogusRealloc, \
48 [id].get_chunk_context = BogusGetChunkContext, \
49 [id].get_chunk_space = BogusGetChunkSpace
50
52
62#ifdef MEMORY_CONTEXT_CHECKING
64#endif
65
66
76#ifdef MEMORY_CONTEXT_CHECKING
78#endif
79
80
90#ifdef MEMORY_CONTEXT_CHECKING
92#endif
93
94
104#ifdef MEMORY_CONTEXT_CHECKING
106#endif
107
108
118#ifdef MEMORY_CONTEXT_CHECKING
120#endif
121
122
123
124
125
126
127
128
140};
141
142#undef BOGUS_MCTX
143
144
145
146
147
149{
154
155
156
157
158
160
161
162
163
164
172
173
176
180 int max_level, int max_children,
183 int *num_contexts);
185 const char *stats_string,
186 bool print_to_stderr);
191 int num_contexts, dsa_area *area,
192 int max_levels);
194 int *stats_count,
195 bool summary);
200
201
202
203
204
205
206#define AssertNotInCriticalSection(context) \
207 Assert(CritSectionCount == 0 || (context)->allowInCritSection)
208
209
210
211
212
213#define MCXT_METHOD(pointer, method) \
214 mcxt_methods[GetMemoryChunkMethodID(pointer)].method
215
216
217
218
219
220
223{
225
226
227
228
229
230
232
233
235
236 header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
237
238
240
242}
243
244
245
246
247
248
249
252{
254
255
257
258 header = *((const uint64 *) ((const char *) pointer - sizeof(uint64)));
259
260
262
263 return header;
264}
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
289{
290
293
294
295
296
297
298
299
300
302 {
304 if (curr == top)
305 return NULL;
306 }
308}
309
310
311
312
313
314
315
316static void
318{
319 elog(ERROR, "pfree called with invalid pointer %p (header 0x%016" PRIx64 ")",
321}
322
323static void *
325{
326 elog(ERROR, "repalloc called with invalid pointer %p (header 0x%016" PRIx64 ")",
328 return NULL;
329}
330
333{
334 elog(ERROR, "GetMemoryChunkContext called with invalid pointer %p (header 0x%016" PRIx64 ")",
336 return NULL;
337}
338
341{
342 elog(ERROR, "GetMemoryChunkSpace called with invalid pointer %p (header 0x%016" PRIx64 ")",
344 return 0;
345}
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369void
371{
373
374
375
376
378 "TopMemoryContext",
380
381
382
383
384
386
387
388
389
390
391
392
393
394
395
396
397
398
399
401 "ErrorContext",
402 8 * 1024,
403 8 * 1024,
404 8 * 1024);
406}
407
408
409
410
411
412
413void
415{
417
418
421
422
425}
426
427
428
429
430
431
432void
434{
436
437
439 {
441
442
443
444
445
446
447
448
449
454 }
455}
456
457
458
459
460
461
462
463void
465{
467
469 curr != NULL;
471 {
473 }
474}
475
476
477
478
479
480
481
482
483
484void
486{
488
490
491
492
493
494
495
496
497
498
499 curr = context;
500 for (;;)
501 {
503
504
507
508
509
510
511
512 parent = curr->parent;
514
515 if (curr == context)
516 break;
517 curr = parent;
518 }
519}
520
521
522
523
524
525
526static void
528{
530
532
534
536
537
538
539
540
541
542
544
545
546
547
548
549
551
552
553
554
555
556
557 context->ident = NULL;
558
560
562}
563
564
565
566
567
568
569void
571{
573
574
575
576
577
580}
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598void
601{
603
604
607
608 context->isReset = false;
609}
610
611
612
613
614
615static void
617{
619
620
621
622
623
624
625 while ((cb = context->reset_cbs) != NULL)
626 {
629 }
630}
631
632
633
634
635
636
637
638
639
640
641
642void
644{
646 context->ident = id;
647}
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667void
669{
671 Assert(context != new_parent);
672
673
674 if (new_parent == context->parent)
675 return;
676
677
679 {
681
684 else
685 {
688 }
689
692 }
693
694
695 if (new_parent)
696 {
698 context->parent = new_parent;
704 }
705 else
706 {
707 context->parent = NULL;
710 }
711}
712
713
714
715
716
717
718
719
720
721
722
723
724void
726{
728
730}
731
732
733
734
735
736
739{
740 return MCXT_METHOD(pointer, get_chunk_context) (pointer);
741}
742
743
744
745
746
747
748
749
750
753{
754 return MCXT_METHOD(pointer, get_chunk_space) (pointer);
755}
756
757
758
759
760
763{
765
766 return context->parent;
767}
768
769
770
771
772
773bool
775{
777
778
779
780
781
783 return false;
784
786}
787
788
789
790
791
794{
796
798
799 if (recurse)
800 {
802 curr != NULL;
804 {
805 total += curr->mem_allocated;
806 }
807 }
808
809 return total;
810}
811
812
813
814
815
816void
819{
821
822 memset(consumed, 0, sizeof(*consumed));
823
824
825 context->methods->stats(context, NULL, NULL, consumed, false);
826
827
829 curr != NULL;
831 {
832 curr->methods->stats(curr, NULL, NULL, consumed, false);
833 }
834}
835
836
837
838
839
840
841
842
843
844void
846{
847
849}
850
851
852
853
854
855
856
857
858
859void
861 int max_level, int max_children,
862 bool print_to_stderr)
863{
865 int num_contexts;
867
868 memset(&grand_totals, 0, sizeof(grand_totals));
869
870 if (print_to_stderr)
872 else
874
875
877 &grand_totals, print_location, &num_contexts);
878
879 if (print_to_stderr)
881 "Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used\n",
885 else
886 {
887
888
889
890
891
892
893
894
895
896
900 errmsg_internal("Grand total: %zu bytes in %zu blocks; %zu free (%zu chunks); %zu used",
904 }
905}
906
907
908
909
910
911
912
913
914
915static void
917 int max_level, int max_children,
920{
922 int ichild;
923
925
926
927 switch (print_location)
928 {
932 &level,
933 totals, true);
934 break;
935
939 &level,
940 totals, false);
941 break;
942
944
945
946
947
948
949
950
952 NULL,
953 NULL,
954 totals, false);
955 break;
956 }
957
958
959 *num_contexts = *num_contexts + 1;
960
961
962
963
964
965
966
967
968
970 ichild = 0;
972 {
973 for (; child != NULL && ichild < max_children;
974 child = child->nextchild, ichild++)
975 {
977 max_level, max_children,
978 totals,
979 print_location, num_contexts);
980 }
981 }
982
983 if (child != NULL)
984 {
985
987
988 memset(&local_totals, 0, sizeof(local_totals));
989
990 ichild = 0;
991 while (child != NULL)
992 {
993 child->methods->stats(child, NULL, NULL, &local_totals, false);
994 ichild++;
996 }
997
998
999
1000
1001
1002 *num_contexts = *num_contexts + ichild;
1003
1005 {
1006 for (int i = 0; i < level; i++)
1009 "%d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used\n",
1010 ichild,
1016 }
1021 errmsg_internal("level: %d; %d more child contexts containing %zu total in %zu blocks; %zu free (%zu chunks); %zu used",
1022 level,
1023 ichild,
1029
1030 if (totals)
1031 {
1036 }
1037 }
1038}
1039
1040
1041
1042
1043
1044
1045
1046
1047static void
1049 const char *stats_string,
1050 bool print_to_stderr)
1051{
1052 int level = *(int *) passthru;
1053 const char *name = context->name;
1055 char truncated_ident[110];
1056 int i;
1057
1058
1059
1060
1061
1062
1063 if (ident && strcmp(name, "dynahash") == 0)
1064 {
1067 }
1068
1069 truncated_ident[0] = '\0';
1070
1072 {
1073
1074
1075
1076
1077
1078
1079 int idlen = strlen(ident);
1080 bool truncated = false;
1081
1082 strcpy(truncated_ident, ": ");
1083 i = strlen(truncated_ident);
1084
1085 if (idlen > 100)
1086 {
1088 truncated = true;
1089 }
1090
1091 while (idlen-- > 0)
1092 {
1093 unsigned char c = *ident++;
1094
1095 if (c < ' ')
1096 c = ' ';
1097 truncated_ident[i++] = c;
1098 }
1099 truncated_ident[i] = '\0';
1100
1101 if (truncated)
1102 strcat(truncated_ident, "...");
1103 }
1104
1105 if (print_to_stderr)
1106 {
1107 for (i = 1; i < level; i++)
1109 fprintf(stderr, "%s: %s%s\n", name, stats_string, truncated_ident);
1110 }
1111 else
1116 level, name, stats_string, truncated_ident)));
1117}
1118
1119
1120
1121
1122
1123
1124
1125#ifdef MEMORY_CONTEXT_CHECKING
1126void
1128{
1130 context->methods->check(context);
1131
1133 curr != NULL;
1135 {
1137 curr->methods->check(curr);
1138 }
1139}
1140#endif
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174void
1179 const char *name)
1180{
1181
1183
1184
1186 Assert(node != parent);
1187
1188
1189 node->type = tag;
1192 node->parent = parent;
1197 node->ident = NULL;
1199
1200
1201 if (parent)
1202 {
1207
1209 }
1210 else
1211 {
1214 }
1215
1217}
1218
1219
1220
1221
1222
1223
1224
1225void *
1227{
1229 {
1233 (errcode(ERRCODE_OUT_OF_MEMORY),
1234 errmsg("out of memory"),
1235 errdetail("Failed on request of size %zu in memory context \"%s\".",
1236 size, context->name)));
1237 }
1238 return NULL;
1239}
1240
1241
1242
1243
1244
1245
1246void
1248{
1249 elog(ERROR, "invalid memory alloc request size %zu", size);
1250}
1251
1252
1253
1254
1255
1256
1257
1258
1259void *
1261{
1262 void *ret;
1263
1266
1267 context->isReset = false;
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279 ret = context->methods->alloc(context, size, 0);
1280
1282
1283 return ret;
1284}
1285
1286
1287
1288
1289
1290
1291
1292
1293void *
1295{
1296 void *ret;
1297
1300
1301 context->isReset = false;
1302
1303 ret = context->methods->alloc(context, size, 0);
1304
1306
1308
1309 return ret;
1310}
1311
1312
1313
1314
1315
1316void *
1318{
1319 void *ret;
1320
1323
1326 elog(ERROR, "invalid memory alloc request size %zu", size);
1327
1328 context->isReset = false;
1329
1330 ret = context->methods->alloc(context, size, flags);
1332 return NULL;
1333
1335
1338
1339 return ret;
1340}
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350void
1352{
1355
1356}
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366void
1368{
1371
1372}
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383void
1385{
1387
1388
1389
1390
1391
1395 errmsg("logging memory contexts of PID %d", MyProcPid)));
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1409}
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435void
1437{
1438 List *contexts;
1440 HTAB *context_id_lookup;
1441 int context_id = 0;
1443 bool summary = false;
1444 int max_stats;
1446 int stats_count = 0;
1447 int stats_num = 0;
1449 int num_individual_stats = 0;
1450
1452
1453
1454
1455
1456
1460
1461 context_id_lookup = hash_create("pg_get_remote_backend_memory_contexts",
1462 256,
1465
1466
1468
1469
1470 max_stats =
1475
1476
1477
1478
1479
1480
1482 summary);
1483
1484
1485
1486
1487
1488
1489
1490 stats_num = Min(stats_count, max_stats);
1491
1493
1494
1495
1496
1497
1498
1500 {
1503
1505
1507
1510
1512
1513
1514
1515
1516
1517
1518
1519
1521
1522
1524 }
1525
1526
1527
1528
1529
1531 {
1533
1538 }
1540
1541
1542
1543
1544
1547
1549 {
1550
1551
1552
1553
1556 }
1557
1558
1559
1560
1561
1562
1566
1569
1570 if (summary)
1571 {
1572 int cxt_id = 0;
1574
1575
1576 memset(&stat, 0, sizeof(stat));
1578 &stat, true);
1582 cxt_id = cxt_id + 1;
1583
1584
1585
1586
1587
1588
1591 {
1593 int num_contexts = 0;
1594
1595 path = NIL;
1596 memset(&grand_totals, 0, sizeof(grand_totals));
1597
1600
1602
1603
1604
1605
1606
1607
1611 }
1613
1614
1616
1618
1619 return;
1620 }
1621
1623 {
1625
1626
1627
1628
1629
1631
1632
1633 memset(&stat, 0, sizeof(stat));
1634 (*cur->methods->stats) (cur, NULL, NULL, &stat, true);
1635
1636
1637 if (context_id < (max_stats - 1) || stats_count <= max_stats)
1638 {
1639
1641 }
1642 else
1643 {
1644 meminfo[max_stats - 1].totalspace += stat.totalspace;
1645 meminfo[max_stats - 1].nblocks += stat.nblocks;
1646 meminfo[max_stats - 1].freespace += stat.freespace;
1647 meminfo[max_stats - 1].freechunks += stat.freechunks;
1648 }
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659 if (stats_count > max_stats && context_id == (max_stats - 2))
1660 {
1661 char *nameptr;
1662 int namelen = strlen("Remaining Totals");
1663
1664 num_individual_stats = context_id + 1;
1667 strlcpy(nameptr, "Remaining Totals", namelen + 1);
1670 meminfo[max_stats - 1].type = 0;
1671 }
1672 context_id++;
1673 }
1674
1675
1676
1677
1678
1679 if (stats_count <= max_stats)
1680 {
1682 }
1683
1684 else
1685 {
1686 meminfo[max_stats - 1].num_agg_stats = context_id -
1687 num_individual_stats;
1688
1689
1690
1691
1692
1694 }
1695
1696
1698
1700}
1701
1702
1703
1704
1705
1706static void
1708{
1712}
1713
1714
1715
1716
1717
1718
1719
1720static List *
1722{
1723 bool found;
1726
1727 for (cur_context = c; cur_context != NULL; cur_context = cur_context->parent)
1728 {
1730
1731 cur_entry = hash_search(context_id_lookup, &cur_context, HASH_FIND, &found);
1732
1733 if (!found)
1734 elog(ERROR, "hash table corrupted, can't construct path value");
1735
1737 }
1738
1739 return path;
1740}
1741
1742
1743
1744
1745
1746static void
1748 int *stats_count, bool summary)
1749{
1751 {
1753 bool found;
1754
1758
1759
1760
1761
1762
1763 entry->context_id = ++(*stats_count);
1764
1765
1767 {
1768 if (summary)
1769 {
1773
1774 entry->context_id = ++(*stats_count);
1775 }
1776
1777 contexts = lappend(contexts, c);
1778 }
1779
1780
1781
1782
1783
1784 if (summary)
1785 break;
1786 }
1787}
1788
1789
1790
1791
1792
1793
1794static void
1798 dsa_area *area, int max_levels)
1799{
1801 const char *name = context->name;
1802 int *path_list;
1803
1804
1805
1806
1807
1808 if (context->ident && strncmp(context->name, "dynahash", 8) == 0)
1809 {
1812 }
1813
1814 if (name != NULL)
1815 {
1816 int namelen = strlen(name);
1817 char *nameptr;
1818
1822
1823 memcxt_info[curr_id].name = dsa_allocate(area, namelen + 1);
1826 }
1827 else
1829
1830
1831 if (ident != NULL)
1832 {
1833 int idlen = strlen(context->ident);
1834 char *identptr;
1835
1836
1837
1838
1839
1843
1847 }
1848 else
1850
1851
1852 if (path == NIL)
1854 else
1855 {
1857
1858 memcxt_info[curr_id].path_length = levels;
1859 memcxt_info[curr_id].path = dsa_allocate0(area, levels * sizeof(int));
1861 path_list = (int *) dsa_get_address(area, memcxt_info[curr_id].path);
1862
1864 {
1866 if (--levels == 0)
1867 break;
1868 }
1869 }
1870 memcxt_info[curr_id].type = context->type;
1872 memcxt_info[curr_id].nblocks = stat.nblocks;
1873 memcxt_info[curr_id].freespace = stat.freespace;
1875 memcxt_info[curr_id].num_agg_stats = num_contexts;
1876}
1877
1878
1879
1880
1881
1882
1883
1884static void
1887{
1889
1891 Assert(meminfo != NULL);
1892 for (int i = 0; i < total_stats; i++)
1893 {
1896
1899
1901 dsa_free(area, meminfo[i].path);
1902 }
1903
1906}
1907
1908
1909
1910
1911
1912void
1914{
1916
1918 return;
1919
1921
1923 {
1925 return;
1926 }
1927
1928
1931
1932
1933
1934
1935
1936
1939
1942}
1943
1944void *
1946{
1947
1948 void *ret;
1950
1953
1954 context->isReset = false;
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966 ret = context->methods->alloc(context, size, 0);
1967
1968 Assert(ret != NULL);
1970
1971 return ret;
1972}
1973
1974void *
1976{
1977
1978 void *ret;
1980
1983
1984 context->isReset = false;
1985
1986 ret = context->methods->alloc(context, size, 0);
1987
1988 Assert(ret != NULL);
1990
1992
1993 return ret;
1994}
1995
1996void *
1998{
1999
2000 void *ret;
2002
2005
2006 context->isReset = false;
2007
2008 ret = context->methods->alloc(context, size, flags);
2010 {
2011
2013 return NULL;
2014 }
2015
2017
2020
2021 return ret;
2022}
2023
2024
2025
2026
2027
2028
2029
2030
2031
2032
2033
2034
2035
2036
2037
2038
2039void *
2041 Size size, Size alignto, int flags)
2042{
2044 Size alloc_size;
2045 void *unaligned;
2046 void *aligned;
2047
2048
2049 Assert(alignto < (128 * 1024 * 1024));
2050
2051
2052 Assert((alignto & (alignto - 1)) == 0);
2053
2054
2055
2056
2057
2058 if (unlikely(alignto <= MAXIMUM_ALIGNOF))
2060
2061
2062
2063
2064
2065
2066
2067
2068
2069
2070
2071
2072
2073
2074
2075
2076
2077
2079
2080#ifdef MEMORY_CONTEXT_CHECKING
2081
2082 alloc_size += 1;
2083#endif
2084
2085
2087
2088
2089 aligned = (void *) TYPEALIGN(alignto, (char *) unaligned +
2091
2093
2094
2095
2096
2097
2098
2099
2100
2101
2102
2103
2106
2107
2108 Assert((void *) TYPEALIGN(alignto, aligned) == aligned);
2109
2110#ifdef MEMORY_CONTEXT_CHECKING
2111 alignedchunk->requested_size = size;
2112
2113 set_sentinel(aligned, size);
2114#endif
2115
2116
2118 (char *) alignedchunk - (char *) unaligned);
2119
2120
2122
2123 return aligned;
2124}
2125
2126
2127
2128
2129
2130
2131
2132
2133
2134
2135
2136
2137
2138
2139
2140
2141void *
2143{
2145}
2146
2147
2148
2149
2150
2151void
2153{
2154#ifdef USE_VALGRIND
2157#endif
2158
2160
2161#ifdef USE_VALGRIND
2164#endif
2165}
2166
2167
2168
2169
2170
2171void *
2173{
2174#ifdef USE_VALGRIND
2176#endif
2177#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
2179#endif
2180 void *ret;
2181
2183
2184
2186
2187
2188
2189
2190
2191
2192
2193
2194
2195
2196
2198
2199#ifdef USE_VALGRIND
2202#endif
2203
2204 return ret;
2205}
2206
2207
2208
2209
2210
2211
2212void *
2214{
2215#if defined(USE_ASSERT_CHECKING) || defined(USE_VALGRIND)
2217#endif
2218 void *ret;
2219
2221
2222
2224
2225
2226
2227
2228
2229
2230
2231
2232
2233
2234
2237 return NULL;
2238
2240
2241 return ret;
2242}
2243
2244
2245
2246
2247
2248
2249void *
2251{
2252 void *ret;
2253
2254
2255 if (unlikely(oldsize > size))
2256 elog(ERROR, "invalid repalloc0 call: oldsize %zu, new size %zu",
2257 oldsize, size);
2258
2259 ret = repalloc(pointer, size);
2260 memset((char *) ret + oldsize, 0, (size - oldsize));
2261 return ret;
2262}
2263
2264
2265
2266
2267
2268
2269
2270void *
2272{
2273 void *ret;
2274
2277
2278 context->isReset = false;
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2291
2293
2294 return ret;
2295}
2296
2297
2298
2299
2300
2301
2302void *
2304{
2305
2307}
2308
2309
2310
2311
2312
2313char *
2315{
2316 char *nstr;
2317 Size len = strlen(string) + 1;
2318
2320
2321 memcpy(nstr, string, len);
2322
2323 return nstr;
2324}
2325
2326char *
2328{
2330}
2331
2332
2333
2334
2335
2336
2337char *
2339{
2340 char *out;
2341
2343
2345 memcpy(out, in, len);
2346 out[len] = '\0';
2347
2348 return out;
2349}
2350
2351
2352
2353
2354char *
2356{
2357 size_t n;
2358
2359 n = strlen(in);
2360 while (n > 0 && in[n - 1] == '\n')
2361 n--;
2363}
Datum idx(PG_FUNCTION_ARGS)
MemoryContext AlignedAllocGetChunkContext(void *pointer)
void * AlignedAllocRealloc(void *pointer, Size size, int flags)
Size AlignedAllocGetChunkSpace(void *pointer)
void AlignedAllocFree(void *pointer)
void AllocSetReset(MemoryContext context)
void * AllocSetRealloc(void *pointer, Size size, int flags)
Size AllocSetGetChunkSpace(void *pointer)
MemoryContext AllocSetGetChunkContext(void *pointer)
void AllocSetStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
bool AllocSetIsEmpty(MemoryContext context)
void * AllocSetAlloc(MemoryContext context, Size size, int flags)
void AllocSetFree(void *pointer)
void AllocSetDelete(MemoryContext context)
TimestampTz GetCurrentTimestamp(void)
void BumpFree(void *pointer)
void BumpDelete(MemoryContext context)
Size BumpGetChunkSpace(void *pointer)
void BumpStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
MemoryContext BumpGetChunkContext(void *pointer)
void BumpReset(MemoryContext context)
bool BumpIsEmpty(MemoryContext context)
void * BumpRealloc(void *pointer, Size size, int flags)
void * BumpAlloc(MemoryContext context, Size size, int flags)
#define TYPEALIGN(ALIGNVAL, LEN)
#define MemSetAligned(start, val, len)
void ConditionVariableBroadcast(ConditionVariable *cv)
#define fprintf(file, fmt, msg)
dsa_area * dsa_attach(dsa_handle handle)
void * dsa_get_address(dsa_area *area, dsa_pointer dp)
void dsa_pin_mapping(dsa_area *area)
dsa_handle dsa_get_handle(dsa_area *area)
void dsa_detach(dsa_area *area)
void dsa_free(dsa_area *area, dsa_pointer dp)
void dsa_pin(dsa_area *area)
#define dsa_allocate0(area, size)
#define dsa_allocate(area, size)
#define InvalidDsaPointer
#define DSA_HANDLE_INVALID
#define dsa_create(tranch_id)
#define DsaPointerIsValid(x)
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
void hash_destroy(HTAB *hashp)
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
int errmsg_internal(const char *fmt,...)
int errhidestmt(bool hide_stmt)
int errdetail(const char *fmt,...)
int errhidecontext(bool hide_ctx)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
#define ereport(elevel,...)
#define MCXT_ALLOC_NO_OOM
void * GenerationRealloc(void *pointer, Size size, int flags)
void GenerationReset(MemoryContext context)
void GenerationFree(void *pointer)
MemoryContext GenerationGetChunkContext(void *pointer)
Size GenerationGetChunkSpace(void *pointer)
bool GenerationIsEmpty(MemoryContext context)
void GenerationStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
void GenerationDelete(MemoryContext context)
void * GenerationAlloc(MemoryContext context, Size size, int flags)
volatile sig_atomic_t LogMemoryContextPending
volatile sig_atomic_t InterruptPending
volatile uint32 CritSectionCount
volatile sig_atomic_t PublishMemoryContextPending
Assert(PointerIsAligned(start, uint64))
List * lappend(List *list, void *datum)
List * lcons_int(int datum, List *list)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
int pg_mbcliplen(const char *mbstr, int len, int limit)
void * repalloc0(void *pointer, Size oldsize, Size size)
void HandleGetMemoryContextInterrupt(void)
static void MemoryContextCallResetCallbacks(MemoryContext context)
char * MemoryContextStrdup(MemoryContext context, const char *string)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext MessageContext
bool MemoryContextIsEmpty(MemoryContext context)
void MemoryContextMemConsumed(MemoryContext context, MemoryContextCounters *consumed)
void MemoryContextReset(MemoryContext context)
void MemoryContextCreate(MemoryContext node, NodeTag tag, MemoryContextMethodID method_id, MemoryContext parent, const char *name)
void * MemoryContextAllocZero(MemoryContext context, Size size)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void HandleLogMemoryContextInterrupt(void)
void MemoryContextRegisterResetCallback(MemoryContext context, MemoryContextCallback *cb)
static MemoryContextMethodID GetMemoryChunkMethodID(const void *pointer)
void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
static void * BogusRealloc(void *pointer, Size size, int flags)
void * repalloc(void *pointer, Size size)
void AtProcExit_memstats_cleanup(int code, Datum arg)
static void compute_contexts_count_and_ids(List *contexts, HTAB *context_id_lookup, int *stats_count, bool summary)
void pfree(void *pointer)
Size GetMemoryChunkSpace(void *pointer)
void * palloc0(Size size)
static void free_memorycontextstate_dsa(dsa_area *area, int total_stats, dsa_pointer prev_dsa_pointer)
static Size BogusGetChunkSpace(void *pointer)
void ProcessGetMemoryContextInterrupt(void)
void * MemoryContextAllocAligned(MemoryContext context, Size size, Size alignto, int flags)
void MemoryContextDeleteChildren(MemoryContext context)
MemoryContext TopMemoryContext
char * pchomp(const char *in)
#define AssertNotInCriticalSection(context)
MemoryContext CurTransactionContext
static void PublishMemoryContext(MemoryStatsEntry *memcxt_info, int curr_id, MemoryContext context, List *path, MemoryContextCounters stat, int num_contexts, dsa_area *area, int max_levels)
MemoryContext CurrentMemoryContext
static MemoryContext MemoryContextTraverseNext(MemoryContext curr, MemoryContext top)
MemoryContext GetMemoryChunkContext(void *pointer)
void * MemoryContextAllocExtended(MemoryContext context, Size size, int flags)
void MemoryContextStatsDetail(MemoryContext context, int max_level, int max_children, bool print_to_stderr)
Size MemoryContextMemAllocated(MemoryContext context, bool recurse)
char * pnstrdup(const char *in, Size len)
void MemoryContextStats(MemoryContext context)
void MemoryContextInit(void)
static void BogusFree(void *pointer)
void * palloc_extended(Size size, int flags)
MemoryContext PostmasterContext
void * MemoryContextAllocationFailure(MemoryContext context, Size size, int flags)
static void end_memorycontext_reporting(void)
static const MemoryContextMethods mcxt_methods[]
static void MemoryContextStatsInternal(MemoryContext context, int level, int max_level, int max_children, MemoryContextCounters *totals, PrintDestination print_location, int *num_contexts)
void * repalloc_extended(void *pointer, Size size, int flags)
MemoryContext MemoryContextGetParent(MemoryContext context)
void ProcessLogMemoryContextInterrupt(void)
MemoryContext ErrorContext
static MemoryContext BogusGetChunkContext(void *pointer)
dsa_area * MemoryStatsDsaArea
MemoryContext CacheMemoryContext
void MemoryContextSizeFailure(MemoryContext context, Size size, int flags)
void * MemoryContextAllocHuge(MemoryContext context, Size size)
void MemoryContextDelete(MemoryContext context)
void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow)
static List * compute_context_path(MemoryContext c, HTAB *context_id_lookup)
static void MemoryContextDeleteOnly(MemoryContext context)
void MemoryContextResetChildren(MemoryContext context)
static void MemoryContextStatsPrint(MemoryContext context, void *passthru, const char *stats_string, bool print_to_stderr)
void * repalloc_huge(void *pointer, Size size)
void MemoryContextSetIdentifier(MemoryContext context, const char *id)
void MemoryContextResetOnly(MemoryContext context)
static uint64 GetMemoryChunkHeader(const void *pointer)
MemoryContext PortalContext
void * palloc_aligned(Size size, Size alignto, int flags)
#define MCXT_METHOD(pointer, method)
struct MemoryStatsBackendState * memCxtState
struct MemoryStatsCtl * memCxtArea
#define VALGRIND_DESTROY_MEMPOOL(context)
#define VALGRIND_MAKE_MEM_DEFINED(addr, size)
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size)
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed)
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size)
#define VALGRIND_MEMPOOL_FREE(context, addr)
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size)
#define MemoryContextIsValid(context)
#define AllocSetContextCreate
#define MEMORY_CONTEXT_REPORT_MAX_PER_BACKEND
#define ALLOCSET_DEFAULT_SIZES
#define AllocHugeSizeIsValid(size)
#define AllocSizeIsValid(size)
#define MEMORY_CONTEXT_IDENT_SHMEM_SIZE
struct MemoryStatsContextId MemoryStatsContextId
#define MAX_MEMORY_CONTEXT_STATS_SIZE
#define MEMORY_CONTEXT_METHODID_MASK
#define PallocAlignedExtraBytes(alignto)
@ MCTX_15_RESERVED_WIPEDMEM_ID
@ MCTX_1_RESERVED_GLIBC_ID
@ MCTX_0_RESERVED_UNUSEDMEM_ID
@ MCTX_2_RESERVED_GLIBC_ID
@ MCTX_ALIGNED_REDIRECT_ID
struct MemoryChunk MemoryChunk
#define PointerGetMemoryChunk(p)
static void MemoryChunkSetHdrMask(MemoryChunk *chunk, void *block, Size value, MemoryContextMethodID methodid)
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
struct MemoryContextData * MemoryContext
static int list_length(const List *l)
#define foreach_current_index(var_or_cell)
#define foreach_ptr(type, var, lst)
#define foreach_int(var, lst)
size_t strnlen(const char *str, size_t maxlen)
size_t strlcpy(char *dst, const char *src, size_t siz)
void * SlabAlloc(MemoryContext context, Size size, int flags)
void SlabFree(void *pointer)
void SlabReset(MemoryContext context)
Size SlabGetChunkSpace(void *pointer)
bool SlabIsEmpty(MemoryContext context)
MemoryContext SlabGetChunkContext(void *pointer)
void * SlabRealloc(void *pointer, Size size, int flags)
void SlabStats(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
void SlabDelete(MemoryContext context)
bool stack_is_too_deep(void)
struct MemoryContextCallback * next
MemoryContextCallbackFunction func
MemoryContextCallback * reset_cbs
const MemoryContextMethods * methods
void(* delete_context)(MemoryContext context)
void(* stats)(MemoryContext context, MemoryStatsPrintFunc printfunc, void *passthru, MemoryContextCounters *totals, bool print_to_stderr)
bool(* is_empty)(MemoryContext context)
void *(* alloc)(MemoryContext context, Size size, int flags)
void(* reset)(MemoryContext context)
TimestampTz stats_timestamp
dsa_pointer memstats_dsa_pointer
dsa_handle memstats_dsa_handle