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