summaryrefslogtreecommitdiff
path: root/winsup/cygwin/shm.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <vinschen@redhat.com>2007-11-12 15:30:18 +0000
committerCorinna Vinschen <vinschen@redhat.com>2007-11-12 15:30:18 +0000
commite62ab8f1f4f65459d52959afc912eaaf0bc2767c (patch)
tree50b6c4702778be7d9115991dd645f479f9d91a8e /winsup/cygwin/shm.cc
parent6a96d471ceab0397a4c69a33a7c6795f18dc7857 (diff)
downloadgdb-e62ab8f1f4f65459d52959afc912eaaf0bc2767c.tar.gz
2007-11-08 Christopher Faylor <me+cygwin@cgf.cx>
* dllfixdbg: Eliminate extra objcopy step. 2007-11-07 Pedro Alves <pedro_alves@portugalmail.pt> * dllfixdbg: Pass --only-keep-debug to objcopy, instead of selecting the sections manually. 2007-11-06 Corinna Vinschen <corinna@vinschen.de> * thread.cc (pthread_key_create): Drop check for incoming valid object. 2007-11-06 Corinna Vinschen <corinna@vinschen.de> * shm.cc: Include sync.h (struct shm_shmid_list): Add ref_count member. (struct shm_attached_list): Remove hdl and size members. Add a parent member pointing to referenced shm_shmid_list entry. (shm_guard): New muto. (SLIST_LOCK): Define. (SLIST_UNLOCK): Define. (fixup_shms_after_fork): Use hdl and size members of parent shm_shmid_list entry. (shmat): Access sequential bookkeeping lists in a thread safe way. Accommodate change in list element layout. Align comments. (shmctl): Ditto. (shmdt): Ditto. (shmget): Ditto. 2007-11-05 Corinna Vinschen <corinna@vinschen.de> * shm.cc (shmctl): On IPC_RMID don't unmap views and don't close handle if the map is still referenced to emulate Linux and BSD behaviour. 2007-11-05 Corinna Vinschen <corinna@vinschen.de> * shm.cc (shmctl): On IPC_RMID also unmap all views on shared mem as well as connected shm_attached_list entry. 2007-10-30 Corinna Vinschen <corinna@vinschen.de> * fhandler_disk_file.cc (fhandler_base::fstat_helper): Don't remove write bits for directories with R/O attribute. (fhandler_base::fhaccess): Don't shortcircuit R/O attribute with W_OK scenarios for directories. 2007-09-26 Corinna Vinschen <corinna@vinschen.de> * termios.cc (setspeed): Support new baud rates introduced 2007-02-05. 2007-09-18 Corinna Vinschen <corinna@vinschen.de> * mmap.cc (fh_disk_file): Delete as global static variable and... (mmap64): ...define as local pointer to make mmap thread-safe. Accommodate throughout. Only initialize fh_disk_file after file could be opened with GENERIC_EXECUTE access. 2007-09-06 Brian Dessent <brian@dessent.net> * include/sys/stdio.h (_flockfile): Don't try to lock a FILE that has the __SSTR flag set. (_ftrylockfile): Likewise. (_funlockfile): Likewise. 2007-08-24 Corinna Vinschen <corinna@vinschen.de> * syscalls.cc (open): Don't follow symlinks if O_EXCL is given. 2007-08-09 Ernie Coskrey <Ernie.Coskrey@steeleye.com> * gendef (sigbe): Reset "incyg" while the stack lock is active to avoid a potential race. 2007-08-01 Corinna Vinschen <corinna@vinschen.de> * localtime.cc (tzsetwall): Don't set TZ. 2007-07-17 Corinna Vinschen <corinna@vinschen.de> * fhandler.cc (fhandler_base::fhaccess): Add check for R/O file system. 2007-07-14 Christopher Faylor <me+cygwin@cgf.cx> * init.cc (in_dllentry): Delete. (dll_entry): Remove assignment to deleted variable. * winsup.h (in_dllentry): Delete declaration. * exceptions.cc (inside_kernel): Use another method to see if we are in dll_entry phase. 2007-07-14 Christopher Faylor <me+cygwin@cgf.cx> * init.cc (in_dllentry): Make NO_COPY to avoid spurious false positives. 2007-07-09 Christopher Faylor <me+cygwin@cgf.cx> * dlfcn.cc (dlclose): Don't close handle returned from GetModuleHandle(NULL). 2007-07-06 Corinna Vinschen <corinna@vinschen.de> * times.cc (gettimeofday): Align definition to POSIX. 2007-07-04 Corinna Vinschen <corinna@vinschen.de> * times.cc: Define __timezonefunc__ before including time.h to protect definition of timezone function. 2007-07-04 Corinna Vinschen <corinna@vinschen.de> * include/cygwin/time.h: Switch to timezone variable by default. Add comment. 2007-06-27 Corinna Vinschen <corinna@vinschen.de> * shared_info.h (SHARED_INFO_CB): Accommodate change to shared_info. (CURR_SHARED_MAGIC): Ditto. (class shared_info): Add heap_slop_inited member. * shared.cc (shared_info::heap_slop_size): Use heap_slop_inited to track initializing heap_slop since 0 is a valid value for heap_slop. Drop useless < 0 consideration. 2007-06-12 Christopher Faylor <me+cygwin@cgf.cx> * signal.cc (usleep): Use useconds_t for the type as per POSIX. 2007-06-12 Corinna Vinschen <corinna@vinschen.de> * fhandler.cc (fhandler_base::fstat): Set pipe permission bits more correctly. 2007-05-29 Corinna Vinschen <corinna@vinschen.de> * dtable.cc (dtable::set_file_pointers_for_exec): Call SetFilePointer correctly for 64 bit file access. Comment out functionality. * fhandler.cc (fhandler_base::open): Don't set append_mode. (fhandler_base::write): Check for O_APPEND instead of append_mode. Call SetFilePointer correctly for 64 bit file access. Handle errors from SetFilePointer. * fhandler.h (class fhandler_base): Drop append_mode status flag. * fhandler_disk_file.cc (fhandler_base::fstat_helper): Handle seeking correctly for 64 bit file access. 2007-05-21 Christian Franke <franke@computer.org> * fhandler_floppy.cc (fhandler_dev_floppy::lseek): Don't invalidate devbuf if new position is within buffered range. 2007-05-21 Eric Blake <ebb9@byu.net> * include/search.h (hsearch_r): Provide declaration. 2007-05-21 Christian Franke <franke@computer.org> Corinna Vinschen <corinna@vinschen.de> * fhandler_floppy.cc (fhandler_dev_floppy::lseek): Set buf size to sector size. Simplify non-sector aligned case. Handle errors from raw_read. 2007-05-15 Corinna Vinschen <corinna@vinschen.de> * fhandler_socket.cc (adjust_socket_file_mode): New inline function. (fhandler_socket::fchmod): Squeeze mode through adjust_socket_file_mode before using it. (fhandler_socket::bind): Ditto. 2007-04-18 Brian Dessent <brian@dessent.net> * cygwin.sc: Remove duplicated .debug_macinfo section. * dllfixdbg: Also copy DWARF-2 sections into .dbg file. 2007-04-06 Eric Blake <ebb9@byu.net> * include/stdint.h (WINT_MIN): Fix sign. 2007-04-04 Eric Blake <ebb9@byu.net> * include/stdint.h (WINT_MIN, WINT_MAX): Fix definition. 2007-03-28 Christopher Faylor <me@cgf.cx> * spawn.cc (spawn_guts): Start pure-windows processes in a suspended state to avoid potential DuplicateHandle problems. 2007-03-07 Christopher Faylor <me@cgf.cx> * signal.cc (handle_sigprocmask): Remove extraneous sig_dispatch_pending. 2007-02-26 Corinna Vinschen <corinna@vinschen.de> * fhandler.cc (fhandler_base::fstat): Set all file times to arbitrary fixed value. 2007-02-20 Christopher Faylor <me@cgf.cx> * exceptions.cc (_cygtls::signal_exit): Only call myself.exit when when exit_state indicates that we've visited do_exit. * sync.h (lock_process::lock_process): Use renamed exit_state - ES_PROCESS_LOCKED. * winsup.h: Rename ES_MUTO_SET to ES_PROCESS_LOCKED. 2007-02-20 Corinna Vinschen <corinna@vinschen.de> * fhandler_socket.cc (fhandler_socket::bind): Remove printing wrong errno in debug output. 2007-02-05 Corinna Vinschen <corinna@vinschen.de> * fhandler_serial.cc (fhandler_serial::tcsetattr): Add support for baud rates up to 3000000 baud. Add missing 128K and 256K cases. (fhandler_serial::tcgetattr): Ditto. * include/sys/termios.h: Add baud rate definitions from B460800 up to B3000000. 2007-01-04 Brian Ford <Brian.Ford@FlightSafety.com> Corinna Vinschen <corinna@vinschen.de> * fhandler.h (PREFERRED_IO_BLKSIZE): Define as 64K. * fhandler.cc (fhandler_base::fstat): Set st_blksize to PREFERRED_IO_BLKSIZE. * fhandler_disk_file.cc (fhandler_base::fstat_helper): Ditto. * fhandler_mailslot.cc (fhandler_mailslot::fstat): Ditto. * fhandler_raw.cc (fhandler_dev_raw::fstat): Ditto. 2006-11-08 Corinna Vinschen <corinna@vinschen.de> * security.cc (get_token_group_sidlist): Always add the local group to the token. 2006-07-14 Corinna Vinschen <corinna@vinschen.de> * security.cc (get_token_group_sidlist): Always add the interactive group to the token. Create logon_id group SID by copying it from incoming group list.
Diffstat (limited to 'winsup/cygwin/shm.cc')
-rw-r--r--winsup/cygwin/shm.cc411
1 files changed, 411 insertions, 0 deletions
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc
new file mode 100644
index 00000000000..3170fcae3f4
--- /dev/null
+++ b/winsup/cygwin/shm.cc
@@ -0,0 +1,411 @@
+/* shm.cc: XSI IPC interface for Cygwin.
+
+ Copyright 2003 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 "cygerrno.h"
+#include <signal.h>
+#ifdef USE_SERVER
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include "pinfo.h"
+#include "sigproc.h"
+
+#include "cygserver_ipc.h"
+#include "cygserver_shm.h"
+#include "cygtls.h"
+#include "sync.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;
+ int 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;
+ /* Remove map from list... */
+ SLIST_FOREACH (sph_entry, &sph_list, sph_next)
+ {
+ vm_object_t ptr = MapViewOfFileEx (sph_entry->parent->hdl,
+ sph_entry->access, 0, 0,
+ sph_entry->parent->size,
+ sph_entry->ptr);
+ if (ptr != sph_entry->ptr)
+ api_fatal ("MapViewOfFileEx (%p), %E. Terminating.", sph_entry->ptr);
+ }
+ return 0;
+}
+#endif /* USE_SERVER */
+
+/*
+ * XSI shmaphore API. These are exported by the DLL.
+ */
+
+extern "C" void *
+shmat (int shmid, const void *shmaddr, int shmflg)
+{
+#ifdef USE_SERVER
+ 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;
+ }
+ 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)
+ {
+ __seterrno ();
+ 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;
+#else
+ set_errno (ENOSYS);
+ raise (SIGSYS);
+ return (void *) -1;
+#endif
+}
+
+extern "C" int
+shmctl (int shmid, int cmd, struct shmid_ds *buf)
+{
+#ifdef USE_SERVER
+ 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 ();
+#else
+ set_errno (ENOSYS);
+ raise (SIGSYS);
+ return -1;
+#endif
+}
+
+extern "C" int
+shmdt (const void *shmaddr)
+{
+#ifdef USE_SERVER
+ 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 ();
+#else
+ set_errno (ENOSYS);
+ raise (SIGSYS);
+ return -1;
+#endif
+}
+
+extern "C" int
+shmget (key_t key, size_t size, int shmflg)
+{
+#ifdef USE_SERVER
+ 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;
+#else
+ set_errno (ENOSYS);
+ raise (SIGSYS);
+ return -1;
+#endif
+}