|
|
|
|
@ -127,14 +127,9 @@ int dynamic_shared_memory_type; |
|
|
|
|
* map it. |
|
|
|
|
* |
|
|
|
|
* DSM_OP_ATTACH. Map the segment, whose size must be the request_size. |
|
|
|
|
* The segment may already be mapped; any existing mapping should be removed |
|
|
|
|
* before creating a new one. |
|
|
|
|
* |
|
|
|
|
* DSM_OP_DETACH. Unmap the segment. |
|
|
|
|
* |
|
|
|
|
* DSM_OP_RESIZE. Resize the segment to the given request_size and |
|
|
|
|
* remap the segment at that new size. |
|
|
|
|
* |
|
|
|
|
* DSM_OP_DESTROY. Unmap the segment, if it is mapped. Destroy the |
|
|
|
|
* segment. |
|
|
|
|
* |
|
|
|
|
@ -142,8 +137,7 @@ int dynamic_shared_memory_type; |
|
|
|
|
* op: The operation to be performed. |
|
|
|
|
* handle: The handle of an existing object, or for DSM_OP_CREATE, the |
|
|
|
|
* a new handle the caller wants created. |
|
|
|
|
* request_size: For DSM_OP_CREATE, the requested size. For DSM_OP_RESIZE, |
|
|
|
|
* the new size. Otherwise, 0. |
|
|
|
|
* request_size: For DSM_OP_CREATE, the requested size. Otherwise, 0. |
|
|
|
|
* impl_private: Private, implementation-specific data. Will be a pointer |
|
|
|
|
* to NULL for the first operation on a shared memory segment within this |
|
|
|
|
* backend; thereafter, it will point to the value to which it was set |
|
|
|
|
@ -165,7 +159,7 @@ dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
void **impl_private, void **mapped_address, Size *mapped_size, |
|
|
|
|
int elevel) |
|
|
|
|
{ |
|
|
|
|
Assert(op == DSM_OP_CREATE || op == DSM_OP_RESIZE || request_size == 0); |
|
|
|
|
Assert(op == DSM_OP_CREATE || request_size == 0); |
|
|
|
|
Assert((op != DSM_OP_CREATE && op != DSM_OP_ATTACH) || |
|
|
|
|
(*mapped_address == NULL && *mapped_size == 0)); |
|
|
|
|
|
|
|
|
|
@ -198,31 +192,6 @@ dsm_impl_op(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Does the current dynamic shared memory implementation support resizing |
|
|
|
|
* segments? (The answer here could be platform-dependent in the future, |
|
|
|
|
* since AIX allows shmctl(shmid, SHM_RESIZE, &buffer), though you apparently |
|
|
|
|
* can't resize segments to anything larger than 256MB that way. For now, |
|
|
|
|
* we keep it simple.) |
|
|
|
|
*/ |
|
|
|
|
bool |
|
|
|
|
dsm_impl_can_resize(void) |
|
|
|
|
{ |
|
|
|
|
switch (dynamic_shared_memory_type) |
|
|
|
|
{ |
|
|
|
|
case DSM_IMPL_POSIX: |
|
|
|
|
return true; |
|
|
|
|
case DSM_IMPL_SYSV: |
|
|
|
|
return false; |
|
|
|
|
case DSM_IMPL_WINDOWS: |
|
|
|
|
return false; |
|
|
|
|
case DSM_IMPL_MMAP: |
|
|
|
|
return true; |
|
|
|
|
default: |
|
|
|
|
return false; /* should not happen */ |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
#ifdef USE_DSM_POSIX |
|
|
|
|
/*
|
|
|
|
|
* Operating system primitives to support POSIX shared memory. |
|
|
|
|
@ -296,7 +265,7 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're attaching the segment, determine the current size; if we are |
|
|
|
|
* creating or resizing the segment, set the size to the requested value. |
|
|
|
|
* creating the segment, set the size to the requested value. |
|
|
|
|
*/ |
|
|
|
|
if (op == DSM_OP_ATTACH) |
|
|
|
|
{ |
|
|
|
|
@ -319,16 +288,14 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
} |
|
|
|
|
request_size = st.st_size; |
|
|
|
|
} |
|
|
|
|
else if (*mapped_size != request_size && |
|
|
|
|
dsm_impl_posix_resize(fd, request_size) != 0) |
|
|
|
|
else if (dsm_impl_posix_resize(fd, request_size) != 0) |
|
|
|
|
{ |
|
|
|
|
int save_errno; |
|
|
|
|
|
|
|
|
|
/* Back out what's already been done. */ |
|
|
|
|
save_errno = errno; |
|
|
|
|
close(fd); |
|
|
|
|
if (op == DSM_OP_CREATE) |
|
|
|
|
shm_unlink(name); |
|
|
|
|
shm_unlink(name); |
|
|
|
|
errno = save_errno; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
@ -346,35 +313,6 @@ dsm_impl_posix(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're reattaching or resizing, we must remove any existing mapping, |
|
|
|
|
* unless we've already got the right thing mapped. |
|
|
|
|
*/ |
|
|
|
|
if (*mapped_address != NULL) |
|
|
|
|
{ |
|
|
|
|
if (*mapped_size == request_size) |
|
|
|
|
return true; |
|
|
|
|
if (munmap(*mapped_address, *mapped_size) != 0) |
|
|
|
|
{ |
|
|
|
|
int save_errno; |
|
|
|
|
|
|
|
|
|
/* Back out what's already been done. */ |
|
|
|
|
save_errno = errno; |
|
|
|
|
close(fd); |
|
|
|
|
if (op == DSM_OP_CREATE) |
|
|
|
|
shm_unlink(name); |
|
|
|
|
errno = save_errno; |
|
|
|
|
|
|
|
|
|
ereport(elevel, |
|
|
|
|
(errcode_for_dynamic_shared_memory(), |
|
|
|
|
errmsg("could not unmap shared memory segment \"%s\": %m", |
|
|
|
|
name))); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
*mapped_address = NULL; |
|
|
|
|
*mapped_size = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Map it. */ |
|
|
|
|
address = mmap(NULL, request_size, PROT_READ | PROT_WRITE, |
|
|
|
|
MAP_SHARED | MAP_HASSEMAPHORE | MAP_NOSYNC, fd, 0); |
|
|
|
|
@ -457,10 +395,9 @@ dsm_impl_posix_resize(int fd, off_t size) |
|
|
|
|
* Operating system primitives to support System V shared memory. |
|
|
|
|
* |
|
|
|
|
* System V shared memory segments are manipulated using shmget(), shmat(), |
|
|
|
|
* shmdt(), and shmctl(). There's no portable way to resize such |
|
|
|
|
* segments. As the default allocation limits for System V shared memory |
|
|
|
|
* are usually quite low, the POSIX facilities may be preferable; but |
|
|
|
|
* those are not supported everywhere. |
|
|
|
|
* shmdt(), and shmctl(). As the default allocation limits for System V |
|
|
|
|
* shared memory are usually quite low, the POSIX facilities may be |
|
|
|
|
* preferable; but those are not supported everywhere. |
|
|
|
|
*/ |
|
|
|
|
static bool |
|
|
|
|
dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
@ -473,13 +410,6 @@ dsm_impl_sysv(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
char name[64]; |
|
|
|
|
int *ident_cache; |
|
|
|
|
|
|
|
|
|
/* Resize is not supported for System V shared memory. */ |
|
|
|
|
if (op == DSM_OP_RESIZE) |
|
|
|
|
{ |
|
|
|
|
elog(elevel, "System V shared memory segments cannot be resized"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Since resize isn't supported, reattach is a no-op. */ |
|
|
|
|
if (op == DSM_OP_ATTACH && *mapped_address != NULL) |
|
|
|
|
return true; |
|
|
|
|
@ -670,13 +600,6 @@ dsm_impl_windows(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
char name[64]; |
|
|
|
|
MEMORY_BASIC_INFORMATION info; |
|
|
|
|
|
|
|
|
|
/* Resize is not supported for Windows shared memory. */ |
|
|
|
|
if (op == DSM_OP_RESIZE) |
|
|
|
|
{ |
|
|
|
|
elog(elevel, "Windows shared memory segments cannot be resized"); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Since resize isn't supported, reattach is a no-op. */ |
|
|
|
|
if (op == DSM_OP_ATTACH && *mapped_address != NULL) |
|
|
|
|
return true; |
|
|
|
|
@ -905,7 +828,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're attaching the segment, determine the current size; if we are |
|
|
|
|
* creating or resizing the segment, set the size to the requested value. |
|
|
|
|
* creating the segment, set the size to the requested value. |
|
|
|
|
*/ |
|
|
|
|
if (op == DSM_OP_ATTACH) |
|
|
|
|
{ |
|
|
|
|
@ -928,24 +851,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
} |
|
|
|
|
request_size = st.st_size; |
|
|
|
|
} |
|
|
|
|
else if (*mapped_size > request_size && ftruncate(fd, request_size)) |
|
|
|
|
{ |
|
|
|
|
int save_errno; |
|
|
|
|
|
|
|
|
|
/* Back out what's already been done. */ |
|
|
|
|
save_errno = errno; |
|
|
|
|
CloseTransientFile(fd); |
|
|
|
|
if (op == DSM_OP_CREATE) |
|
|
|
|
unlink(name); |
|
|
|
|
errno = save_errno; |
|
|
|
|
|
|
|
|
|
ereport(elevel, |
|
|
|
|
(errcode_for_dynamic_shared_memory(), |
|
|
|
|
errmsg("could not resize shared memory segment \"%s\" to %zu bytes: %m", |
|
|
|
|
name, request_size))); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
else if (*mapped_size < request_size) |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
/*
|
|
|
|
|
* Allocate a buffer full of zeros. |
|
|
|
|
@ -985,8 +891,7 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
/* Back out what's already been done. */ |
|
|
|
|
save_errno = errno; |
|
|
|
|
CloseTransientFile(fd); |
|
|
|
|
if (op == DSM_OP_CREATE) |
|
|
|
|
unlink(name); |
|
|
|
|
unlink(name); |
|
|
|
|
errno = save_errno ? save_errno : ENOSPC; |
|
|
|
|
|
|
|
|
|
ereport(elevel, |
|
|
|
|
@ -997,35 +902,6 @@ dsm_impl_mmap(dsm_op op, dsm_handle handle, Size request_size, |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* If we're reattaching or resizing, we must remove any existing mapping, |
|
|
|
|
* unless we've already got the right thing mapped. |
|
|
|
|
*/ |
|
|
|
|
if (*mapped_address != NULL) |
|
|
|
|
{ |
|
|
|
|
if (*mapped_size == request_size) |
|
|
|
|
return true; |
|
|
|
|
if (munmap(*mapped_address, *mapped_size) != 0) |
|
|
|
|
{ |
|
|
|
|
int save_errno; |
|
|
|
|
|
|
|
|
|
/* Back out what's already been done. */ |
|
|
|
|
save_errno = errno; |
|
|
|
|
CloseTransientFile(fd); |
|
|
|
|
if (op == DSM_OP_CREATE) |
|
|
|
|
unlink(name); |
|
|
|
|
errno = save_errno; |
|
|
|
|
|
|
|
|
|
ereport(elevel, |
|
|
|
|
(errcode_for_dynamic_shared_memory(), |
|
|
|
|
errmsg("could not unmap shared memory segment \"%s\": %m", |
|
|
|
|
name))); |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
*mapped_address = NULL; |
|
|
|
|
*mapped_size = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* Map it. */ |
|
|
|
|
address = mmap(NULL, request_size, PROT_READ | PROT_WRITE, |
|
|
|
|
MAP_SHARED | MAP_HASSEMAPHORE | MAP_NOSYNC, fd, 0); |
|
|
|
|
|