diff options
Diffstat (limited to 'winsup/cygwin/shm.cc')
-rw-r--r-- | winsup/cygwin/shm.cc | 388 |
1 files changed, 0 insertions, 388 deletions
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc deleted file mode 100644 index 8b41a38df..000000000 --- a/winsup/cygwin/shm.cc +++ /dev/null @@ -1,388 +0,0 @@ -/* shm.cc: XSI IPC interface for Cygwin. - - Copyright 2003, 2004, 2007, 2009 Red Hat, Inc. - -This file is part of Cygwin. - -This software is a copyrighted work licensed under the terms of the -Cygwin license. Please consult the file "CYGWIN_LICENSE" for -details. */ - -#include "winsup.h" -#include <sys/queue.h> -#include <unistd.h> - -#include "pinfo.h" -#include "sigproc.h" - -#include "cygserver_shm.h" -#include "cygtls.h" -#include "sync.h" -#include "ntdll.h" - -/* - * client_request_shm Constructors - */ - -client_request_shm::client_request_shm (int shmid, - const void *shmaddr, - int shmflg) - : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) -{ - _parameters.in.shmop = SHMOP_shmat; - ipc_set_proc_info (_parameters.in.ipcblk); - - _parameters.in.atargs.shmid = shmid; - _parameters.in.atargs.shmaddr = shmaddr; - _parameters.in.atargs.shmflg = shmflg; - - msglen (sizeof (_parameters.in)); -} - -client_request_shm::client_request_shm (int shmid, - int cmd, - struct shmid_ds *buf) - : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) -{ - _parameters.in.shmop = SHMOP_shmctl; - ipc_set_proc_info (_parameters.in.ipcblk); - - _parameters.in.ctlargs.shmid = shmid; - _parameters.in.ctlargs.cmd = cmd; - _parameters.in.ctlargs.buf = buf; - - msglen (sizeof (_parameters.in)); -} - -client_request_shm::client_request_shm (const void *shmaddr) - : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) -{ - _parameters.in.shmop = SHMOP_shmdt; - ipc_set_proc_info (_parameters.in.ipcblk); - - _parameters.in.dtargs.shmaddr = shmaddr; - - msglen (sizeof (_parameters.in)); -} - -client_request_shm::client_request_shm (key_t key, - size_t size, - int shmflg) - : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) -{ - _parameters.in.shmop = SHMOP_shmget; - ipc_set_proc_info (_parameters.in.ipcblk); - - _parameters.in.getargs.key = key; - _parameters.in.getargs.size = size; - _parameters.in.getargs.shmflg = shmflg; - - msglen (sizeof (_parameters.in)); -} - -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); - - _parameters.in.forkargs = *p1; -} - -/* 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; - int ref_count; -}; - -static SLIST_HEAD (, shm_shmid_list) ssh_list; - -/* List of attached mappings, as returned by shmat. */ -struct shm_attached_list { - SLIST_ENTRY (shm_attached_list) sph_next; - vm_object_t ptr; - shm_shmid_list *parent; - ULONG access; -}; - -static SLIST_HEAD (, shm_attached_list) sph_list; - -static NO_COPY muto shm_guard; -#define SLIST_LOCK() (shm_guard.init ("shm_guard")->acquire ()) -#define SLIST_UNLOCK() (shm_guard.release ()) - -int __stdcall -fixup_shms_after_fork () -{ - 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 (&parent); - if (request.make_request () == -1 || request.retval () == -1) - { - syscall_printf ("-1 [%d] = fixup_shms_after_fork ()", request.error_code ()); - set_errno (request.error_code ()); - return 0; - } - shm_attached_list *sph_entry; - /* Reconstruct map from list... */ - SLIST_FOREACH (sph_entry, &sph_list, sph_next) - { - NTSTATUS status; - vm_object_t ptr = sph_entry->ptr; - ULONG viewsize = sph_entry->parent->size; - status = NtMapViewOfSection (sph_entry->parent->hdl, NtCurrentProcess (), - &ptr, 0, sph_entry->parent->size, NULL, - &viewsize, ViewShare, 0, sph_entry->access); - if (!NT_SUCCESS (status) || ptr != sph_entry->ptr) - api_fatal ("fixup_shms_after_fork: NtMapViewOfSection (%p), status %p. Terminating.", - sph_entry->ptr, status); - } - return 0; -} - -/* - * XSI shmaphore API. These are exported by the DLL. - */ - -extern "C" void * -shmat (int shmid, const void *shmaddr, int shmflg) -{ - syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0x%x)", - shmid, shmaddr, shmflg); - - SLIST_LOCK (); - shm_shmid_list *ssh_entry; - SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next) - { - if (ssh_entry->shmid == shmid) - break; - } - if (!ssh_entry) - { - /* The shmid is unknown to this process so far. Try to get it from - the server if it exists. Use special internal call to shmget, - which interprets the key as a shmid and only returns a valid - shmid if one exists. Since shmctl inserts a new entry for this - shmid into ssh_list automatically, we just have to go through - that list again. If that still fails, well, bad luck. */ - if (shmid && shmget ((key_t) shmid, 0, IPC_KEY_IS_SHMID) != -1) - { - SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next) - { - if (ssh_entry->shmid == shmid) - break; - } - } - if (!ssh_entry) - { - /* Invalid shmid */ - set_errno (EINVAL); - SLIST_UNLOCK (); - return (void *) -1; - } - } - /* Early increment ref counter. This allows further actions to run with - unlocked lists, because shmdt or shmctl(IPC_RMID) won't delete this - ssh_entry. */ - ++ssh_entry->ref_count; - SLIST_UNLOCK (); - - vm_object_t attach_va = NULL; - if (shmaddr) - { - 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); - --ssh_entry->ref_count; - return (void *) -1; - } - } - /* Try allocating memory before calling cygserver. */ - shm_attached_list *sph_entry = new (shm_attached_list); - if (!sph_entry) - { - set_errno (ENOMEM); - --ssh_entry->ref_count; - return (void *) -1; - } - NTSTATUS status; - vm_object_t ptr = NULL; - ULONG viewsize = ssh_entry->size; - ULONG access = (shmflg & SHM_RDONLY) ? PAGE_READONLY : PAGE_READWRITE; - status = NtMapViewOfSection (ssh_entry->hdl, NtCurrentProcess (), &ptr, 0, - ssh_entry->size, NULL, &viewsize, ViewShare, - MEM_TOP_DOWN, access); - if (!NT_SUCCESS (status)) - { - __seterrno_from_nt_status (status); - delete sph_entry; - --ssh_entry->ref_count; - return (void *) -1; - } - /* 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) - { - syscall_printf ("-1 [%d] = shmat ()", request.error_code ()); - UnmapViewOfFile (ptr); - delete sph_entry; - set_errno (request.error_code ()); - --ssh_entry->ref_count; - if (request.error_code () == ENOSYS) - raise (SIGSYS); - return (void *) -1; - } - sph_entry->ptr = ptr; - sph_entry->parent = ssh_entry; - sph_entry->access = access; - SLIST_LOCK (); - SLIST_INSERT_HEAD (&sph_list, sph_entry, sph_next); - SLIST_UNLOCK (); - return ptr; -} - -extern "C" int -shmctl (int shmid, int cmd, struct shmid_ds *buf) -{ - syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = 0x%x)", - shmid, cmd, buf); - myfault efault; - if (efault.faulted (EFAULT)) - return -1; - 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 ()); - if (request.error_code () == ENOSYS) - raise (SIGSYS); - return -1; - } - if (cmd == IPC_RMID) - { - /* Cleanup */ - shm_shmid_list *ssh_entry, *ssh_next_entry; - SLIST_LOCK (); - SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry) - { - if (ssh_entry->shmid == shmid) - { - /* Remove this entry from the list and close the handle - only if it's not in use anymore. */ - if (ssh_entry->ref_count <= 0) - { - SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next); - CloseHandle (ssh_entry->hdl); - delete ssh_entry; - } - break; - } - } - SLIST_UNLOCK (); - } - return request.retval (); -} - -extern "C" int -shmdt (const void *shmaddr) -{ - syscall_printf ("shmdt (shmaddr = %p)", shmaddr); - client_request_shm request (shmaddr); - if (request.make_request () == -1 || request.retval () == -1) - { - syscall_printf ("-1 [%d] = shmdt ()", request.error_code ()); - set_errno (request.error_code ()); - if (request.error_code () == ENOSYS) - raise (SIGSYS); - return -1; - } - shm_attached_list *sph_entry, *sph_next_entry; - /* Remove map from list... */ - SLIST_LOCK (); - 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); - /* ...unmap view... */ - UnmapViewOfFile (sph_entry->ptr); - /* ...and, if this was the last reference to this shared section... */ - shm_shmid_list *ssh_entry = sph_entry->parent; - if (--ssh_entry->ref_count <= 0) - { - /* ...delete parent entry and close handle. */ - SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next); - CloseHandle (ssh_entry->hdl); - delete ssh_entry; - } - delete sph_entry; - break; - } - } - SLIST_UNLOCK (); - return request.retval (); -} - -extern "C" int -shmget (key_t key, size_t size, int 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] = shmget ()", request.error_code ()); - delete ssh_new_entry; - set_errno (request.error_code ()); - if (request.error_code () == ENOSYS) - raise (SIGSYS); - 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_LOCK (); - 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; - SLIST_UNLOCK (); - 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; - ssh_new_entry->ref_count = 0; - SLIST_INSERT_HEAD (&ssh_list, ssh_new_entry, ssh_next); - SLIST_UNLOCK (); - return shmid; -} |