diff options
author | Corinna Vinschen <vinschen@redhat.com> | 2007-11-12 15:30:18 +0000 |
---|---|---|
committer | Corinna Vinschen <vinschen@redhat.com> | 2007-11-12 15:30:18 +0000 |
commit | e62ab8f1f4f65459d52959afc912eaaf0bc2767c (patch) | |
tree | 50b6c4702778be7d9115991dd645f479f9d91a8e /winsup/cygwin/shm.cc | |
parent | 6a96d471ceab0397a4c69a33a7c6795f18dc7857 (diff) | |
download | gdb-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.cc | 411 |
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 +} |