aboutsummaryrefslogtreecommitdiff
path: root/src/backend/storage/ipc/dsm.c
diff options
context:
space:
mode:
authorRobert Haas <rhaas@postgresql.org>2015-03-19 13:02:16 -0400
committerRobert Haas <rhaas@postgresql.org>2015-03-19 13:03:03 -0400
commit12968cf4085409c50f70c6643d92befdb34008f6 (patch)
tree5b54eca34e67eb16387e94c4d3c69acf03678140 /src/backend/storage/ipc/dsm.c
parent5f286c02423f28c8e4c4d07569417a3d4f40f1a0 (diff)
downloadpostgresql-12968cf4085409c50f70c6643d92befdb34008f6.tar.gz
postgresql-12968cf4085409c50f70c6643d92befdb34008f6.zip
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.
Diffstat (limited to 'src/backend/storage/ipc/dsm.c')
-rw-r--r--src/backend/storage/ipc/dsm.c31
1 files changed, 29 insertions, 2 deletions
diff --git a/src/backend/storage/ipc/dsm.c b/src/backend/storage/ipc/dsm.c
index 983d0fa744f..d2b231f7895 100644
--- a/src/backend/storage/ipc/dsm.c
+++ b/src/backend/storage/ipc/dsm.c
@@ -454,9 +454,9 @@ dsm_set_control_handle(dsm_handle h)
* Create a new dynamic shared memory 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 nitems;
@@ -466,6 +466,21 @@ dsm_create(Size size)
if (!dsm_init_done)
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. */
for (;;)
{
@@ -496,9 +511,21 @@ dsm_create(Size size)
/* Verify that we can support an additional mapping. */
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,
(errcode(ERRCODE_INSUFFICIENT_RESOURCES),
errmsg("too many dynamic shared memory segments")));
+ }
/* Enter the handle into a new array slot. */
dsm_control->item[nitems].handle = seg->handle;