提交 0ac5e5a7 编写于 作者: R Robert Haas

Allow dynamic allocation of shared memory segments.

Patch by myself and Amit Kapila.  Design help from Noah Misch.  Review
by Andres Freund.
上级 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
此差异已折叠。
此差异已折叠。
...@@ -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% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册