* acconfig.h: Add USE_CYGSERVER define. * config.h.in: Regenerate. * configure.in: Add --enable-server setting. * configure: Regenerate. * fhandler_tty.cc (fhandler_tty_slave::open): Conditionalize compilation of cygserver stuff. * fork.cc (fork_child): Ditto. * shm.cc: Ditto. * tty.cc (tty::common_init): Ditto. * dcrt0.cc: Use bool rather than BOOL for CYGWIN environment variable definitions. * environ.cc: Ditto. * ntea.cc: Ditto. * security.cc: Ditto. * security.h: Ditto. * syscalls.cc (check_posix_perm): Remove externs that were already declared in a header. * winsup.h: Ditto. Declare _MT_SAFE here. Delete it someday since cygwin should always be _MT_SAFE.
		
			
				
	
	
		
			694 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			694 lines
		
	
	
		
			19 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* 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"
 | 
						|
#ifdef USE_CYGSERVER
 | 
						|
#include <sys/types.h>
 | 
						|
 | 
						|
#include <assert.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 = 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_CYGSERVER */
 |