#author("2017-05-24T23:56:36+09:00","default:haikikyou","haikikyou")
[[PostgreSQL/開発]]

#contents

* 概要 [#d39eb51e]

- メモリアロケーションのユーティリティ機能

* 定義 [#x1a86688]

** マクロ [#qcffa5c6]

*** MaxAllocSize, MaxAllocHugeSize [#r5e25b72]

|~マクロ名|~説明|~値|h
|MaxAllocSize|アロケーションの最大サイズ(1G-1)。&br;pallocでは,このサイズがリミットである。&br;|(Size) 0x3fffffff|
|MaxAllocHugeSize|アロケーションの最大サイズ(SIZE_MAX/2)。&br;XXXHogeやXXX_huge系の関数ではこのリミットとなる。&br;|(Size) -1 >> 1|

このマクロ定数を直接使うシーンはあまりない。AllocHugeSizeIsValidやAllocSizeIsValidなどのチェックマクロがMemoryAllocXXXX関数で使われている。
*** AllocSizeIsValid, AllocHugeSizeIsValid [#o711b550]


*** STANDARDCHUNKHEADERSIZE [#l8764aec]

*** MemoryContextResetAndDeleteChildren [#u74855f2]

*** ALLOCSET_DEFAULT_XXXX [#i7676be1]

|~定数|~説明|~値|h
|ALLOCSET_DEFAULT_MINSIZE||0|
|ALLOCSET_DEFAULT_INITSIZE||(8 * 1024)|
|ALLOCSET_DEFAULT_MAXSIZE||(8 * 1024 * 1024)|

*** ALLOCSET_SMALL_XXXX [#x8b6a559]

|~定数|~説明|~値|h
|ALLOCSET_SMALL_MINSIZE||0|
|ALLOCSET_SMALL_INITSIZE||(1 * 1024)|
|ALLOCSET_SMALL_MAXSIZE||(8 * 1024)|


*** ALLOCSET_SEPARATE_THRESHOLD [#v16bd8d2]
** 列挙型 [#a91733b0]

** 構造体 [#j3ab1cd0]

*** Struct [#pd8e61e3]

|~番号|~データ型|~フィールド|~説明|h


** 関数 [#u75fdaa2]

*** MemoryContextInit [#zfc402dc]

#geshi(c){{
extern void MemoryContextInit(void);
}}

- メモリコンテスト管理システムの初期化を行なう。
- postmasterのスタートアップ時に呼ばれるので,拡張機能などでこの関数を呼ぶケースはない(すでにメモリコンテキスト管理が利用できる状態になっているため)。
- この処理の中で,TopMemoryContextというメモリコンテキストツリーのトープレベルのメモリコンテキストとErrorContextが作成される。


&size(12){&color(white,orange){ 参考 };}; [[MemoryContextInit()>https://doxygen.postgresql.org/mcxt_8c.html#a90e9ce77120b687f9197ec3f42556e7b]] - on doxygen.postgresql.org
*** MemoryContextReset [#r2f7ee24]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextReset(MemoryContext context);
}}

- 指定されたメモリコンテキスト及び子階層に割り当てられたメモリ領域を解放する。
- 子階層のメモリコンテキストに対しては,MemoryContextDelete()(AllocSetDelete())を再帰的に呼ぶ。
- 対象のメモリコンテキスト(context)については,MemoryContextResetOnly()(AllocSetReset())が呼ばれる。contextの最初のブロック(存在すれば)は残され,メモリチャンクは消去される(freeptrは先頭にポイントされる)。

&size(12){&color(white,orange){ 参考 };};
- [[AllocSetDelete()>https://doxygen.postgresql.org/aset_8c.html#a800b4ddef4d9f1bc24252d34af22971c]] - on doxygen.postgresql.org
- [[AllocSetReset()>https://doxygen.postgresql.org/aset_8c.html#a4184c05efdf010f2c86bb057f4bc41a9]] - on doxygen.postgresql.org
*** MemoryContextDelete [#j584a692]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextDelete(MemoryContext context);
}}

- 指定されたメモリコンテキストのメモリ領域を解放する。
- 子階層のメモリコンテキストも再帰的に処理される。


&size(12){&color(white,orange){ 参考 };}; [[MemoryContextDelete()>https://doxygen.postgresql.org/mcxt_8c.html#adabf8bdc427b4e273e7445b4701f51f2]] - on doxygen.postgresql.org
*** MemoryContextResetOnly [#x6978405]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextResetOnly(MemoryContext context);
}}

- 指定されたメモリコンテキストをリセットする(AllocSetReset()が呼ばれる)。
- 子階層のメモリコンテキストに対しては何もしない。

*** MemoryContextResetChildren [#g76807a0]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextResetChildren(MemoryContext context);
}}

- 指定されたメモリコンテキストの子階層のメモリコンテキストに対して,再帰的にMemoryContextResetOnly関数を呼ぶ。
*** MemoryContextDeleteChildren [#q7ca2c17]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextDeleteChildren(MemoryContext context);
}}

- 指定されたメモリコンテキストの子階層のメモリコンテキストに対して,再帰的にMemoryContextDelete関数を呼ぶ。

&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{{
#define BLOCK_SIZE 1024 * 8

void reset_callback(void *arg)
{
    MemoryContext context = (MemoryContext)arg;
    elog(NOTICE, "%s will be deleted.", context->name);
}

void sample()
{
    MemoryContext oldcontext = NULL;
    MemoryContextCallback callback;
    MemoryContextCallback callback2;

    // init parent context
    MemoryContext parent_context = AllocSetContextCreate(CurrentMemoryContext,
                                                  "parent context",
                                                  0,
                                                  BLOCK_SIZE,
                                                  BLOCK_SIZE);

    callback.func = reset_callback;
    callback.arg = parent_context;
    MemoryContextRegisterResetCallback(parent_context, &callback);

    oldcontext = MemoryContextSwitchTo(parent_context);

    // parent context from here
    StringInfo strinfo = makeStringInfo();
    appendStringInfo(strinfo, "Hello %s", "Duke");
    elog(NOTICE, "%s", strinfo->data);

    // init child context
    MemoryContext child_context = AllocSetContextCreate(parent_context,
                                                  "child context",
                                                  0,
                                                  BLOCK_SIZE,
                                                  BLOCK_SIZE);
    callback2.func = reset_callback;
    callback2.arg = child_context;
    MemoryContextRegisterResetCallback(child_context, &callback2);

    MemoryContextSwitchTo(child_context);

    // child context from here
    StringInfo strinfo2 = makeStringInfo();
    appendStringInfo(strinfo2, "Hello %s", "Togo");
    elog(NOTICE, "%s", strinfo2->data);


    // switch back to original context.
    MemoryContextSwitchTo(oldcontext);

    // delete parent_context and child_context
    //
    //  CurrentMemoryContext
    //    |- parent_context     <--- delete
    //        |- child_context  <--- delete
    MemoryContextDeleteChildren(CurrentMemoryContext);
}
}}}
*** MemoryContextSetParent [#b9de69d5]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
// 引数2:新しい親となるメモリコンテキスト
extern void MemoryContextSetParent(MemoryContext context, MemoryContext new_parent);

/* Change a context to belong a new parent.

== Before ==
new_parent             current_parent
  |- context1            |- context <-- move to (o)
  |- context2            |- next_context

== After ==
new_parent             current_parent
  |- context (o)         |- next_context
  |- context1
  |- context2            
*/
}}

- 指定されたメモリコンテキスト(context)を新しいメモリコンテスト(new_parent)に付け替える。

&size(12){&color(white,orange){ 参考 };}; [[MemoryContextSetParent()>https://doxygen.postgresql.org/mcxt_8c.html#a38bd1f1dd1d024e312d5e5dabd68831d]] - on doxygen.postgresql.org
*** GetMemoryChunkSpace [#h49cf6cc]

#geshi(c){{
// 引数1:メモリチャンクのポインタ
// 戻り値:メモリチャンクサイズ(ヘッダ含む)
extern Size GetMemoryChunkSpace(void *pointer);
}}

- 指定されたメモリチャンクのサイズを返す(ヘッダサイズ含む)。


&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{{
void test_chunk_space()
{
    elog(NOTICE, "STANDARDCHUNKHEADERSIZE = %d", STANDARDCHUNKHEADERSIZE);

    char *chunk1 = palloc(128); // 128 + STANDARDCHUNKHEADERSIZE
    elog(NOTICE, "%d", GetMemoryChunkSpace(chunk1)); // NOTICE:  152

    char *chunk2 = palloc(256-32); // 256 + STANDARDCHUNKHEADERSIZE
    elog(NOTICE, "%d", GetMemoryChunkSpace(chunk2)); // NOTICE:  280
}
}}}
*** GetMemoryChunkContext [#s051b011]

#geshi(c){{
// 引数1:メモリチャンクのポインタ
// 戻り値:メモリチャンクが属するメモリコンテキスト
extern MemoryContext GetMemoryChunkContext(void *pointer);
}}

- 指定されたメモリチャンクの所属するメモリコンテキストを返す。


&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{{
void test_chunk()
{
    MemoryContext context = AllocSetContextCreate(CurrentMemoryContext,
                                                         "my context",
                                                         0,
                                                         1024 * 8,
                                                         1024 * 8);

    MemoryContext oldcontext = MemoryContextSwitchTo(context);
    StringInfo strinfo = makeStringInfo();
    elog(NOTICE, "%s", GetMemoryChunkContext(strinfo)->name); // NOTICE:  my contex

    MemoryContextSwitchTo(oldcontext);
    MemoryContextDelete(context);
}
}}}
*** MemoryContextGetParent [#o8a8b1a8]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
// 戻り値:contextの親のメモリコンテスト
extern MemoryContext MemoryContextGetParent(MemoryContext context);
}}

- 指定されたメモリコンテキストの親のメモリコンテキストを返す。


*** MemoryContextIsEmpty [#lac3b573]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
// 戻り値:true:空,false:空でない
extern bool MemoryContextIsEmpty(MemoryContext context);
}}

- 対象のメモリコンテストが空であるか否かを返す。
-- firstchildを持っていない場合はtrue。
--メモリコンテキストが新しい場合またはリセットされている場合はtrue。

&size(12){&color(white,orange){ 参考 };}; 
- [[AllocSetIsEmpty()>https://doxygen.postgresql.org/aset_8c.html#a4e07d97322537c87a4e33f13686e24bc]] - on doxygen.postgresql.org
- [[MemoryContextIsEmpty()>https://doxygen.postgresql.org/mcxt_8c.html#a1b1b3c0b50c290306a1e5eb88d1241f6]] - on doxygen.postgresql.org
*** MemoryContextStats [#p2c2599b]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextStats(MemoryContext context);
}}

- 指定されたメモリコンテキストの統計情報を出力する。

&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{{
void test_chunk()
{
    MemoryContext context = AllocSetContextCreate(CurrentMemoryContext,
                                                         "my context",
                                                         0,
                                                         1024 * 8,
                                                         1024 * 8);


    MemoryContext oldcontext = MemoryContextSwitchTo(context);
    StringInfo strinfo = makeStringInfo();
    elog(NOTICE, "%s", GetMemoryChunkContext(strinfo)->name); // NOTICE:  my contex

    MemoryContextStats(context);
    // my context: 8192 total in 1 blocks; 7056 free (0 chunks); 1136 used

    MemoryContextSwitchTo(oldcontext);
    MemoryContextDelete(context);
}
}}}

&size(12){&color(white,orange){ 参考 };}; [[MemoryContextStats()>https://doxygen.postgresql.org/mcxt_8c.html#a8e04497c2dd94b1e4a11b761bd27735c]] - on doxygen.postgresql.org
*** MemoryContextAllowInCriticalSection [#l9fe4341]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
// 引数2:クリティカルセクションのメモリアローケーションを許可するか否か
//      true:許可する,false:許可しない
extern void MemoryContextAllowInCriticalSection(MemoryContext context, bool allow);
}}

- 指定されたメモリコンテキストで,クリティカルセクション内でのメモリアロケーションの許可/不許可を設定する。
- デバッグ時に有効,一時的に許可など。

&size(12){&color(white,orange){ 参考 };}; [[palloc()>https://doxygen.postgresql.org/mcxt_8c.html#af25167ef63e16e1cbeb08b6f1f24e1d7]] - on doxygen.postgresql.org

&size(12){&color(white,#800080){ 実験 };};
#geshi(c){{{
//
// Debug, on enable assertion
//
void test_crit()
{
    MemoryContext context = AllocSetContextCreate(CurrentMemoryContext,
                                                  "my context",
                                                  0,
                                                  1024 * 8,
                                                  1024 * 8);
    context->allowInCritSection = false; // 許可しない,trueだと下のpallocは成功する
    MemoryContext oldcontext = MemoryContextSwitchTo(context);

    START_CRIT_SECTION();
    // クリティカルセクション内でのメモリアローケーションは通常許可されない
    void *chunk = palloc(128);
    // TRAP: FailedAssertion("!(CritSectionCount == 0 || (CurrentMemoryContext)->allowInCritSection)", File: "mcxt.c", Line: 818)
    END_CRIT_SECTION();

    MemoryContextSwitchTo(oldcontext);
    MemoryContextDelete(context);
}
}}}
*** MemoryContextCheck [#ka9bb5bd]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
extern void MemoryContextCheck(MemoryContext context);
}}

- デバッグ用の関数。
- ブロックリスト,チャンクを操作し整合性をチェックする。
- AllocSetCheck関数が呼ばれる。
*** MemoryContextContains [#n111b2d3]

#geshi(c){{
// 引数1:対象のメモリコンテキスト
// 引数2:メモリチャンクのポインタ
// 戻り値:true:含まれる,false:含まれない
extern bool MemoryContextContains(MemoryContext context, void *pointer);
}}

- メモリチャンクが指定されたメモリコンテキストに属するかを判定する。
- メモリチャンクのヘッダに登録されているメモリコンテキストが指定されたメモリコンテキストと等しいかチェックする。

&size(12){&color(white,orange){ 参考 };}; [[MemoryContextContains()>https://doxygen.postgresql.org/mcxt_8c.html#a91a5f76758e8559995c691a6de6849b2]] - on doxygen.postgresql.org

&size(12){&color(white,#00afcc){ サンプル };};
#geshi(c){{{
void test_chunk_contains()
{
    void *chunk = palloc(128);
    elog(NOTICE, "%d", MemoryContextContains(CurrentMemoryContext, chunk)); // NOTICE:  1
    pfree(chunk);
}
}}}
*** MemoryContextCreate [#a79de8dc]

#geshi(c){{
// 引数1:
extern MemoryContext MemoryContextCreate(NodeTag tag, Size size,
					MemoryContextMethods *methods,
					MemoryContext parent,
					const char *name);
}}

- 説明




*** AllocSetContextCreate [#lc8a5772]

#geshi(c){{
// 引数1:
extern MemoryContext AllocSetContextCreate(MemoryContext parent,
					  const char *name,
					  Size minContextSize,
					  Size initBlockSize,
					  Size maxBlockSize);
}}





















* サンプルプログラム [#j0b18196]

#geshi(c){{
// sample
}}

* 参考・関連 [#vceb7bae]

- [[memutils.h>https://doxygen.postgresql.org/memutils_8h.html]] - on doxygen.postgresql.org
- [[aset.c>https://doxygen.postgresql.org/aset_8c.html]] - on doxygen.postgresql.org
- [[mcxt.c>https://doxygen.postgresql.org/mcxt_8c.html]] - on doxygen.postgresql.org
- [[palloc.h>PostgreSQL/開発/include/utils/palloc.h]]

&size(12){&color(white,orange){ 関連 };};

#related
* コメント [#m0e0ed05]

#comment

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
目次
ダブルクリックで閉じるTOP | 閉じる
GO TO TOP