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.
This commit is contained in:
Robert Haas 2015-03-19 13:02:16 -04:00
parent 5f286c0242
commit 12968cf408
3 changed files with 33 additions and 4 deletions

View File

@ -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;

View File

@ -17,6 +17,8 @@
typedef struct dsm_segment dsm_segment;
#define DSM_CREATE_NULL_IF_MAXSEGMENTS 0x0001
/* Startup and shutdown functions. */
struct PGShmemHeader; /* avoid including pg_shmem.h */
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);
#endif
/* 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 void *dsm_resize(dsm_segment *seg, Size size);
extern void *dsm_remap(dsm_segment *seg);

View File

@ -125,7 +125,7 @@ setup_dynamic_shared_memory(int64 queue_size, int nworkers,
segsize = shm_toc_estimate(&e);
/* 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),
segsize);