00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #define MCXT_INCLUDE_DEFINITIONS
00024
00025 #include "postgres.h"
00026
00027 #include "utils/memutils.h"
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038 MemoryContext CurrentMemoryContext = NULL;
00039
00040
00041
00042
00043
00044 MemoryContext TopMemoryContext = NULL;
00045 MemoryContext ErrorContext = NULL;
00046 MemoryContext PostmasterContext = NULL;
00047 MemoryContext CacheMemoryContext = NULL;
00048 MemoryContext MessageContext = NULL;
00049 MemoryContext TopTransactionContext = NULL;
00050 MemoryContext CurTransactionContext = NULL;
00051
00052
00053 MemoryContext PortalContext = NULL;
00054
00055 static void MemoryContextStatsInternal(MemoryContext context, int level);
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078 void
00079 MemoryContextInit(void)
00080 {
00081 AssertState(TopMemoryContext == NULL);
00082
00083
00084
00085
00086
00087
00088
00089 TopMemoryContext = AllocSetContextCreate((MemoryContext) NULL,
00090 "TopMemoryContext",
00091 0,
00092 8 * 1024,
00093 8 * 1024);
00094
00095
00096
00097
00098
00099 CurrentMemoryContext = TopMemoryContext;
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109 ErrorContext = AllocSetContextCreate(TopMemoryContext,
00110 "ErrorContext",
00111 8 * 1024,
00112 8 * 1024,
00113 8 * 1024);
00114 }
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124 void
00125 MemoryContextReset(MemoryContext context)
00126 {
00127 AssertArg(MemoryContextIsValid(context));
00128
00129
00130 if (context->firstchild != NULL)
00131 MemoryContextResetChildren(context);
00132
00133
00134 if (!context->isReset)
00135 {
00136 (*context->methods->reset) (context);
00137 context->isReset = true;
00138 }
00139 }
00140
00141
00142
00143
00144
00145
00146
00147 void
00148 MemoryContextResetChildren(MemoryContext context)
00149 {
00150 MemoryContext child;
00151
00152 AssertArg(MemoryContextIsValid(context));
00153
00154 for (child = context->firstchild; child != NULL; child = child->nextchild)
00155 MemoryContextReset(child);
00156 }
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 void
00169 MemoryContextDelete(MemoryContext context)
00170 {
00171 AssertArg(MemoryContextIsValid(context));
00172
00173 Assert(context != TopMemoryContext);
00174
00175 Assert(context != CurrentMemoryContext);
00176
00177 MemoryContextDeleteChildren(context);
00178
00179
00180
00181
00182
00183
00184 MemoryContextSetParent(context, NULL);
00185
00186 (*context->methods->delete_context) (context);
00187 pfree(context);
00188 }
00189
00190
00191
00192
00193
00194
00195 void
00196 MemoryContextDeleteChildren(MemoryContext context)
00197 {
00198 AssertArg(MemoryContextIsValid(context));
00199
00200
00201
00202
00203
00204 while (context->firstchild != NULL)
00205 MemoryContextDelete(context->firstchild);
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216 void
00217 MemoryContextResetAndDeleteChildren(MemoryContext context)
00218 {
00219 AssertArg(MemoryContextIsValid(context));
00220
00221 MemoryContextDeleteChildren(context);
00222 MemoryContextReset(context);
00223 }
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243 void
00244 MemoryContextSetParent(MemoryContext context, MemoryContext new_parent)
00245 {
00246 AssertArg(MemoryContextIsValid(context));
00247 AssertArg(context != new_parent);
00248
00249
00250 if (context->parent)
00251 {
00252 MemoryContext parent = context->parent;
00253
00254 if (context == parent->firstchild)
00255 parent->firstchild = context->nextchild;
00256 else
00257 {
00258 MemoryContext child;
00259
00260 for (child = parent->firstchild; child; child = child->nextchild)
00261 {
00262 if (context == child->nextchild)
00263 {
00264 child->nextchild = context->nextchild;
00265 break;
00266 }
00267 }
00268 }
00269 }
00270
00271
00272 if (new_parent)
00273 {
00274 AssertArg(MemoryContextIsValid(new_parent));
00275 context->parent = new_parent;
00276 context->nextchild = new_parent->firstchild;
00277 new_parent->firstchild = context;
00278 }
00279 else
00280 {
00281 context->parent = NULL;
00282 context->nextchild = NULL;
00283 }
00284 }
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294 Size
00295 GetMemoryChunkSpace(void *pointer)
00296 {
00297 StandardChunkHeader *header;
00298
00299
00300
00301
00302
00303
00304 Assert(pointer != NULL);
00305 Assert(pointer == (void *) MAXALIGN(pointer));
00306
00307
00308
00309
00310 header = (StandardChunkHeader *)
00311 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00312
00313 AssertArg(MemoryContextIsValid(header->context));
00314
00315 return (*header->context->methods->get_chunk_space) (header->context,
00316 pointer);
00317 }
00318
00319
00320
00321
00322
00323
00324 MemoryContext
00325 GetMemoryChunkContext(void *pointer)
00326 {
00327 StandardChunkHeader *header;
00328
00329
00330
00331
00332
00333
00334 Assert(pointer != NULL);
00335 Assert(pointer == (void *) MAXALIGN(pointer));
00336
00337
00338
00339
00340 header = (StandardChunkHeader *)
00341 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00342
00343 AssertArg(MemoryContextIsValid(header->context));
00344
00345 return header->context;
00346 }
00347
00348
00349
00350
00351
00352 MemoryContext
00353 MemoryContextGetParent(MemoryContext context)
00354 {
00355 AssertArg(MemoryContextIsValid(context));
00356
00357 return context->parent;
00358 }
00359
00360
00361
00362
00363
00364 bool
00365 MemoryContextIsEmpty(MemoryContext context)
00366 {
00367 AssertArg(MemoryContextIsValid(context));
00368
00369
00370
00371
00372
00373 if (context->firstchild != NULL)
00374 return false;
00375
00376 return (*context->methods->is_empty) (context);
00377 }
00378
00379
00380
00381
00382
00383
00384
00385
00386 void
00387 MemoryContextStats(MemoryContext context)
00388 {
00389 MemoryContextStatsInternal(context, 0);
00390 }
00391
00392 static void
00393 MemoryContextStatsInternal(MemoryContext context, int level)
00394 {
00395 MemoryContext child;
00396
00397 AssertArg(MemoryContextIsValid(context));
00398
00399 (*context->methods->stats) (context, level);
00400 for (child = context->firstchild; child != NULL; child = child->nextchild)
00401 MemoryContextStatsInternal(child, level + 1);
00402 }
00403
00404
00405
00406
00407
00408
00409
00410 #ifdef MEMORY_CONTEXT_CHECKING
00411 void
00412 MemoryContextCheck(MemoryContext context)
00413 {
00414 MemoryContext child;
00415
00416 AssertArg(MemoryContextIsValid(context));
00417
00418 (*context->methods->check) (context);
00419 for (child = context->firstchild; child != NULL; child = child->nextchild)
00420 MemoryContextCheck(child);
00421 }
00422 #endif
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435 bool
00436 MemoryContextContains(MemoryContext context, void *pointer)
00437 {
00438 StandardChunkHeader *header;
00439
00440
00441
00442
00443
00444
00445 if (pointer == NULL || pointer != (void *) MAXALIGN(pointer))
00446 return false;
00447
00448
00449
00450
00451 header = (StandardChunkHeader *)
00452 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00453
00454
00455
00456
00457
00458
00459 if (header->context == context && AllocSizeIsValid(header->size))
00460 return true;
00461 return false;
00462 }
00463
00464
00465
00466
00467
00468
00469
00470
00471
00472
00473
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512 MemoryContext
00513 MemoryContextCreate(NodeTag tag, Size size,
00514 MemoryContextMethods *methods,
00515 MemoryContext parent,
00516 const char *name)
00517 {
00518 MemoryContext node;
00519 Size needed = size + strlen(name) + 1;
00520
00521
00522 if (TopMemoryContext != NULL)
00523 {
00524
00525 node = (MemoryContext) MemoryContextAlloc(TopMemoryContext,
00526 needed);
00527 }
00528 else
00529 {
00530
00531 node = (MemoryContext) malloc(needed);
00532 Assert(node != NULL);
00533 }
00534
00535
00536 MemSet(node, 0, size);
00537 node->type = tag;
00538 node->methods = methods;
00539 node->parent = NULL;
00540 node->firstchild = NULL;
00541 node->nextchild = NULL;
00542 node->isReset = true;
00543 node->name = ((char *) node) + size;
00544 strcpy(node->name, name);
00545
00546
00547 (*node->methods->init) (node);
00548
00549
00550
00551 if (parent)
00552 {
00553 node->parent = parent;
00554 node->nextchild = parent->firstchild;
00555 parent->firstchild = node;
00556 }
00557
00558
00559 return node;
00560 }
00561
00562
00563
00564
00565
00566
00567
00568
00569 void *
00570 MemoryContextAlloc(MemoryContext context, Size size)
00571 {
00572 AssertArg(MemoryContextIsValid(context));
00573
00574 if (!AllocSizeIsValid(size))
00575 elog(ERROR, "invalid memory alloc request size %lu",
00576 (unsigned long) size);
00577
00578 context->isReset = false;
00579
00580 return (*context->methods->alloc) (context, size);
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590 void *
00591 MemoryContextAllocZero(MemoryContext context, Size size)
00592 {
00593 void *ret;
00594
00595 AssertArg(MemoryContextIsValid(context));
00596
00597 if (!AllocSizeIsValid(size))
00598 elog(ERROR, "invalid memory alloc request size %lu",
00599 (unsigned long) size);
00600
00601 context->isReset = false;
00602
00603 ret = (*context->methods->alloc) (context, size);
00604
00605 MemSetAligned(ret, 0, size);
00606
00607 return ret;
00608 }
00609
00610
00611
00612
00613
00614
00615
00616
00617 void *
00618 MemoryContextAllocZeroAligned(MemoryContext context, Size size)
00619 {
00620 void *ret;
00621
00622 AssertArg(MemoryContextIsValid(context));
00623
00624 if (!AllocSizeIsValid(size))
00625 elog(ERROR, "invalid memory alloc request size %lu",
00626 (unsigned long) size);
00627
00628 context->isReset = false;
00629
00630 ret = (*context->methods->alloc) (context, size);
00631
00632 MemSetLoop(ret, 0, size);
00633
00634 return ret;
00635 }
00636
00637 void *
00638 palloc(Size size)
00639 {
00640
00641 AssertArg(MemoryContextIsValid(CurrentMemoryContext));
00642
00643 if (!AllocSizeIsValid(size))
00644 elog(ERROR, "invalid memory alloc request size %lu",
00645 (unsigned long) size);
00646
00647 CurrentMemoryContext->isReset = false;
00648
00649 return (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
00650 }
00651
00652 void *
00653 palloc0(Size size)
00654 {
00655
00656 void *ret;
00657
00658 AssertArg(MemoryContextIsValid(CurrentMemoryContext));
00659
00660 if (!AllocSizeIsValid(size))
00661 elog(ERROR, "invalid memory alloc request size %lu",
00662 (unsigned long) size);
00663
00664 CurrentMemoryContext->isReset = false;
00665
00666 ret = (*CurrentMemoryContext->methods->alloc) (CurrentMemoryContext, size);
00667
00668 MemSetAligned(ret, 0, size);
00669
00670 return ret;
00671 }
00672
00673
00674
00675
00676
00677 void
00678 pfree(void *pointer)
00679 {
00680 StandardChunkHeader *header;
00681
00682
00683
00684
00685
00686
00687 Assert(pointer != NULL);
00688 Assert(pointer == (void *) MAXALIGN(pointer));
00689
00690
00691
00692
00693 header = (StandardChunkHeader *)
00694 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00695
00696 AssertArg(MemoryContextIsValid(header->context));
00697
00698 (*header->context->methods->free_p) (header->context, pointer);
00699 }
00700
00701
00702
00703
00704
00705 void *
00706 repalloc(void *pointer, Size size)
00707 {
00708 StandardChunkHeader *header;
00709
00710
00711
00712
00713
00714
00715 Assert(pointer != NULL);
00716 Assert(pointer == (void *) MAXALIGN(pointer));
00717
00718
00719
00720
00721 header = (StandardChunkHeader *)
00722 ((char *) pointer - STANDARDCHUNKHEADERSIZE);
00723
00724 AssertArg(MemoryContextIsValid(header->context));
00725
00726 if (!AllocSizeIsValid(size))
00727 elog(ERROR, "invalid memory alloc request size %lu",
00728 (unsigned long) size);
00729
00730
00731 Assert(!header->context->isReset);
00732
00733 return (*header->context->methods->realloc) (header->context,
00734 pointer, size);
00735 }
00736
00737
00738
00739
00740
00741 char *
00742 MemoryContextStrdup(MemoryContext context, const char *string)
00743 {
00744 char *nstr;
00745 Size len = strlen(string) + 1;
00746
00747 nstr = (char *) MemoryContextAlloc(context, len);
00748
00749 memcpy(nstr, string, len);
00750
00751 return nstr;
00752 }
00753
00754 char *
00755 pstrdup(const char *in)
00756 {
00757 return MemoryContextStrdup(CurrentMemoryContext, in);
00758 }
00759
00760
00761
00762
00763
00764
00765 char *
00766 pnstrdup(const char *in, Size len)
00767 {
00768 char *out = palloc(len + 1);
00769
00770 memcpy(out, in, len);
00771 out[len] = '\0';
00772 return out;
00773 }