⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cygserver_shm.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 2 页
字号:
		  if (segptr->is_pending_delete ())		    delete_segment (segptr);		}	      break;	    case SHM_STAT:	// ipcs(8) i'face.	      out_ds = segptr->_ds;	      out_shmid = segptr->_shmid;	      break;	    }      }      break;    case IPC_INFO:      out_shminfo.shmmax = SHMMAX;      out_shminfo.shmmin = SHMMIN;      out_shminfo.shmmni = SHMMNI;      out_shminfo.shmseg = SHMSEG;      out_shminfo.shmall = SHMALL;      break;    case SHM_INFO:		// ipcs(8) i'face.      out_shmid = _intid_max;      out_shm_info.shm_ids = _shm_ids;      out_shm_info.shm_tot = _shm_tot;      out_shm_info.shm_atts = _shm_atts;      break;    default:      result = -EINVAL;      break;    }  LeaveCriticalSection (&_segments_lock);  if (result < 0)    syscall_printf (("-1 [%d] = "		     "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"),		    -result,		    shmid, cmd, client->cygpid (), client->winpid ());  else    syscall_printf (("%d = "		     "shmctl (shmid = %d, cmd = 0x%x) for %d(%lu)"),		    ((cmd == SHM_STAT || cmd == SHM_INFO)		     ? out_shmid		     : result),		    shmid, cmd, client->cygpid (), client->winpid ());  return result;}/*---------------------------------------------------------------------------* * server_shmmgr::shmdt () *---------------------------------------------------------------------------*/intserver_shmmgr::shmdt (const int shmid, class process *const client){  syscall_printf ("shmdt (shmid = %d) for %d(%lu)",		  shmid, client->cygpid (), client->winpid ());  int result = 0;  EnterCriticalSection (&_segments_lock);  segment_t *const segptr = find (ipc_ext2int (shmid, IPC_SHMOP));  if (!segptr)    result = -EINVAL;  else    result = segptr->detach (client);  if (!result)    _shm_atts -= 1;  if (!result && segptr->is_pending_delete ())    delete_segment (segptr);  LeaveCriticalSection (&_segments_lock);  if (result < 0)    syscall_printf ("-1 [%d] = shmdt (shmid = %d) for %d(%lu)",		    -result, shmid, client->cygpid (), client->winpid ());  else    syscall_printf ("%d = shmdt (shmid = %d) for %d(%lu)",		    result, shmid, client->cygpid (), client->winpid ());  return result;}/*---------------------------------------------------------------------------* * server_shmmgr::shmget () *---------------------------------------------------------------------------*/intserver_shmmgr::shmget (int & out_shmid,		       const key_t key, const size_t size, const int shmflg,		       const uid_t uid, const gid_t gid,		       class process *const client){  syscall_printf (("shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "		   "for %d(%lu)"),		  key, size, shmflg,		  client->cygpid (), client->winpid ());  int result = 0;  EnterCriticalSection (&_segments_lock);  if (key == IPC_PRIVATE)    result = new_segment (key, size, shmflg,			  client->cygpid (), uid, gid);  else    {      segment_t *const segptr = find_by_key (key);      if (!segptr)	if (shmflg & IPC_CREAT)	  result = new_segment (key, size, shmflg,				client->cygpid (), uid, gid);	else	  result = -ENOENT;      else if (segptr->is_deleted ())	result = -EIDRM;      else if ((shmflg & IPC_CREAT) && (shmflg & IPC_EXCL))	result = -EEXIST;      else if ((shmflg & ~(segptr->_ds.shm_perm.mode)) & 0777)	result = -EACCES;      else if (size && segptr->_ds.shm_segsz < size)	result = -EINVAL;      else	result = segptr->_shmid;    }  LeaveCriticalSection (&_segments_lock);  if (result >= 0)    {      out_shmid = result;      result = 0;    }  if (result < 0)    syscall_printf (("-1 [%d] = "		     "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "		     "for %d(%lu)"),		    -result,		    key, size, shmflg,		    client->cygpid (), client->winpid ());  else    syscall_printf (("%d = "		     "shmget (key = 0x%016llx, size = %u, shmflg = 0%o) "		     "for %d(%lu)"),		    out_shmid,		    key, size, shmflg,		    client->cygpid (), client->winpid ());  return result;}/*---------------------------------------------------------------------------* * server_shmmgr::initialise_instance () *---------------------------------------------------------------------------*//* static */ voidserver_shmmgr::initialise_instance (){  assert (!_instance);  _instance = safe_new0 (server_shmmgr);  assert (_instance);}/*---------------------------------------------------------------------------* * server_shmmgr::server_shmmgr () *---------------------------------------------------------------------------*/server_shmmgr::server_shmmgr ()  : _segments_head (NULL),    _shm_ids (0),    _shm_tot (0),    _shm_atts (0),    _intid_max (0){  InitializeCriticalSection (&_segments_lock);}/*---------------------------------------------------------------------------* * server_shmmgr::~server_shmmgr () *---------------------------------------------------------------------------*/server_shmmgr::~server_shmmgr (){  DeleteCriticalSection (&_segments_lock);}/*---------------------------------------------------------------------------* * server_shmmgr::find_by_key () *---------------------------------------------------------------------------*/server_shmmgr::segment_t *server_shmmgr::find_by_key (const key_t key){  for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next)    if (segptr->_ds.shm_perm.key == key)      return segptr;  return NULL;}/*---------------------------------------------------------------------------* * server_shmmgr::find () *---------------------------------------------------------------------------*/server_shmmgr::segment_t *server_shmmgr::find (const int intid, segment_t **previous){  if (previous)    *previous = NULL;  for (segment_t *segptr = _segments_head; segptr; segptr = segptr->_next)    if (segptr->_intid == intid)      return segptr;    else if (segptr->_intid > intid) // The list is sorted by intid.      return NULL;    else if (previous)      *previous = segptr;  return NULL;}/*---------------------------------------------------------------------------* * server_shmmgr::new_segment () *---------------------------------------------------------------------------*/intserver_shmmgr::new_segment (const key_t key,			    const size_t size,			    const int shmflg,			    const pid_t cygpid,			    const uid_t uid,			    const gid_t gid){  if (size < SHMMIN || size > SHMMAX)      return -EINVAL;  const HANDLE hFileMap = CreateFileMapping (INVALID_HANDLE_VALUE,					     NULL, PAGE_READWRITE,					     0, size,					     NULL);  if (!hFileMap)    {      syscall_printf ("failed to create file mapping [size = %lu]: %E", size);      return -ENOMEM;		// FIXME    }  segment_t *const segptr = new_segment (key, size, hFileMap);  if (!segptr)    {      (void) CloseHandle (hFileMap);      return -ENOSPC;    }  segptr->_ds.shm_perm.cuid = segptr->_ds.shm_perm.uid = uid;  segptr->_ds.shm_perm.cgid = segptr->_ds.shm_perm.gid = gid;  segptr->_ds.shm_perm.mode = shmflg & 0777;  segptr->_ds.shm_segsz = size;  segptr->_ds.shm_cpid = cygpid;  segptr->_ds.shm_ctime = time (NULL); // FIXME: sub-second times.  return segptr->_shmid;}/*---------------------------------------------------------------------------* * server_shmmgr::new_segment () * * Allocate a new segment for the given key and file map with the * lowest available intid and insert into the segment map. *---------------------------------------------------------------------------*/server_shmmgr::segment_t *server_shmmgr::new_segment (const key_t key, const size_t size,			    const HANDLE hFileMap){  // FIXME: Overflow risk.  if (_shm_tot + size > SHMALL)    return NULL;  int intid = 0;		// Next expected intid value.  segment_t *previous = NULL;	// Insert pointer.  // Find first unallocated intid.  for (segment_t *segptr = _segments_head;       segptr && segptr->_intid == intid;       segptr = segptr->_next, intid++)    {      previous = segptr;    }  /* By the time this condition is reached (given the default value of   * SHMMNI), the linear searches should all replaced by something   * just a *little* cleverer . . .   */  if (intid >= SHMMNI)    return NULL;  segment_t *const segptr = safe_new (segment_t, key, intid, hFileMap);  assert (segptr);  if (previous)    {      segptr->_next = previous->_next;      previous->_next = segptr;    }  else    {      segptr->_next = _segments_head;      _segments_head = segptr;    }  _shm_ids += 1;  _shm_tot += size;  if (intid > _intid_max)    _intid_max = intid;  return segptr;}/*---------------------------------------------------------------------------* * server_shmmgr::delete_segment () *---------------------------------------------------------------------------*/voidserver_shmmgr::delete_segment (segment_t *const segptr){  assert (segptr);  assert (segptr->is_pending_delete ());  segment_t *previous = NULL;  const segment_t *const tmp = find (segptr->_intid, &previous);  assert (tmp == segptr);  assert (previous ? previous->_next == segptr : _segments_head == segptr);  if (previous)    previous->_next = segptr->_next;  else    _segments_head = segptr->_next;  assert (_shm_ids > 0);  _shm_ids -= 1;  _shm_tot -= segptr->_ds.shm_segsz;  safe_delete (segptr);}/*---------------------------------------------------------------------------* * client_request_shm::client_request_shm () *---------------------------------------------------------------------------*/client_request_shm::client_request_shm ()  : client_request (CYGSERVER_REQUEST_SHM,		    &_parameters, sizeof (_parameters)){  // verbose: syscall_printf ("created");}/*---------------------------------------------------------------------------* * client_request_shm::serve () *---------------------------------------------------------------------------*/voidclient_request_shm::serve (transport_layer_base *const conn,			   process_cache *const cache){  assert (conn);  assert (!error_code ());  if (msglen () != sizeof (_parameters.in))    {      syscall_printf ("bad request body length: expecting %lu bytes, got %lu",		      sizeof (_parameters), msglen ());      error_code (EINVAL);      msglen (0);      return;    }  // FIXME: Get a return code out of this and don't continue on error.  conn->impersonate_client ();  class process *const client = cache->process (_parameters.in.cygpid,						_parameters.in.winpid);  if (!client)    {      error_code (EAGAIN);      msglen (0);      return;    }  int result = -EINVAL;  switch (_parameters.in.shmop)    {    case SHMOP_shmget:      result = shmmgr.shmget (_parameters.out.shmid,			      _parameters.in.key, _parameters.in.size,			      _parameters.in.shmflg,			      _parameters.in.uid, _parameters.in.gid,			      client);      break;    case SHMOP_shmat:      result = shmmgr.shmat (_parameters.out.hFileMap,			     _parameters.in.shmid, _parameters.in.shmflg,			     client);      break;    case SHMOP_shmdt:      result = shmmgr.shmdt (_parameters.in.shmid, client);      break;    case SHMOP_shmctl:      result = shmmgr.shmctl (_parameters.out.shmid,			      _parameters.out.ds, _parameters.out.shminfo,			      _parameters.out.shm_info,			      _parameters.in.shmid, _parameters.in.cmd,			      _parameters.in.ds,			      client);      break;    }  client->release ();  conn->revert_to_self ();  if (result < 0)    {      error_code (-result);      msglen (0);    }  else    msglen (sizeof (_parameters.out));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -