diff options
Diffstat (limited to 'winsup/cygwin/shm.cc')
-rw-r--r-- | winsup/cygwin/shm.cc | 693 |
1 files changed, 0 insertions, 693 deletions
diff --git a/winsup/cygwin/shm.cc b/winsup/cygwin/shm.cc deleted file mode 100644 index 94a86e2..0000000 --- a/winsup/cygwin/shm.cc +++ /dev/null @@ -1,693 +0,0 @@ -/* shm.cc: Single unix specification IPC interface for Cygwin. - - Copyright 2002 Red Hat, Inc. - - Written by Conrad Scott <conrad.scott@dsl.pipex.com>. - Based on code by Robert Collins <robert.collins@hotmail.com>. - -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/types.h> - -#include <assert.h> -#include <errno.h> -#include <stdio.h> -#include <unistd.h> - -#include "cygerrno.h" -#include "safe_memory.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. - */ -/* static */ client_shmmgr::segment_t *client_shmmgr::_segments_head; -/* static */ long client_shmmgr::_shmat_cnt; - -/*---------------------------------------------------------------------------* - * client_shmmgr::instance () - *---------------------------------------------------------------------------*/ - -client_shmmgr & -client_shmmgr::instance () -{ - if (!_instance) - _instance = safe_new0 (client_shmmgr); - - assert (_instance); - - return *_instance; -} - -/*---------------------------------------------------------------------------* - * client_shmmgr::shmat () - *---------------------------------------------------------------------------*/ - -void * -client_shmmgr::shmat (const int shmid, - const void *const shmaddr, - const int shmflg) -{ - 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); - - 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 (). - - return (ptr ? ptr : (void *) -1); -} - -/*---------------------------------------------------------------------------* - * client_shmmgr::shmctl () - *---------------------------------------------------------------------------*/ - -int -client_shmmgr::shmctl (const int shmid, - const int cmd, - struct shmid_ds *const buf) -{ - 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; - } - - syscall_printf ("%d = shmctl (shmid = %d, cmd = 0x%x, buf = %p)", - result, shmid, cmd, buf); - - return result; -} - -/*---------------------------------------------------------------------------* - * 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) -{ - 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); - - assert (segptr->hFileMap); - - if (!CloseHandle (segptr->hFileMap)) - syscall_printf (("failed to close file map handle " - "[shmid = %d, handle = %p]: %E"), - segptr->shmid, segptr->hFileMap); - - client_request_shm request (segptr->shmid); - - 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 ())); - - safe_delete (segptr); - - syscall_printf ("0 = shmdt (shmaddr = %p)", shmaddr); - - return 0; -} - -/*---------------------------------------------------------------------------* - * client_shmmgr::shmget () - *---------------------------------------------------------------------------*/ - -int -client_shmmgr::shmget (const key_t key, const size_t size, const int shmflg) -{ - syscall_printf ("shmget (key = 0x%016X, size = %u, shmflg = 0%o)", - key, size, shmflg); - - client_request_shm request (key, size, shmflg); - - if (request.make_request () == -1 || request.error_code ()) - { - syscall_printf (("-1 [%d] = " - "shmget (key = 0x%016X, size = %u, shmflg = 0%o)"), - request.error_code (), - key, size, shmflg); - set_errno (request.error_code ()); - return -1; - } - - 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; -} - -/*---------------------------------------------------------------------------* - * 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; -} - -/*---------------------------------------------------------------------------* - * 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) -{ - client_request_shm request (shmid, shmflg); - - if (request.make_request () == -1 || request.error_code ()) - { - 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; - } - - 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) - { - syscall_printf (("failed to map view " - "[shmid = %d, handle = %p, shmaddr = %p]: %E"), - shmid, request.hFileMap (), shmaddr); - result = EINVAL; // FIXME - } - else if (shmaddr && ptr != 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 (result != 0) - { - 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); - 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) - { - segptr->next = previous->next; - previous->next = segptr; - } - else - { - segptr->next = _segments_head; - _segments_head = segptr; - } - - const long cnt = InterlockedIncrement (&_shmat_cnt); - assert (cnt > 0); - - return segptr; -} - -/*---------------------------------------------------------------------------* - * shmat () - *---------------------------------------------------------------------------*/ - -extern "C" void * -shmat (const int shmid, const void *const shmaddr, const int shmflg) -{ - sigframe thisframe (mainthread); - return shmmgr.shmat (shmid, shmaddr, shmflg); -} - -/*---------------------------------------------------------------------------* - * shmctl () - *---------------------------------------------------------------------------*/ - -extern "C" int -shmctl (const int shmid, const int cmd, struct shmid_ds *const buf) -{ - sigframe thisframe (mainthread); - return shmmgr.shmctl (shmid, cmd, buf); -} - -/*---------------------------------------------------------------------------* - * shmdt () - *---------------------------------------------------------------------------*/ - -extern "C" int -shmdt (const void *const shmaddr) -{ - sigframe thisframe (mainthread); - return shmmgr.shmdt (shmaddr); -} - -/*---------------------------------------------------------------------------* - * shmget () - *---------------------------------------------------------------------------*/ - -extern "C" int -shmget (const key_t key, const size_t size, const int shmflg) -{ - sigframe thisframe (mainthread); - return shmmgr.shmget (key, size, shmflg); -} - -/*---------------------------------------------------------------------------* - * 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 = geteuid (); - _parameters.in.gid = getegid (); - - 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 = geteuid (); - _parameters.in.gid = getegid (); - - 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 = geteuid (); - _parameters.in.gid = getegid (); - - 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 = geteuid (); - _parameters.in.gid = getegid (); - - msglen (sizeof (_parameters.in)); -} |