📄 cygserver_shm.cc
字号:
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 + -