summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/shm.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2003-11-19 18:50:23 +0000
committerCorinna Vinschen <corinna@vinschen.de>2003-11-19 18:50:23 +0000
commita6df500f7daacc08cd7c66f4212cb6ab6cbe803e (patch)
treef81a85de384145f0d97d3f717f54359b00800e3f /winsup/cygwin/shm.cc
parent282113ba894449ed17e85b296cf0760d5206ac8d (diff)
downloadcygnal-a6df500f7daacc08cd7c66f4212cb6ab6cbe803e.tar.gz
cygnal-a6df500f7daacc08cd7c66f4212cb6ab6cbe803e.tar.bz2
cygnal-a6df500f7daacc08cd7c66f4212cb6ab6cbe803e.zip
* cygserver.h (client_request::request_code_t): Add
CYGSERVER_REQUEST_MSG and CYGSERVER_REQUEST_SEM. (admininstrator_group_sid): Add extern declaration. * cygserver_ipc.h: Rewrite. * cygserver_msg.h: New file. * cygserver_sem.h: New file. * cygserver_shm.h: More or less rewrite. * cygwin.din: Add msgctl, msgget, msgrcv, msgsnd, semctl, semget and semop. * msg.cc: Rewrite. * safe_memory.h: Remove. * sem.cc: Rewrite. * shm.cc: Rewrite. * include/cygwin/ipc.h: Use appropriate guard. (struct ipc_perm): Add seq. (IPCID_TO_IX): New define from BSD. (IPCID_TO_SEQ): Ditto. (IXSEQ_TO_IPCID): Ditto. (IPC_R): Ditto. (IPC_W): Ditto. (IPC_M): Ditto. * include/cygwin/msg.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (msgqnum_t): Define unsigned. (msglen_t): Ditto. (struct msqid_ds): Add msg_first and msg_last. (struct msginfo): Remove msgpool. Add msgssz and msgseg. * include/cygwin/sem.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (SEM_UNDO): Define appropriately. (struct semid_ds): Add sem_base. (struct seminfo): Add semmap and semusz. (SEM_A): New define from BSD. (SEM_R): Ditto. (SEM_ALLOC): Ditto. (union semun): Define. * include/cygwin/shm.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (SHMLBA): Define using cygwin_internal(CW_GET_SHMLBA) call. (struct shmid_ds): Add shm_internal. (struct shm_info): Rename shm_ids to used_ids as in BSD. Add define for shm_ids. * include/cygwin/sysproto.h: New file. * include/cygwin/version.h: Bump API minor number. * include/sys/ipc.h: New file. * include/sys/msg.h: New file. * include/sys/queue.h: New file from BSD. * include/sys/sem.h: New file. * include/sys/shm.h: New file. * include/sys/sysproto.h: New file.
Diffstat (limited to 'winsup/cygwin/shm.cc')
-rw-r--r--winsup/cygwin/shm.cc865
1 files changed, 257 insertions, 608 deletions
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
index a5e7c31df..ef3248f4f 100644
--- a/winsup/cygwin/shm.cc
+++ b/winsup/cygwin/shm.cc
@@ -1,9 +1,6 @@
-/* shm.cc: Single unix specification IPC interface for Cygwin.
+/* shm.cc: XSI IPC interface for Cygwin.
- Copyright 2002,2003 Red Hat, Inc.
-
- Written by Conrad Scott <conrad.scott@dsl.pipex.com>.
- Based on code by Robert Collins <robert.collins@hotmail.com>.
+ Copyright 2003 Red Hat, Inc.
This file is part of Cygwin.
@@ -15,697 +12,349 @@ details. */
#include "cygerrno.h"
#ifdef USE_SERVER
#include <sys/types.h>
-
-#include <assert.h>
+#include <sys/queue.h>
#include <stdio.h>
#include <unistd.h>
-#include "safe_memory.h"
+#include "pinfo.h"
#include "sigproc.h"
#include "cygserver_ipc.h"
#include "cygserver_shm.h"
-/*---------------------------------------------------------------------------*
- * class client_shmmgr
- *
- * A singleton class.
- *---------------------------------------------------------------------------*/
-
-#define shmmgr (client_shmmgr::instance ())
-
-class client_shmmgr
-{
-private:
- class segment_t
- {
- public:
- const int shmid;
- const void *const shmaddr;
- const int shmflg;
- HANDLE hFileMap; // Updated by fixup_shms_after_fork ().
-
- segment_t *next;
-
- segment_t (const int shmid, const void *const shmaddr, const int shmflg,
- const HANDLE hFileMap)
- : shmid (shmid), shmaddr (shmaddr), shmflg (shmflg), hFileMap (hFileMap),
- next (NULL)
- {}
- };
-
-public:
- static client_shmmgr & instance ();
-
- void *shmat (int shmid, const void *, int shmflg);
- int shmctl (int shmid, int cmd, struct shmid_ds *);
- int shmdt (const void *);
- int shmget (key_t, size_t, int shmflg);
-
- int fixup_shms_after_fork ();
-
-private:
- static NO_COPY client_shmmgr *_instance;
-
- CRITICAL_SECTION _segments_lock;
- static segment_t *_segments_head; // List of attached segs by shmaddr.
-
- static long _shmat_cnt; // No. of attached segs; for info. only.
-
- client_shmmgr ();
- ~client_shmmgr ();
-
- // Undefined (as this class is a singleton):
- client_shmmgr (const client_shmmgr &);
- client_shmmgr & operator= (const client_shmmgr &);
-
- segment_t *find (const void *, segment_t **previous = NULL);
-
- void *attach (int shmid, const void *, int shmflg, HANDLE & hFileMap);
-
- segment_t *new_segment (int shmid, const void *, int shmflg, HANDLE);
-};
-
-/* static */ NO_COPY client_shmmgr *client_shmmgr::_instance;
-
-/* The following two variables must be inherited by child processes
- * since they are used by fixup_shms_after_fork () to re-attach to the
- * parent's shm segments.
+/*
+ * client_request_shm Constructors
*/
-/* static */ client_shmmgr::segment_t *client_shmmgr::_segments_head;
-/* static */ long client_shmmgr::_shmat_cnt;
-/*---------------------------------------------------------------------------*
- * client_shmmgr::instance ()
- *---------------------------------------------------------------------------*/
-
-client_shmmgr &
-client_shmmgr::instance ()
+client_request_shm::client_request_shm (int shmid,
+ const void *shmaddr,
+ int shmflg)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
{
- if (!_instance)
- _instance = safe_new0 (client_shmmgr);
+ _parameters.in.shmop = SHMOP_shmat;
+ ipc_set_proc_info (_parameters.in.ipcblk);
- assert (_instance);
+ _parameters.in.atargs.shmid = shmid;
+ _parameters.in.atargs.shmaddr = shmaddr;
+ _parameters.in.atargs.shmflg = shmflg;
- return *_instance;
+ msglen (sizeof (_parameters.in));
}
-/*---------------------------------------------------------------------------*
- * client_shmmgr::shmat ()
- *---------------------------------------------------------------------------*/
-
-void *
-client_shmmgr::shmat (const int shmid,
- const void *const shmaddr,
- const int shmflg)
+client_request_shm::client_request_shm (int shmid,
+ int cmd,
+ struct shmid_ds *buf)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
{
- syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)",
- shmid, shmaddr, shmflg);
-
- EnterCriticalSection (&_segments_lock);
-
- HANDLE hFileMap = NULL;
-
- void *const ptr = attach (shmid, shmaddr, shmflg, hFileMap);
-
- if (ptr)
- new_segment (shmid, ptr, shmflg, hFileMap);
-
- LeaveCriticalSection (&_segments_lock);
+ _parameters.in.shmop = SHMOP_shmctl;
+ ipc_set_proc_info (_parameters.in.ipcblk);
- if (ptr)
- syscall_printf ("%p = shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)",
- ptr, shmid, shmaddr, shmflg);
- // else
- // See the syscall_printf in client_shmmgr::attach ().
+ _parameters.in.ctlargs.shmid = shmid;
+ _parameters.in.ctlargs.cmd = cmd;
+ _parameters.in.ctlargs.buf = buf;
- return (ptr ? ptr : (void *) -1);
+ msglen (sizeof (_parameters.in));
}
-/*---------------------------------------------------------------------------*
- * client_shmmgr::shmctl ()
- *---------------------------------------------------------------------------*/
-
-int
-client_shmmgr::shmctl (const int shmid,
- const int cmd,
- struct shmid_ds *const buf)
+client_request_shm::client_request_shm (const void *shmaddr)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
{
- syscall_printf ("shmctl (shmid = %d, cmd = 0x%x, buf = %p)",
- shmid, cmd, buf);
-
- // Check parameters and set up in parameters as required.
-
- const struct shmid_ds *in_buf = NULL;
-
- switch (cmd)
- {
- case IPC_SET:
- if (__check_invalid_read_ptr_errno (buf, sizeof (struct shmid_ds)))
- {
- syscall_printf (("-1 [EFAULT] = "
- "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
- shmid, cmd, buf);
- set_errno (EFAULT);
- return -1;
- }
- in_buf = buf;
- break;
-
- case IPC_STAT:
- case SHM_STAT:
- if (__check_null_invalid_struct_errno (buf, sizeof (struct shmid_ds)))
- {
- syscall_printf (("-1 [EFAULT] = "
- "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
- shmid, cmd, buf);
- set_errno (EFAULT);
- return -1;
- }
- break;
-
- case IPC_INFO:
- if (__check_null_invalid_struct_errno (buf, sizeof (struct shminfo)))
- {
- syscall_printf (("-1 [EFAULT] = "
- "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
- shmid, cmd, buf);
- set_errno (EFAULT);
- return -1;
- }
- break;
-
- case SHM_INFO:
- if (__check_null_invalid_struct_errno (buf, sizeof (struct shm_info)))
- {
- syscall_printf (("-1 [EFAULT] = "
- "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
- shmid, cmd, buf);
- set_errno (EFAULT);
- return -1;
- }
- break;
- }
-
- // Create and issue the command.
-
- client_request_shm request (shmid, cmd, in_buf);
-
- if (request.make_request () == -1 || request.error_code ())
- {
- syscall_printf (("-1 [%d] = "
- "shmctl (shmid = %d, cmd = 0x%x, buf = %p)"),
- request.error_code (), shmid, cmd, buf);
- set_errno (request.error_code ());
- return -1;
- }
-
- // Some commands require special processing for their out parameters.
-
- int result = 0;
-
- switch (cmd)
- {
- case IPC_STAT:
- *buf = request.ds ();
- break;
-
- case IPC_INFO:
- *(struct shminfo *) buf = request.shminfo ();
- break;
-
- case SHM_STAT: // ipcs(8) i'face.
- result = request.shmid ();
- *buf = request.ds ();
- break;
-
- case SHM_INFO: // ipcs(8) i'face.
- result = request.shmid ();
- *(struct shm_info *) buf = request.shm_info ();
- break;
- }
+ _parameters.in.shmop = SHMOP_shmdt;
+ ipc_set_proc_info (_parameters.in.ipcblk);
- syscall_printf ("%d = shmctl (shmid = %d, cmd = 0x%x, buf = %p)",
- result, shmid, cmd, buf);
+ _parameters.in.dtargs.shmaddr = shmaddr;
- return result;
+ msglen (sizeof (_parameters.in));
}
-/*---------------------------------------------------------------------------*
- * client_shmmgr::shmdt ()
- *
- * According to Posix, the only error condition for this system call
- * is EINVAL if shmaddr is not the address of the start of an attached
- * shared memory segment. Given that, all other errors just generate
- * tracing noise.
- *---------------------------------------------------------------------------*/
-
-int
-client_shmmgr::shmdt (const void *const shmaddr)
+client_request_shm::client_request_shm (key_t key,
+ size_t size,
+ int shmflg)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
{
- syscall_printf ("shmdt (shmaddr = %p)", shmaddr);
-
- EnterCriticalSection (&_segments_lock);
-
- segment_t *previous = NULL;
-
- segment_t *const segptr = find (shmaddr, &previous);
-
- if (!segptr)
- {
- LeaveCriticalSection (&_segments_lock);
- syscall_printf ("-1 [EINVAL] = shmdt (shmaddr = %p)", shmaddr);
- set_errno (EINVAL);
- return -1;
- }
-
- assert (previous ? previous->next == segptr : _segments_head == segptr);
-
- if (previous)
- previous->next = segptr->next;
- else
- _segments_head = segptr->next;
-
- LeaveCriticalSection (&_segments_lock);
-
- const long cnt = InterlockedDecrement (&_shmat_cnt);
- assert (cnt >= 0);
-
- if (!UnmapViewOfFile ((void *) shmaddr))
- syscall_printf (("failed to unmap view "
- "[shmid = %d, handle = %p, shmaddr = %p]:"
- "%E"),
- segptr->shmid, segptr->hFileMap, shmaddr);
+ _parameters.in.shmop = SHMOP_shmget;
+ ipc_set_proc_info (_parameters.in.ipcblk);
- assert (segptr->hFileMap);
+ _parameters.in.getargs.key = key;
+ _parameters.in.getargs.size = size;
+ _parameters.in.getargs.shmflg = shmflg;
- if (!CloseHandle (segptr->hFileMap))
- syscall_printf (("failed to close file map handle "
- "[shmid = %d, handle = %p]: %E"),
- segptr->shmid, segptr->hFileMap);
+ msglen (sizeof (_parameters.in));
+}
- client_request_shm request (segptr->shmid);
+client_request_shm::client_request_shm (proc *p1)
+ : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
+{
+ _parameters.in.shmop = SHMOP_shmfork;
+ ipc_set_proc_info (_parameters.in.ipcblk);
- if (request.make_request () == -1 || request.error_code ())
- syscall_printf ("shmdt request failed [shmid = %d, handle = %p]: %s",
- segptr->shmid, segptr->hFileMap,
- strerror (request.error_code ()));
+ _parameters.in.forkargs = *p1;
+}
- safe_delete (segptr);
+/* List of shmid's with file mapping HANDLE and size, returned by shmget. */
+struct shm_shmid_list {
+ SLIST_ENTRY(shm_shmid_list) ssh_next;
+ int shmid;
+ vm_object_t hdl;
+ size_t size;
+};
- syscall_printf ("0 = shmdt (shmaddr = %p)", shmaddr);
+static SLIST_HEAD(, shm_shmid_list) ssh_list;
- return 0;
-}
+/* List of attached mappings, as returned by shmat. */
+struct shm_attached_list {
+ SLIST_ENTRY(shm_attached_list) sph_next;
+ vm_object_t ptr;
+ vm_object_t hdl;
+ size_t size;
+ int access;
+};
-/*---------------------------------------------------------------------------*
- * client_shmmgr::shmget ()
- *---------------------------------------------------------------------------*/
+static SLIST_HEAD(, shm_attached_list) sph_list;
-int
-client_shmmgr::shmget (const key_t key, const size_t size, const int shmflg)
+int __stdcall
+fixup_shms_after_fork ()
{
- syscall_printf ("shmget (key = 0x%016X, size = %u, shmflg = 0%o)",
- key, size, shmflg);
+ if (!SLIST_FIRST (&sph_list))
+ return 0;
+ pinfo p (myself->ppid);
+ proc parent = { myself->ppid, p->dwProcessId, p->uid, p->gid };
- client_request_shm request (key, size, shmflg);
-
- if (request.make_request () == -1 || request.error_code ())
+ client_request_shm request (&parent);
+ if (request.make_request () == -1 || request.retval () == -1)
{
- syscall_printf (("-1 [%d] = "
- "shmget (key = 0x%016X, size = %u, shmflg = 0%o)"),
- request.error_code (),
- key, size, shmflg);
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
set_errno (request.error_code ());
- return -1;
+ return 0;
+ }
+ shm_attached_list *sph_entry;
+ /* Remove map from list... */
+ SLIST_FOREACH (sph_entry, &sph_list, sph_next)
+ {
+ vm_object_t ptr = MapViewOfFileEx(sph_entry->hdl, sph_entry->access,
+ 0, 0, sph_entry->size, sph_entry->ptr);
+ if (ptr != sph_entry->ptr)
+ api_fatal ("MapViewOfFileEx (%p), %E. Terminating.", sph_entry->ptr);
}
-
- syscall_printf (("%d = shmget (key = 0x%016X, size = %u, shmflg = 0%o)"),
- request.shmid (),
- key, size, shmflg);
-
- return request.shmid ();
-}
-
-/*---------------------------------------------------------------------------*
- * client_shmmgr::fixup_shms_after_fork ()
- *
- * The hFileMap handles are non-inheritable: so they have to be
- * re-acquired from cygserver.
- *
- * Nb. This routine need not be thread-safe as it is only called at startup.
- *---------------------------------------------------------------------------*/
-
-int
-client_shmmgr::fixup_shms_after_fork ()
-{
- debug_printf ("re-attaching to shm segments: %d attached", _shmat_cnt);
-
- {
- int length = 0;
- for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
- length += 1;
-
- if (_shmat_cnt != length)
- {
- system_printf (("state inconsistent: "
- "_shmat_cnt = %d, length of segments list = %d"),
- _shmat_cnt, length);
- return 1;
- }
- }
-
- for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
- if (!attach (segptr->shmid,
- segptr->shmaddr,
- segptr->shmflg & ~SHM_RND,
- segptr->hFileMap))
- {
- system_printf ("fatal error re-attaching to shm segment %d",
- segptr->shmid);
- return 1;
- }
-
- if (_shmat_cnt)
- debug_printf ("re-attached all %d shm segments", _shmat_cnt);
-
return 0;
}
+#endif /* USE_SERVER */
-/*---------------------------------------------------------------------------*
- * client_shmmgr::client_shmmgr ()
- *---------------------------------------------------------------------------*/
-
-client_shmmgr::client_shmmgr ()
-{
- InitializeCriticalSection (&_segments_lock);
-}
-
-/*---------------------------------------------------------------------------*
- * client_shmmgr::~client_shmmgr ()
- *---------------------------------------------------------------------------*/
-
-client_shmmgr::~client_shmmgr ()
-{
- DeleteCriticalSection (&_segments_lock);
-}
-
-/*---------------------------------------------------------------------------*
- * client_shmmgr::find ()
- *---------------------------------------------------------------------------*/
-
-client_shmmgr::segment_t *
-client_shmmgr::find (const void *const shmaddr, segment_t **previous)
-{
- if (previous)
- *previous = NULL;
-
- for (segment_t *segptr = _segments_head; segptr; segptr = segptr->next)
- if (segptr->shmaddr == shmaddr)
- return segptr;
- else if (segptr->shmaddr > shmaddr) // The list is sorted by shmaddr.
- return NULL;
- else if (previous)
- *previous = segptr;
-
- return NULL;
-}
+/*
+ * XSI shmaphore API. These are exported by the DLL.
+ */
-/*---------------------------------------------------------------------------*
- * client_shmmgr::attach ()
- *
- * The body of shmat (), also used by fixup_shms_after_fork ().
- *---------------------------------------------------------------------------*/
-
-void *
-client_shmmgr::attach (const int shmid,
- const void *shmaddr,
- const int shmflg,
- HANDLE & hFileMap)
+extern "C" void *
+shmat (int shmid, const void *shmaddr, int shmflg)
{
- client_request_shm request (shmid, shmflg);
+#ifdef USE_SERVER
+ sigframe thisframe (mainthread);
+ syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0x%x)",
+ shmid, shmaddr, shmflg);
- if (request.make_request () == -1 || request.error_code ())
+ shm_shmid_list *ssh_entry;
+ SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next)
{
- syscall_printf (("-1 [%d] = "
- "shmat (shmid = %d, shmaddr = %p, shmflg = 0%o)"),
- request.error_code (), shmid, shmaddr, shmflg);
- set_errno (request.error_code ());
- return NULL;
+ if (ssh_entry->shmid == shmid)
+ break;
}
-
- int result = 0;
-
- const DWORD access = (shmflg & SHM_RDONLY) ? FILE_MAP_READ : FILE_MAP_WRITE;
-
- if (shmaddr && (shmflg & SHM_RND))
- shmaddr = (char *) shmaddr - ((ssize_t) shmaddr % SHMLBA);
-
- void *const ptr =
- MapViewOfFileEx (request.hFileMap (), access, 0, 0, 0, (void *) shmaddr);
-
- if (!ptr)
+ if (!ssh_entry)
{
- syscall_printf (("failed to map view "
- "[shmid = %d, handle = %p, shmaddr = %p]: %E"),
- shmid, request.hFileMap (), shmaddr);
- result = EINVAL; // FIXME
+ /* Invalid shmid */
+ set_errno (EINVAL);
+ return NULL;
}
- else if (shmaddr && ptr != shmaddr)
+ vm_object_t attach_va = NULL;
+ if (shmaddr)
{
- syscall_printf (("failed to map view at requested address "
- "[shmid = %d, handle = %p]: "
- "requested address = %p, mapped address = %p"),
- shmid, request.hFileMap (),
- shmaddr, ptr);
- result = EINVAL; // FIXME
+ if (shmflg & SHM_RND)
+ attach_va = (vm_object_t)((vm_offset_t)shmaddr & ~(SHMLBA-1));
+ else
+ attach_va = (vm_object_t)shmaddr;
+ /* Don't even bother to call anything if shmaddr is NULL or
+ not aligned. */
+ if (!attach_va || (vm_offset_t)attach_va % SHMLBA)
+ {
+ set_errno (EINVAL);
+ return NULL;
+ }
}
-
- if (result != 0)
+ /* Try allocating memory before calling cygserver. */
+ shm_attached_list *sph_entry = new (shm_attached_list);
+ if (!sph_entry)
{
- if (!CloseHandle (request.hFileMap ()))
- syscall_printf (("failed to close file map handle "
- "[shmid = %d, handle = %p]: %E"),
- shmid, request.hFileMap ());
-
- client_request_shm dt_req (shmid);
-
- if (dt_req.make_request () == -1 || dt_req.error_code ())
- syscall_printf ("shmdt request failed [shmid = %d, handle = %p]: %s",
- shmid, request.hFileMap (),
- strerror (dt_req.error_code ()));
-
- set_errno (result);
+ set_errno (ENOMEM);
return NULL;
}
-
- hFileMap = request.hFileMap ();
- return ptr;
-}
-
-/*---------------------------------------------------------------------------*
- * client_shmmgr::new_segment ()
- *
- * Allocate a new segment for the given shmid, file map and address
- * and insert into the segment map.
- *---------------------------------------------------------------------------*/
-
-client_shmmgr::segment_t *
-client_shmmgr::new_segment (const int shmid,
- const void *const shmaddr,
- const int shmflg,
- const HANDLE hFileMap)
-{
- assert (ipc_ext2int_subsys (shmid) == IPC_SHMOP);
- assert (hFileMap);
- assert (shmaddr);
-
- segment_t *previous = NULL; // Insert pointer.
-
- const segment_t *const tmp = find (shmaddr, &previous);
-
- assert (!tmp);
- assert (previous \
- ? (!previous->next || previous->next->shmaddr > shmaddr) \
- : (!_segments_head || _segments_head->shmaddr > shmaddr));
-
- segment_t *const segptr =
- safe_new (segment_t, shmid, shmaddr, shmflg, hFileMap);
-
- assert (segptr);
-
- if (previous)
+ DWORD access = (shmflg & SHM_RDONLY) ? FILE_MAP_READ : FILE_MAP_WRITE;
+ vm_object_t ptr = MapViewOfFileEx(ssh_entry->hdl, access, 0, 0,
+ ssh_entry->size, attach_va);
+ if (!ptr)
{
- segptr->next = previous->next;
- previous->next = segptr;
+ __seterrno ();
+ delete sph_entry;
+ return NULL;
}
- else
+ /* Use returned ptr address as is, so it's stored using the exact value
+ in cygserver. */
+ client_request_shm request (shmid, ptr, shmflg & ~SHM_RND);
+ if (request.make_request () == -1 || request.ptrval () == NULL)
{
- segptr->next = _segments_head;
- _segments_head = segptr;
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
+ UnmapViewOfFile (ptr);
+ delete sph_entry;
+ set_errno (request.error_code ());
+ return NULL;
}
-
- const long cnt = InterlockedIncrement (&_shmat_cnt);
- assert (cnt > 0);
-
- return segptr;
-}
-
-/*---------------------------------------------------------------------------*
- * fixup_shms_after_fork ()
- *---------------------------------------------------------------------------*/
-
-int __stdcall
-fixup_shms_after_fork ()
-{
- return shmmgr.fixup_shms_after_fork ();
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::client_request_shm ()
- *---------------------------------------------------------------------------*/
-
-client_request_shm::client_request_shm (const int shmid, const int shmflg)
- : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
-{
- _parameters.in.shmop = SHMOP_shmat;
-
- _parameters.in.shmid = shmid;
- _parameters.in.shmflg = shmflg;
-
- _parameters.in.cygpid = getpid ();
- _parameters.in.winpid = GetCurrentProcessId ();
- _parameters.in.uid = geteuid32 ();
- _parameters.in.gid = getegid32 ();
-
- msglen (sizeof (_parameters.in));
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::client_request_shm ()
- *---------------------------------------------------------------------------*/
-
-client_request_shm::client_request_shm (const int shmid,
- const int cmd,
- const struct shmid_ds *const buf)
- : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
-{
- _parameters.in.shmop = SHMOP_shmctl;
-
- _parameters.in.shmid = shmid;
- _parameters.in.cmd = cmd;
- if (buf)
- _parameters.in.ds = *buf;
-
- _parameters.in.cygpid = getpid ();
- _parameters.in.winpid = GetCurrentProcessId ();
- _parameters.in.uid = geteuid32 ();
- _parameters.in.gid = getegid32 ();
-
- msglen (sizeof (_parameters.in));
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::client_request_shm ()
- *---------------------------------------------------------------------------*/
-
-client_request_shm::client_request_shm (const int shmid)
- : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
-{
- _parameters.in.shmop = SHMOP_shmdt;
-
- _parameters.in.shmid = shmid;
-
- _parameters.in.cygpid = getpid ();
- _parameters.in.winpid = GetCurrentProcessId ();
- _parameters.in.uid = geteuid32 ();
- _parameters.in.gid = getegid32 ();
-
- msglen (sizeof (_parameters.in));
-}
-
-/*---------------------------------------------------------------------------*
- * client_request_shm::client_request_shm ()
- *---------------------------------------------------------------------------*/
-
-client_request_shm::client_request_shm (const key_t key,
- const size_t size,
- const int shmflg)
- : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters))
-{
- _parameters.in.shmop = SHMOP_shmget;
-
- _parameters.in.key = key;
- _parameters.in.size = size;
- _parameters.in.shmflg = shmflg;
-
- _parameters.in.cygpid = getpid ();
- _parameters.in.winpid = GetCurrentProcessId ();
- _parameters.in.uid = geteuid32 ();
- _parameters.in.gid = getegid32 ();
-
- msglen (sizeof (_parameters.in));
-}
-#endif /* USE_SERVER */
-
-/*---------------------------------------------------------------------------*
- * shmat ()
- *---------------------------------------------------------------------------*/
-
-extern "C" void *
-shmat (const int shmid, const void *const shmaddr, const int shmflg)
-{
-#ifdef USE_SERVER
- sigframe thisframe (mainthread);
- return shmmgr.shmat (shmid, shmaddr, shmflg);
+ sph_entry->ptr = ptr;
+ sph_entry->hdl = ssh_entry->hdl;
+ sph_entry->size = ssh_entry->size;
+ sph_entry->access = access;
+ SLIST_INSERT_HEAD (&sph_list, sph_entry, sph_next);
+ return ptr;
#else
set_errno (ENOSYS);
- return (void *) -1;
+ return NULL;
#endif
}
-/*---------------------------------------------------------------------------*
- * shmctl ()
- *---------------------------------------------------------------------------*/
-
extern "C" int
-shmctl (const int shmid, const int cmd, struct shmid_ds *const buf)
+shmctl (int shmid, int cmd, struct shmid_ds *buf)
{
#ifdef USE_SERVER
sigframe thisframe (mainthread);
- return shmmgr.shmctl (shmid, cmd, buf);
+ syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = 0x%x)",
+ shmid, cmd, buf);
+ switch (cmd)
+ {
+ case IPC_STAT:
+ case IPC_SET:
+ if (__check_null_invalid_struct_errno (buf, sizeof (struct shmid_ds)))
+ return -1;
+ break;
+ case IPC_INFO:
+ /* shmid == 0: Request for shminfo struct. */
+ if (!shmid
+ && __check_null_invalid_struct_errno (buf, sizeof (struct shminfo)))
+ return -1;
+ /* Otherwise, request shmid entries from internal shmid_ds array. */
+ if (shmid)
+ if (__check_null_invalid_struct_errno (buf, shmid * sizeof (struct shmid_ds)))
+ return -1;
+ break;
+ case SHM_INFO:
+ if (__check_null_invalid_struct_errno (buf, sizeof (struct shm_info)))
+ return -1;
+ break;
+ }
+ client_request_shm request (shmid, cmd, buf);
+ if (request.make_request () == -1 || request.retval () == -1)
+ {
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
+ set_errno (request.error_code ());
+ return -1;
+ }
+ if (cmd == IPC_RMID)
+ {
+ /* The process must cleanup its own storage... */
+ shm_shmid_list *ssh_entry, *ssh_next_entry;
+ SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry)
+ {
+ if (ssh_entry->shmid == shmid)
+ {
+ SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next);
+ /* ...and close the handle. */
+ CloseHandle (ssh_entry->hdl);
+ delete ssh_entry;
+ break;
+ }
+ }
+ }
+ return request.retval ();
#else
set_errno (ENOSYS);
return -1;
#endif
}
-/*---------------------------------------------------------------------------*
- * shmdt ()
- *---------------------------------------------------------------------------*/
-
extern "C" int
-shmdt (const void *const shmaddr)
+shmdt (const void *shmaddr)
{
#ifdef USE_SERVER
sigframe thisframe (mainthread);
- return shmmgr.shmdt (shmaddr);
+ syscall_printf ("shmget (shmaddr = %p)", shmaddr);
+ client_request_shm request (shmaddr);
+ if (request.make_request () == -1 || request.retval () == -1)
+ {
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
+ set_errno (request.error_code ());
+ return -1;
+ }
+ shm_attached_list *sph_entry, *sph_next_entry;
+ /* Remove map from list... */
+ SLIST_FOREACH_SAFE (sph_entry, &sph_list, sph_next, sph_next_entry)
+ {
+ if (sph_entry->ptr == shmaddr)
+ {
+ SLIST_REMOVE (&sph_list, sph_entry, shm_attached_list, sph_next);
+ /* ...and unmap view. */
+ UnmapViewOfFile (sph_entry->ptr);
+ delete sph_entry;
+ break;
+ }
+ }
+ return request.retval ();
#else
set_errno (ENOSYS);
return -1;
#endif
}
-/*---------------------------------------------------------------------------*
- * shmget ()
- *---------------------------------------------------------------------------*/
-
extern "C" int
-shmget (const key_t key, const size_t size, const int shmflg)
+shmget (key_t key, size_t size, int shmflg)
{
#ifdef USE_SERVER
sigframe thisframe (mainthread);
- return shmmgr.shmget (key, size, shmflg);
+ syscall_printf ("shmget (key = %U, size = %d, shmflg = 0x%x)",
+ key, size, shmflg);
+ /* Try allocating memory before calling cygserver. */
+ shm_shmid_list *ssh_new_entry = new (shm_shmid_list);
+ if (!ssh_new_entry)
+ {
+ set_errno (ENOMEM);
+ return -1;
+ }
+ client_request_shm request (key, size, shmflg);
+ if (request.make_request () == -1 || request.retval () == -1)
+ {
+ syscall_printf ("-1 [%d] = shmctl ()", request.error_code ());
+ delete ssh_new_entry;
+ set_errno (request.error_code ());
+ return -1;
+ }
+ int shmid = request.retval (); /* Shared mem ID */
+ vm_object_t hdl = request.objval (); /* HANDLE associated with it. */
+ shm_shmid_list *ssh_entry;
+ SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next)
+ {
+ if (ssh_entry->shmid == shmid)
+ {
+ /* We already maintain an entry for this shmid. That means,
+ the hdl returned by cygserver is a superfluous duplicate
+ of the original hdl maintained by cygserver. We can safely
+ delete it. */
+ CloseHandle (hdl);
+ delete ssh_new_entry;
+ return shmid;
+ }
+ }
+ /* We arrive here only if shmid is a new one for this process. Add the
+ shmid and hdl value to the list. */
+ ssh_new_entry->shmid = shmid;
+ ssh_new_entry->hdl = hdl;
+ ssh_new_entry->size = size;
+ SLIST_INSERT_HEAD (&ssh_list, ssh_new_entry, ssh_next);
+ return shmid;
#else
set_errno (ENOSYS);
return -1;