Commit 0ac5e5a7 authored by Robert Haas's avatar Robert Haas

Allow dynamic allocation of shared memory segments.

Patch by myself and Amit Kapila.  Design help from Noah Misch.  Review
by Andres Freund.
parent f5665151
...@@ -8384,6 +8384,180 @@ if test "$ac_res" != no; then ...@@ -8384,6 +8384,180 @@ if test "$ac_res" != no; then
fi fi
{ $as_echo "$as_me:$LINENO: checking for library containing shm_open" >&5
$as_echo_n "checking for library containing shm_open... " >&6; }
if test "${ac_cv_search_shm_open+set}" = set; then
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char shm_open ();
int
main ()
{
return shm_open ();
;
return 0;
}
_ACEOF
for ac_lib in '' rt; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
ac_cv_search_shm_open=$ac_res
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
fi
rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_shm_open+set}" = set; then
break
fi
done
if test "${ac_cv_search_shm_open+set}" = set; then
:
else
ac_cv_search_shm_open=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_shm_open" >&5
$as_echo "$ac_cv_search_shm_open" >&6; }
ac_res=$ac_cv_search_shm_open
if test "$ac_res" != no; then
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
{ $as_echo "$as_me:$LINENO: checking for library containing shm_unlink" >&5
$as_echo_n "checking for library containing shm_unlink... " >&6; }
if test "${ac_cv_search_shm_unlink+set}" = set; then
$as_echo_n "(cached) " >&6
else
ac_func_search_save_LIBS=$LIBS
cat >conftest.$ac_ext <<_ACEOF
/* confdefs.h. */
_ACEOF
cat confdefs.h >>conftest.$ac_ext
cat >>conftest.$ac_ext <<_ACEOF
/* end confdefs.h. */
/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
#ifdef __cplusplus
extern "C"
#endif
char shm_unlink ();
int
main ()
{
return shm_unlink ();
;
return 0;
}
_ACEOF
for ac_lib in '' rt; do
if test -z "$ac_lib"; then
ac_res="none required"
else
ac_res=-l$ac_lib
LIBS="-l$ac_lib $ac_func_search_save_LIBS"
fi
rm -f conftest.$ac_objext conftest$ac_exeext
if { (ac_try="$ac_link"
case "(($ac_try" in
*\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
*) ac_try_echo=$ac_try;;
esac
eval ac_try_echo="\"\$as_me:$LINENO: $ac_try_echo\""
$as_echo "$ac_try_echo") >&5
(eval "$ac_link") 2>conftest.er1
ac_status=$?
grep -v '^ *+' conftest.er1 >conftest.err
rm -f conftest.er1
cat conftest.err >&5
$as_echo "$as_me:$LINENO: \$? = $ac_status" >&5
(exit $ac_status); } && {
test -z "$ac_c_werror_flag" ||
test ! -s conftest.err
} && test -s conftest$ac_exeext && {
test "$cross_compiling" = yes ||
$as_test_x conftest$ac_exeext
}; then
ac_cv_search_shm_unlink=$ac_res
else
$as_echo "$as_me: failed program was:" >&5
sed 's/^/| /' conftest.$ac_ext >&5
fi
rm -rf conftest.dSYM
rm -f core conftest.err conftest.$ac_objext conftest_ipa8_conftest.oo \
conftest$ac_exeext
if test "${ac_cv_search_shm_unlink+set}" = set; then
break
fi
done
if test "${ac_cv_search_shm_unlink+set}" = set; then
:
else
ac_cv_search_shm_unlink=no
fi
rm conftest.$ac_ext
LIBS=$ac_func_search_save_LIBS
fi
{ $as_echo "$as_me:$LINENO: result: $ac_cv_search_shm_unlink" >&5
$as_echo "$ac_cv_search_shm_unlink" >&6; }
ac_res=$ac_cv_search_shm_unlink
if test "$ac_res" != no; then
test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
fi
# Solaris: # Solaris:
{ $as_echo "$as_me:$LINENO: checking for library containing fdatasync" >&5 { $as_echo "$as_me:$LINENO: checking for library containing fdatasync" >&5
$as_echo_n "checking for library containing fdatasync... " >&6; } $as_echo_n "checking for library containing fdatasync... " >&6; }
...@@ -19763,7 +19937,8 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` ...@@ -19763,7 +19937,8 @@ LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
for ac_func in cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l
do do
as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh` as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ $as_echo "$as_me:$LINENO: checking for $ac_func" >&5 { $as_echo "$as_me:$LINENO: checking for $ac_func" >&5
......
...@@ -883,6 +883,8 @@ case $host_os in ...@@ -883,6 +883,8 @@ case $host_os in
esac esac
AC_SEARCH_LIBS(getopt_long, [getopt gnugetopt]) AC_SEARCH_LIBS(getopt_long, [getopt gnugetopt])
AC_SEARCH_LIBS(crypt, crypt) AC_SEARCH_LIBS(crypt, crypt)
AC_SEARCH_LIBS(shm_open, rt)
AC_SEARCH_LIBS(shm_unlink, rt)
# Solaris: # Solaris:
AC_SEARCH_LIBS(fdatasync, [rt posix4]) AC_SEARCH_LIBS(fdatasync, [rt posix4])
# Required for thread_test.c on Solaris 2.5: # Required for thread_test.c on Solaris 2.5:
...@@ -1230,7 +1232,7 @@ PGAC_FUNC_GETTIMEOFDAY_1ARG ...@@ -1230,7 +1232,7 @@ PGAC_FUNC_GETTIMEOFDAY_1ARG
LIBS_including_readline="$LIBS" LIBS_including_readline="$LIBS"
LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'` LIBS=`echo "$LIBS" | sed -e 's/-ledit//g' -e 's/-lreadline//g'`
AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l]) AC_CHECK_FUNCS([cbrt dlopen fdatasync getifaddrs getpeerucred getrlimit mbstowcs_l memmove poll pstat readlink setproctitle setsid shm_open sigprocmask symlink sync_file_range towlower utime utimes wcstombs wcstombs_l])
AC_REPLACE_FUNCS(fseeko) AC_REPLACE_FUNCS(fseeko)
case $host_os in case $host_os in
......
...@@ -1194,6 +1194,32 @@ include 'filename' ...@@ -1194,6 +1194,32 @@ include 'filename'
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry id="guc-dynamic-shared-memory-type" xreflabel="dynamic_shared_memory_type">
<term><varname>dynamic_shared_memory_type</varname> (<type>enum</type>)</term>
<indexterm>
<primary><varname>dynamic_shared_memory_type</> configuration parameter</primary>
</indexterm>
<listitem>
<para>
Specifies the dynamic shared memory implementation that the server
should use. Possible values are <literal>posix</> (for POSIX shared
memory allocated using <literal>shm_open</>), <literal>sysv</literal>
(for System V shared memory allocated via <literal>shmget</>),
<literal>windows</> (for Windows shared memory), <literal>mmap</>
(to simulate shared memory using memory-mapped files stored in the
data directory), and <literal>none</> (to disable this feature).
Not all values are supported on all platforms; the first supported
option is the default for that platform. The use of the
<literal>mmap</> option, which is not the default on any platform,
is generally discouraged because the operating system may write
modified pages back to disk repeatedly, increasing system I/O load;
however, it may be useful for debugging, when the
<literal>pg_dynshmem</> directory is stored on a RAM disk, or when
other shared memory facilities are not available.
</para>
</listitem>
</varlistentry>
</variablelist> </variablelist>
</sect2> </sect2>
......
...@@ -29,6 +29,7 @@ ...@@ -29,6 +29,7 @@
#endif #endif
#include "miscadmin.h" #include "miscadmin.h"
#include "portability/mem.h"
#include "storage/ipc.h" #include "storage/ipc.h"
#include "storage/pg_shmem.h" #include "storage/pg_shmem.h"
...@@ -36,31 +37,6 @@ ...@@ -36,31 +37,6 @@
typedef key_t IpcMemoryKey; /* shared memory key passed to shmget(2) */ typedef key_t IpcMemoryKey; /* shared memory key passed to shmget(2) */
typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */ typedef int IpcMemoryId; /* shared memory ID returned by shmget(2) */
#define IPCProtection (0600) /* access/modify by user only */
#ifdef SHM_SHARE_MMU /* use intimate shared memory on Solaris */
#define PG_SHMAT_FLAGS SHM_SHARE_MMU
#else
#define PG_SHMAT_FLAGS 0
#endif
/* Linux prefers MAP_ANONYMOUS, but the flag is called MAP_ANON on other systems. */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
/* BSD-derived systems have MAP_HASSEMAPHORE, but it's not present (or needed) on Linux. */
#ifndef MAP_HASSEMAPHORE
#define MAP_HASSEMAPHORE 0
#endif
#define PG_MMAP_FLAGS (MAP_SHARED|MAP_ANONYMOUS|MAP_HASSEMAPHORE)
/* Some really old systems don't define MAP_FAILED. */
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
unsigned long UsedShmemSegID = 0; unsigned long UsedShmemSegID = 0;
void *UsedShmemSegAddr = NULL; void *UsedShmemSegAddr = NULL;
......
...@@ -15,7 +15,7 @@ override CFLAGS+= -fno-inline ...@@ -15,7 +15,7 @@ override CFLAGS+= -fno-inline
endif endif
endif endif
OBJS = ipc.o ipci.o pmsignal.o procarray.o procsignal.o shmem.o shmqueue.o \ OBJS = dsm_impl.o dsm.o ipc.o ipci.o pmsignal.o procarray.o procsignal.o \
sinval.o sinvaladt.o standby.o shmem.o shmqueue.o sinval.o sinvaladt.o standby.o
include $(top_srcdir)/src/backend/common.mk include $(top_srcdir)/src/backend/common.mk
This diff is collapsed.
This diff is collapsed.
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
#include "replication/walreceiver.h" #include "replication/walreceiver.h"
#include "replication/walsender.h" #include "replication/walsender.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/dsm.h"
#include "storage/ipc.h" #include "storage/ipc.h"
#include "storage/pg_shmem.h" #include "storage/pg_shmem.h"
#include "storage/pmsignal.h" #include "storage/pmsignal.h"
...@@ -249,6 +250,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port) ...@@ -249,6 +250,10 @@ CreateSharedMemoryAndSemaphores(bool makePrivate, int port)
ShmemBackendArrayAllocation(); ShmemBackendArrayAllocation();
#endif #endif
/* Initialize dynamic shared memory facilities. */
if (!IsUnderPostmaster)
dsm_postmaster_startup();
/* /*
* Now give loadable modules a chance to set up their shmem allocations * Now give loadable modules a chance to set up their shmem allocations
*/ */
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include "replication/walreceiver.h" #include "replication/walreceiver.h"
#include "replication/walsender.h" #include "replication/walsender.h"
#include "storage/bufmgr.h" #include "storage/bufmgr.h"
#include "storage/dsm_impl.h"
#include "storage/standby.h" #include "storage/standby.h"
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/proc.h" #include "storage/proc.h"
...@@ -385,6 +386,7 @@ static const struct config_enum_entry synchronous_commit_options[] = { ...@@ -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 wal_level_options[];
extern const struct config_enum_entry sync_method_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 * GUC option variables that are exported from this module
...@@ -3335,6 +3337,16 @@ static struct config_enum ConfigureNamesEnum[] = ...@@ -3335,6 +3337,16 @@ static struct config_enum ConfigureNamesEnum[] =
NULL, NULL, NULL NULL, NULL, NULL
}, },
{
{"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, {"wal_sync_method", PGC_SIGHUP, WAL_SETTINGS,
gettext_noop("Selects the method used for forcing WAL updates to disk."), gettext_noop("Selects the method used for forcing WAL updates to disk."),
......
...@@ -123,6 +123,13 @@ ...@@ -123,6 +123,13 @@
#work_mem = 1MB # min 64kB #work_mem = 1MB # min 64kB
#maintenance_work_mem = 16MB # min 1MB #maintenance_work_mem = 16MB # min 1MB
#max_stack_depth = 2MB # min 100kB #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 - # - Disk -
......
...@@ -98,6 +98,11 @@ typedef struct ResourceOwnerData ...@@ -98,6 +98,11 @@ typedef struct ResourceOwnerData
int nfiles; /* number of owned temporary files */ int nfiles; /* number of owned temporary files */
File *files; /* dynamically allocated array */ File *files; /* dynamically allocated array */
int maxfiles; /* currently allocated array size */ 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; } ResourceOwnerData;
...@@ -132,6 +137,7 @@ static void PrintPlanCacheLeakWarning(CachedPlan *plan); ...@@ -132,6 +137,7 @@ static void PrintPlanCacheLeakWarning(CachedPlan *plan);
static void PrintTupleDescLeakWarning(TupleDesc tupdesc); static void PrintTupleDescLeakWarning(TupleDesc tupdesc);
static void PrintSnapshotLeakWarning(Snapshot snapshot); static void PrintSnapshotLeakWarning(Snapshot snapshot);
static void PrintFileLeakWarning(File file); static void PrintFileLeakWarning(File file);
static void PrintDSMLeakWarning(dsm_segment *seg);
/***************************************************************************** /*****************************************************************************
...@@ -271,6 +277,21 @@ ResourceOwnerReleaseInternal(ResourceOwner owner, ...@@ -271,6 +277,21 @@ ResourceOwnerReleaseInternal(ResourceOwner owner,
PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]); PrintRelCacheLeakWarning(owner->relrefs[owner->nrelrefs - 1]);
RelationClose(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) else if (phase == RESOURCE_RELEASE_LOCKS)
{ {
...@@ -402,6 +423,7 @@ ResourceOwnerDelete(ResourceOwner owner) ...@@ -402,6 +423,7 @@ ResourceOwnerDelete(ResourceOwner owner)
Assert(owner->ncatrefs == 0); Assert(owner->ncatrefs == 0);
Assert(owner->ncatlistrefs == 0); Assert(owner->ncatlistrefs == 0);
Assert(owner->nrelrefs == 0); Assert(owner->nrelrefs == 0);
Assert(owner->ndsms == 0);
Assert(owner->nplanrefs == 0); Assert(owner->nplanrefs == 0);
Assert(owner->ntupdescs == 0); Assert(owner->ntupdescs == 0);
Assert(owner->nsnapshots == 0); Assert(owner->nsnapshots == 0);
...@@ -438,6 +460,8 @@ ResourceOwnerDelete(ResourceOwner owner) ...@@ -438,6 +460,8 @@ ResourceOwnerDelete(ResourceOwner owner)
pfree(owner->snapshots); pfree(owner->snapshots);
if (owner->files) if (owner->files)
pfree(owner->files); pfree(owner->files);
if (owner->dsms)
pfree(owner->dsms);
pfree(owner); pfree(owner);
} }
...@@ -1230,3 +1254,88 @@ PrintFileLeakWarning(File file) ...@@ -1230,3 +1254,88 @@ PrintFileLeakWarning(File file)
"temporary file leak: File %d still referenced", "temporary file leak: File %d still referenced",
file); 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));
}
...@@ -182,6 +182,7 @@ const char *subdirs[] = { ...@@ -182,6 +182,7 @@ const char *subdirs[] = {
"pg_xlog", "pg_xlog",
"pg_xlog/archive_status", "pg_xlog/archive_status",
"pg_clog", "pg_clog",
"pg_dynshmem",
"pg_notify", "pg_notify",
"pg_serial", "pg_serial",
"pg_snapshots", "pg_snapshots",
......
...@@ -424,6 +424,9 @@ ...@@ -424,6 +424,9 @@
/* Define to 1 if you have the `setsid' function. */ /* Define to 1 if you have the `setsid' function. */
#undef HAVE_SETSID #undef HAVE_SETSID
/* Define to 1 if you have the `shm_open' function. */
#undef HAVE_SHM_OPEN
/* Define to 1 if you have the `sigprocmask' function. */ /* Define to 1 if you have the `sigprocmask' function. */
#undef HAVE_SIGPROCMASK #undef HAVE_SIGPROCMASK
......
/*-------------------------------------------------------------------------
*
* mem.h
* portability definitions for various memory operations
*
* Copyright (c) 2001-2013, PostgreSQL Global Development Group
*
* src/include/portability/mem.h
*
*-------------------------------------------------------------------------
*/
#ifndef MEM_H
#define MEM_H
#define IPCProtection (0600) /* access/modify by user only */
#ifdef SHM_SHARE_MMU /* use intimate shared memory on Solaris */
#define PG_SHMAT_FLAGS SHM_SHARE_MMU
#else
#define PG_SHMAT_FLAGS 0
#endif
/* Linux prefers MAP_ANONYMOUS, but the flag is called MAP_ANON on other systems. */
#ifndef MAP_ANONYMOUS
#define MAP_ANONYMOUS MAP_ANON
#endif
/* BSD-derived systems have MAP_HASSEMAPHORE, but it's not present (or needed) on Linux. */
#ifndef MAP_HASSEMAPHORE
#define MAP_HASSEMAPHORE 0
#endif
#define PG_MMAP_FLAGS (MAP_SHARED|MAP_ANONYMOUS|MAP_HASSEMAPHORE)
/* Some really old systems don't define MAP_FAILED. */
#ifndef MAP_FAILED
#define MAP_FAILED ((void *) -1)
#endif
#endif /* MEM_H */
/*-------------------------------------------------------------------------
*
* dsm.h
* manage dynamic shared memory segments
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/dsm.h
*
*-------------------------------------------------------------------------
*/
#ifndef DSM_H
#define DSM_H
#include "storage/dsm_impl.h"
typedef struct dsm_segment dsm_segment;
/* Initialization function. */
extern void dsm_postmaster_startup(void);
/* Functions that create, update, or remove mappings. */
extern dsm_segment *dsm_create(uint64 size);
extern dsm_segment *dsm_attach(dsm_handle h);
extern void *dsm_resize(dsm_segment *seg, uint64 size);
extern void *dsm_remap(dsm_segment *seg);
extern void dsm_detach(dsm_segment *seg);
/* Resource management functions. */
extern void dsm_keep_mapping(dsm_segment *seg);
extern dsm_segment *dsm_find_mapping(dsm_handle h);
/* Informational functions. */
extern void *dsm_segment_address(dsm_segment *seg);
extern uint64 dsm_segment_map_length(dsm_segment *seg);
extern dsm_handle dsm_segment_handle(dsm_segment *seg);
#endif /* DSM_H */
/*-------------------------------------------------------------------------
*
* dsm_impl.h
* low-level dynamic shared memory primitives
*
* Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* src/include/storage/dsm_impl.h
*
*-------------------------------------------------------------------------
*/
#ifndef DSM_IMPL_H
#define DSM_IMPL_H
/* Dynamic shared memory implementations. */
#define DSM_IMPL_NONE 0
#define DSM_IMPL_POSIX 1
#define DSM_IMPL_SYSV 2
#define DSM_IMPL_WINDOWS 3
#define DSM_IMPL_MMAP 4
/*
* Determine which dynamic shared memory implementations will be supported
* on this platform, and which one will be the default.
*/
#ifdef WIN32
#define USE_DSM_WINDOWS
#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_WINDOWS
#else
#ifdef HAVE_SHM_OPEN
#define USE_DSM_POSIX
#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_POSIX
#endif
#define USE_DSM_SYSV
#ifndef DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE
#define DEFAULT_DYNAMIC_SHARED_MEMORY_TYPE DSM_IMPL_SYSV
#endif
#define USE_DSM_MMAP
#endif
/* GUC. */
extern int dynamic_shared_memory_type;
/*
* Directory for on-disk state.
*
* This is used by all implementations for crash recovery and by the mmap
* implementation for storage.
*/
#define PG_DYNSHMEM_DIR "pg_dynshmem"
#define PG_DYNSHMEM_MMAP_FILE_PREFIX "mmap."
/* A "name" for a dynamic shared memory segment. */
typedef uint32 dsm_handle;
/* All the shared-memory operations we know about. */
typedef enum
{
DSM_OP_CREATE,
DSM_OP_ATTACH,
DSM_OP_DETACH,
DSM_OP_RESIZE,
DSM_OP_DESTROY
} dsm_op;
/* Create, attach to, detach from, resize, or destroy a segment. */
extern bool dsm_impl_op(dsm_op op, dsm_handle handle, uint64 request_size,
void **impl_private, void **mapped_address, uint64 *mapped_size,
int elevel);
/* Some implementations cannot resize segments. Can this one? */
extern bool dsm_impl_can_resize(void);
#endif /* DSM_IMPL_H */
...@@ -80,6 +80,7 @@ typedef enum LWLockId ...@@ -80,6 +80,7 @@ typedef enum LWLockId
OldSerXidLock, OldSerXidLock,
SyncRepLock, SyncRepLock,
BackgroundWorkerLock, BackgroundWorkerLock,
DynamicSharedMemoryControlLock,
/* Individual lock IDs end here */ /* Individual lock IDs end here */
FirstBufMappingLock, FirstBufMappingLock,
FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS, FirstLockMgrLock = FirstBufMappingLock + NUM_BUFFER_PARTITIONS,
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
#ifndef RESOWNER_PRIVATE_H #ifndef RESOWNER_PRIVATE_H
#define RESOWNER_PRIVATE_H #define RESOWNER_PRIVATE_H
#include "storage/dsm.h"
#include "storage/fd.h" #include "storage/fd.h"
#include "storage/lock.h" #include "storage/lock.h"
#include "utils/catcache.h" #include "utils/catcache.h"
...@@ -80,4 +81,11 @@ extern void ResourceOwnerRememberFile(ResourceOwner owner, ...@@ -80,4 +81,11 @@ extern void ResourceOwnerRememberFile(ResourceOwner owner,
extern void ResourceOwnerForgetFile(ResourceOwner owner, extern void ResourceOwnerForgetFile(ResourceOwner owner,
File file); File file);
/* support for dynamic shared memory management */
extern void ResourceOwnerEnlargeDSMs(ResourceOwner owner);
extern void ResourceOwnerRememberDSM(ResourceOwner owner,
dsm_segment *);
extern void ResourceOwnerForgetDSM(ResourceOwner owner,
dsm_segment *);
#endif /* RESOWNER_PRIVATE_H */ #endif /* RESOWNER_PRIVATE_H */
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment