diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/misc/guc.c | 12 | ||||
-rw-r--r-- | src/backend/utils/misc/postgresql.conf.sample | 7 | ||||
-rw-r--r-- | src/backend/utils/resowner/resowner.c | 109 |
3 files changed, 128 insertions, 0 deletions
diff --git a/src/backend/utils/misc/guc.c b/src/backend/utils/misc/guc.c index ddbeb34ce72..1756b48c4fe 100644 --- a/src/backend/utils/misc/guc.c +++ b/src/backend/utils/misc/guc.c @@ -61,6 +61,7 @@ #include "replication/walreceiver.h" #include "replication/walsender.h" #include "storage/bufmgr.h" +#include "storage/dsm_impl.h" #include "storage/standby.h" #include "storage/fd.h" #include "storage/proc.h" @@ -385,6 +386,7 @@ static const struct config_enum_entry synchronous_commit_options[] = { */ extern const struct config_enum_entry wal_level_options[]; extern const struct config_enum_entry sync_method_options[]; +extern const struct config_enum_entry dynamic_shared_memory_options[]; /* * GUC option variables that are exported from this module @@ -3336,6 +3338,16 @@ static struct config_enum ConfigureNamesEnum[] = }, { + {"dynamic_shared_memory_type", PGC_POSTMASTER, RESOURCES_MEM, + gettext_noop("Selects the dynamic shared memory implementation used."), + NULL + }, + &dynamic_shared_memory_type, + DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE, dynamic_shared_memory_options, + NULL, NULL, NULL + }, + + { {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS, gettext_noop("Selects the method used for forcing WAL updates to disk."), NULL diff --git a/src/backend/utils/misc/postgresql.conf.sample b/src/backend/utils/misc/postgresql.conf.sample index 70221f42918..707edf1d91d 100644 --- a/src/backend/utils/misc/postgresql.conf.sample +++ b/src/backend/utils/misc/postgresql.conf.sample @@ -123,6 +123,13 @@ #work_mem = 1MB # min 64kB #maintenance_work_mem = 16MB # min 1MB #max_stack_depth = 2MB # min 100kB +#dynamic_shared_memory_type = posix # the default is the first option + # supported by the operating system: + # posix + # sysv + # windows + # mmap + # use none to disable dynamic shared memory # - Disk - diff --git a/src/backend/utils/resowner/resowner.c b/src/backend/utils/resowner/resowner.c index e7ec3931f12..ba177015799 100644 --- a/src/backend/utils/resowner/resowner.c +++ b/src/backend/utils/resowner/resowner.c @@ -98,6 +98,11 @@ typedef struct ResourceOwnerData int nfiles; /* number of owned temporary files */ File *files; /* dynamically allocated array */ int maxfiles; /* currently allocated array size */ + + /* We have built-in support for remembering dynamic shmem segments */ + int ndsms; /* number of owned shmem segments */ + dsm_segment **dsms; /* dynamically allocated array */ + int maxdsms; /* currently allocated array size */ } ResourceOwnerData; @@ -132,6 +137,7 @@ static void PrintPlanCacheLeakWarning(CachedPlan *plan); static void PrintTupleDescLeakWarning(TupleDesc tupdesc); static void PrintSnapshotLeakWarning(Snapshot snapshot); static void PrintFileLeakWarning(File file); +static void PrintDSMLeakWarning(dsm_segment *seg); /***************************************************************************** @@ -271,6 +277,21 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]); RelationClose(owner->relrefs[owner->nrelrefs - 1]); } + + /* + * Release dynamic shared memory segments. Note that dsm_detach() + * will remove the segment from my list, so I just have to iterate + * until there are none. + * + * As in the preceding cases, warn if there are leftover at commit + * time. + */ + while (owner->ndsms > 0) + { + if (isCommit) + PrintDSMLeakWarning(owner->dsms[owner->ndsms - 1]); + dsm_detach(owner->dsms[owner->ndsms - 1]); + } } else if (phase == RESOURCE_RELEASE_LOCKS) { @@ -402,6 +423,7 @@ ResourceOwnerDelete(ResourceOwner owner) Assert(owner->ncatrefs == 0); Assert(owner->ncatlistrefs == 0); Assert(owner->nrelrefs == 0); + Assert(owner->ndsms == 0); Assert(owner->nplanrefs == 0); Assert(owner->ntupdescs == 0); Assert(owner->nsnapshots == 0); @@ -438,6 +460,8 @@ ResourceOwnerDelete(ResourceOwner owner) pfree(owner->snapshots); if (owner->files) pfree(owner->files); + if (owner->dsms) + pfree(owner->dsms); pfree(owner); } @@ -1230,3 +1254,88 @@ PrintFileLeakWarning(File file) "temporary file leak: File %d still referenced", file); } + +/* + * Make sure there is room for at least one more entry in a ResourceOwner's + * dynamic shmem segment reference array. + * + * This is separate from actually inserting an entry because if we run out + * of memory, it's critical to do so *before* acquiring the resource. + */ +void +ResourceOwnerEnlargeDSMs(ResourceOwner owner) +{ + int newmax; + + if (owner->ndsms < owner->maxdsms) + return; /* nothing to do */ + + if (owner->dsms == NULL) + { + newmax = 16; + owner->dsms = (dsm_segment **) + MemoryContextAlloc(TopMemoryContext, + newmax * sizeof(dsm_segment *)); + owner->maxdsms = newmax; + } + else + { + newmax = owner->maxdsms * 2; + owner->dsms = (dsm_segment **) + repalloc(owner->dsms, newmax * sizeof(dsm_segment *)); + owner->maxdsms = newmax; + } +} + +/* + * Remember that a dynamic shmem segment is owned by a ResourceOwner + * + * Caller must have previously done ResourceOwnerEnlargeDSMs() + */ +void +ResourceOwnerRememberDSM(ResourceOwner owner, dsm_segment *seg) +{ + Assert(owner->ndsms < owner->maxdsms); + owner->dsms[owner->ndsms] = seg; + owner->ndsms++; +} + +/* + * Forget that a temporary file is owned by a ResourceOwner + */ +void +ResourceOwnerForgetDSM(ResourceOwner owner, dsm_segment *seg) +{ + dsm_segment **dsms = owner->dsms; + int ns1 = owner->ndsms - 1; + int i; + + for (i = ns1; i >= 0; i--) + { + if (dsms[i] == seg) + { + while (i < ns1) + { + dsms[i] = dsms[i + 1]; + i++; + } + owner->ndsms = ns1; + return; + } + } + elog(ERROR, + "dynamic shared memory segment %u is not owned by resource owner %s", + dsm_segment_handle(seg), owner->name); +} + + +/* + * Debugging subroutine + */ +static void +PrintDSMLeakWarning(dsm_segment *seg) +{ + elog(WARNING, + "dynamic shared memory leak: segment %u still referenced", + dsm_segment_handle(seg)); +} |