Commit 42f4ba33 authored by Éric Thiébaut's avatar Éric Thiébaut
Browse files

Change how shared memory is effectively destroyed

The shared memory is explicitly destroyed by `tao_shared_object_detach`.
Handling of the `TAO_PERSISTENT` bit is done at the shared object level,
not shared memory level.  The same mechanism works for Linux and Mac-OSX.
Another consequence is that TAO shared objects not properly detached will
be persistent.  This is useful for debugging.  Use `ipcs` and `ipcrm -m`
to list and remove such objects.
parent 5f4df579
......@@ -40,15 +40,15 @@
void* tao_shared_memory_create(
tao_shmid* shmid_ptr,
size_t size,
unsigned flags)
unsigned perms)
{
void* addr = BAD_SHM_ADDR;
// Create a new segment of shared memory and get its identifier. Note that
// `shmget` guarantees that the contents of the shared memory segment is
// zero-filled when `IPC_CREAT` and `IPC_EXCL` are both set.
int perms = (flags & PERMS_MASK) | (IPC_CREAT|IPC_EXCL);
int shmid = shmget(IPC_PRIVATE, size, perms);
int shmid = shmget(
IPC_PRIVATE, size, (perms & PERMS_MASK) | (IPC_CREAT | IPC_EXCL));
if (shmid == -1) {
tao_push_system_error("shmget");
goto error;
......@@ -61,15 +61,6 @@ void* tao_shared_memory_create(
goto error;
}
// Unless persistent shared memory is requested, manage to destroy the
// shared memory segment associated with the object on last detach.
if ((flags & TAO_PERSISTENT) == 0) {
if (shmctl(shmid, IPC_RMID, NULL) != 0) {
tao_push_system_error("shmctl");
goto error;
}
}
// Store shared memory identifier and return attachment address.
if (shmid_ptr != NULL) {
*shmid_ptr = shmid;
......@@ -171,14 +162,9 @@ tao_shared_object* tao_shared_object_create(
}
// Create shared memory with at least read and write access for the caller.
// On Mac OS X destroying shared memory segment must be deferred upon last
// detach.
flags |= (S_IRUSR|S_IWUSR);
#ifdef __APPLE__
flags |= TAO_PERSISTENT;
#endif
unsigned perms = (flags & PERMS_MASK) | (S_IRUSR | S_IWUSR);
tao_shmid shmid;
tao_shared_object* obj = tao_shared_memory_create(&shmid, size, flags);
tao_shared_object* obj = tao_shared_memory_create(&shmid, size, perms);
if (obj == NULL) {
return NULL;
}
......@@ -234,13 +220,13 @@ tao_shared_object* tao_shared_object_attach(
goto detach;
}
// Atomically increment the number of attachments.
// Atomically increment the number of attachments and check whether object
// is about to be destroyed. Note that the `flags` member is constant and
// can be safely read without locking the object.
int64_t nrefs_before = atomic_fetch_add_explicit(
&obj->nrefs, 1, memory_order_relaxed);
// Check whether object is about to be destroyed. Note that the `flags`
// member is constant and can be safely read without locking the object.
if (nrefs_before < 1 && (obj->flags & TAO_PERSISTENT) == 0) {
bool destroyed = (nrefs_before < 1 && (obj->flags & TAO_PERSISTENT) == 0);
if (destroyed) {
tao_push_error(__func__, TAO_DESTROYED);
goto detach;
}
......@@ -260,21 +246,19 @@ tao_status tao_shared_object_detach(
return TAO_ERROR;
}
// Atomically decrement the number of attachments.
// Atomically decrement the number of attachments and check whether object
// must be destroyed. Note that the `flags` member is constant and can be
// safely read without locking the object.
int64_t nrefs_before = atomic_fetch_sub_explicit(
&obj->nrefs, 1, memory_order_relaxed);
bool destroy = (nrefs_before == 1 && (obj->flags & TAO_PERSISTENT) == 0);
// Check whether object must be destroyed. Note that the `flags` member is
// constant and can be safely read without locking the object.
// If object is no longer referenced, destroy the mutex and the condition
// variable of the shared object. Compared to `tao_mutex_destroy`, there
// should be no needs to wait for the mutex to be released (because an
// unreferenced object should not be locked).
tao_status status = TAO_OK;
if (nrefs_before == 1 && (obj->flags & TAO_PERSISTENT) == 0) {
// Object is no longer referenced and must be destroyed. The
// associated resources (the mutex and the condition variable) are
// destroyed first, then shared memory segment is removed.
// Compared to `tao_mutex_destroy`, there should be no needs to wait for
// the mutex to be released (because an unreferenced object should not
// be locked).
if (destroy) {
int code = pthread_mutex_destroy(&obj->mutex);
if (code != 0) {
tao_push_error("pthread_mutex_destroy", code);
......@@ -285,21 +269,22 @@ tao_status tao_shared_object_detach(
tao_push_error("pthread_cond_destroy", code);
status = TAO_ERROR;
}
#ifdef __APPLE__
// Destroying shared memory has been deferred until last detach on
// Mac-OS-X.
if (shmctl(obj->shmid, IPC_RMID, NULL) != 0) {
tao_push_system_error("shmctl");
status = TAO_ERROR;
}
#endif
}
// Detach shared memory.
tao_shmid shmid = obj->shmid;
if (shmdt(obj) != 0) {
tao_push_system_error("shmdt");
status = TAO_ERROR;
}
if (destroy) {
// Eventually destroy the shared memory segment. This must be done after
// last detach on Mac-OS.
if (shmctl(shmid, IPC_RMID, NULL) != 0) {
tao_push_system_error("shmctl");
status = TAO_ERROR;
}
}
return status;
}
......
......@@ -67,18 +67,15 @@ typedef int32_t tao_shmid;
*
* @param size Total number of bytes to allocate.
*
* @param flags A combination of bits. The least significant 9 bits
* specify the permissions granted to the owner, group, and
* others as for the system `open(2)` function. The bit @ref
* TAO_PERSISTENT can be set to create persistent shared
* memory. If this bit is not set, the shared memory will be
* destroyed upon last detach.
* @param perms A combination of bits specifying the permissions granted to
* the owner, group, and others as for the system `open(2)`
* function.
*
* @return The location of the shared memory segment in the caller address
* space or `NULL` in case of failure.
*
* @see TAO_PERSISTENT, TAO_BAD_SHMID, tao_shared_memory_attach,
* tao_shared_memory_detach, tao_shared_memory_destroy.
* @see TAO_BAD_SHMID, tao_shared_memory_attach, tao_shared_memory_detach,
* tao_shared_memory_destroy.
*/
extern void* tao_shared_memory_create(
tao_shmid* shmid_ptr,
......
Supports Markdown
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