Commit 12968cf4 authored by Robert Haas's avatar Robert Haas

Add flags argument to dsm_create.

Right now, there's only one flag, DSM_CREATE_NULL_IF_MAXSEGMENTS,
which suppresses the error that would normally be thrown when the
maximum number of segments already exists, instead returning NULL.
It might be useful to add more flags in the future, such as one to
ignore allocation errors, but I haven't done that here.
parent 5f286c02
...@@ -454,9 +454,9 @@ dsm_set_control_handle(dsm_handle h) ...@@ -454,9 +454,9 @@ dsm_set_control_handle(dsm_handle h)
* Create a new dynamic shared memory segment. * Create a new dynamic shared memory segment.
*/ */
dsm_segment * dsm_segment *
dsm_create(Size size) dsm_create(Size size, int flags)
{ {
dsm_segment *seg = dsm_create_descriptor(); dsm_segment *seg;
uint32 i; uint32 i;
uint32 nitems; uint32 nitems;
...@@ -466,6 +466,21 @@ dsm_create(Size size) ...@@ -466,6 +466,21 @@ dsm_create(Size size)
if (!dsm_init_done) if (!dsm_init_done)
dsm_backend_startup(); dsm_backend_startup();
/*
* If we've been instructed to return NULL when it's not possible to
* register another segment, check whether we seem to be at the limit.
* This allows us to avoid the overhead of creating a new segment only to
* immediately destroy it again. Since we don't take the lock here, the
* value we read might be slightly stale, but the remote possibility of
* an unnecessary failure here shouldn't trouble anyone too much.
*/
if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0
&& dsm_control->nitems >= dsm_control->maxitems)
return NULL;
/* Create a new segment descriptor. */
seg = dsm_create_descriptor();
/* Loop until we find an unused segment identifier. */ /* Loop until we find an unused segment identifier. */
for (;;) for (;;)
{ {
...@@ -496,9 +511,21 @@ dsm_create(Size size) ...@@ -496,9 +511,21 @@ dsm_create(Size size)
/* Verify that we can support an additional mapping. */ /* Verify that we can support an additional mapping. */
if (nitems >= dsm_control->maxitems) if (nitems >= dsm_control->maxitems)
{
if ((flags & DSM_CREATE_NULL_IF_MAXSEGMENTS) != 0)
{
dsm_impl_op(DSM_OP_DESTROY, seg->handle, 0, &seg->impl_private,
&seg->mapped_address, &seg->mapped_size, WARNING);
if (seg->resowner != NULL)
ResourceOwnerForgetDSM(seg->resowner, seg);
dlist_delete(&seg->node);
pfree(seg);
return NULL;
}
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES), (errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("too many dynamic shared memory segments"))); errmsg("too many dynamic shared memory segments")));
}
/* Enter the handle into a new array slot. */ /* Enter the handle into a new array slot. */
dsm_control->item[nitems].handle = seg->handle; dsm_control->item[nitems].handle = seg->handle;
......
...@@ -17,6 +17,8 @@ ...@@ -17,6 +17,8 @@
typedef struct dsm_segment dsm_segment; typedef struct dsm_segment dsm_segment;
#define DSM_CREATE_NULL_IF_MAXSEGMENTS 0x0001
/* Startup and shutdown functions. */ /* Startup and shutdown functions. */
struct PGShmemHeader; /* avoid including pg_shmem.h */ struct PGShmemHeader; /* avoid including pg_shmem.h */
extern void dsm_cleanup_using_control_segment(dsm_handle old_control_handle); extern void dsm_cleanup_using_control_segment(dsm_handle old_control_handle);
...@@ -29,7 +31,7 @@ extern void dsm_set_control_handle(dsm_handle h); ...@@ -29,7 +31,7 @@ extern void dsm_set_control_handle(dsm_handle h);
#endif #endif
/* Functions that create, update, or remove mappings. */ /* Functions that create, update, or remove mappings. */
extern dsm_segment *dsm_create(Size size); extern dsm_segment *dsm_create(Size size, int flags);
extern dsm_segment *dsm_attach(dsm_handle h); extern dsm_segment *dsm_attach(dsm_handle h);
extern void *dsm_resize(dsm_segment *seg, Size size); extern void *dsm_resize(dsm_segment *seg, Size size);
extern void *dsm_remap(dsm_segment *seg); extern void *dsm_remap(dsm_segment *seg);
......
...@@ -125,7 +125,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers, ...@@ -125,7 +125,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers,
segsize = shm_toc_estimate(&e); segsize = shm_toc_estimate(&e);
/* Create the shared memory segment and establish a table of contents. */ /* Create the shared memory segment and establish a table of contents. */
seg = dsm_create(shm_toc_estimate(&e)); seg = dsm_create(shm_toc_estimate(&e), 0);
toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg), toc = shm_toc_create(PG_TEST_SHM_MQ_MAGIC, dsm_segment_address(seg),
segsize); segsize);
......
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