* cygserver.h (client_request::request_code_t): Add
CYGSERVER_REQUEST_MSG and CYGSERVER_REQUEST_SEM. (admininstrator_group_sid): Add extern declaration. * cygserver_ipc.h: Rewrite. * cygserver_msg.h: New file. * cygserver_sem.h: New file. * cygserver_shm.h: More or less rewrite. * cygwin.din: Add msgctl, msgget, msgrcv, msgsnd, semctl, semget and semop. * msg.cc: Rewrite. * safe_memory.h: Remove. * sem.cc: Rewrite. * shm.cc: Rewrite. * include/cygwin/ipc.h: Use appropriate guard. (struct ipc_perm): Add seq. (IPCID_TO_IX): New define from BSD. (IPCID_TO_SEQ): Ditto. (IXSEQ_TO_IPCID): Ditto. (IPC_R): Ditto. (IPC_W): Ditto. (IPC_M): Ditto. * include/cygwin/msg.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (msgqnum_t): Define unsigned. (msglen_t): Ditto. (struct msqid_ds): Add msg_first and msg_last. (struct msginfo): Remove msgpool. Add msgssz and msgseg. * include/cygwin/sem.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (SEM_UNDO): Define appropriately. (struct semid_ds): Add sem_base. (struct seminfo): Add semmap and semusz. (SEM_A): New define from BSD. (SEM_R): Ditto. (SEM_ALLOC): Ditto. (union semun): Define. * include/cygwin/shm.h: Use appropriate guard. #ifdef _KERNEL all stuff not explicitely defined by SUSv3. Use signed types in structs to match types used in BSD. (SHMLBA): Define using cygwin_internal(CW_GET_SHMLBA) call. (struct shmid_ds): Add shm_internal. (struct shm_info): Rename shm_ids to used_ids as in BSD. Add define for shm_ids. * include/cygwin/sysproto.h: New file. * include/cygwin/version.h: Bump API minor number. * include/sys/ipc.h: New file. * include/sys/msg.h: New file. * include/sys/queue.h: New file from BSD. * include/sys/sem.h: New file. * include/sys/shm.h: New file. * include/sys/sysproto.h: New file.
This commit is contained in:
		| @@ -1,3 +1,59 @@ | ||||
| 2003-11-19  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* cygserver.h (client_request::request_code_t): Add | ||||
| 	CYGSERVER_REQUEST_MSG and CYGSERVER_REQUEST_SEM. | ||||
| 	(admininstrator_group_sid): Add extern declaration. | ||||
| 	* cygserver_ipc.h: Rewrite. | ||||
| 	* cygserver_msg.h: New file. | ||||
| 	* cygserver_sem.h: New file. | ||||
| 	* cygserver_shm.h: More or less rewrite. | ||||
| 	* cygwin.din: Add msgctl, msgget, msgrcv, msgsnd, semctl, semget and | ||||
| 	semop. | ||||
| 	* msg.cc: Rewrite. | ||||
| 	* safe_memory.h: Remove. | ||||
| 	* sem.cc: Rewrite. | ||||
| 	* shm.cc: Rewrite. | ||||
| 	* include/cygwin/ipc.h: Use appropriate guard. | ||||
| 	(struct ipc_perm): Add seq. | ||||
| 	(IPCID_TO_IX): New define from BSD. | ||||
| 	(IPCID_TO_SEQ): Ditto. | ||||
| 	(IXSEQ_TO_IPCID): Ditto. | ||||
| 	(IPC_R): Ditto. | ||||
| 	(IPC_W): Ditto. | ||||
| 	(IPC_M): Ditto. | ||||
| 	* include/cygwin/msg.h: Use appropriate guard. #ifdef _KERNEL all stuff | ||||
| 	not explicitely defined by SUSv3. Use signed types in structs to match | ||||
| 	types used in BSD. | ||||
| 	(msgqnum_t): Define unsigned. | ||||
| 	(msglen_t): Ditto. | ||||
| 	(struct msqid_ds): Add msg_first and msg_last. | ||||
| 	(struct msginfo): Remove msgpool. Add msgssz and msgseg. | ||||
| 	* include/cygwin/sem.h: Use appropriate guard. #ifdef _KERNEL all stuff | ||||
| 	not explicitely defined by SUSv3. Use signed types in structs to match | ||||
| 	types used in BSD. | ||||
| 	(SEM_UNDO): Define appropriately. | ||||
| 	(struct semid_ds): Add sem_base. | ||||
| 	(struct seminfo): Add semmap and semusz. | ||||
| 	(SEM_A): New define from BSD. | ||||
| 	(SEM_R): Ditto. | ||||
| 	(SEM_ALLOC): Ditto. | ||||
| 	(union semun): Define. | ||||
| 	* include/cygwin/shm.h: Use appropriate guard. #ifdef _KERNEL all stuff | ||||
| 	not explicitely defined by SUSv3. Use signed types in structs to match | ||||
| 	types used in BSD. | ||||
| 	(SHMLBA): Define using cygwin_internal(CW_GET_SHMLBA) call. | ||||
| 	(struct shmid_ds): Add shm_internal. | ||||
| 	(struct shm_info): Rename shm_ids to used_ids as in BSD.  Add define | ||||
| 	for shm_ids. | ||||
| 	* include/cygwin/sysproto.h: New file. | ||||
| 	* include/cygwin/version.h: Bump API minor number. | ||||
| 	* include/sys/ipc.h: New file. | ||||
| 	* include/sys/msg.h: New file. | ||||
| 	* include/sys/queue.h: New file from BSD. | ||||
| 	* include/sys/sem.h: New file. | ||||
| 	* include/sys/shm.h: New file. | ||||
| 	* include/sys/sysproto.h: New file. | ||||
|  | ||||
| 2003-11-19  Corinna Vinschen  <corinna@vinschen.de> | ||||
|  | ||||
| 	* dtable.cc (build_fh_pc): Resurrect accidentally removed | ||||
|   | ||||
| @@ -48,6 +48,8 @@ protected: | ||||
|     CYGSERVER_REQUEST_GET_VERSION, | ||||
|     CYGSERVER_REQUEST_SHUTDOWN, | ||||
|     CYGSERVER_REQUEST_ATTACH_TTY, | ||||
|     CYGSERVER_REQUEST_MSG, | ||||
|     CYGSERVER_REQUEST_SEM, | ||||
|     CYGSERVER_REQUEST_SHM, | ||||
|     CYGSERVER_REQUEST_LAST | ||||
|   } request_code_t; | ||||
| @@ -178,6 +180,10 @@ private: | ||||
| #endif | ||||
| }; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| extern PSID admininstrator_group_sid; | ||||
| #endif | ||||
|  | ||||
| extern bool check_cygserver_available (); | ||||
| extern void cygserver_init (); | ||||
|  | ||||
|   | ||||
| @@ -1,8 +1,6 @@ | ||||
| /* cygserver_ipc.h | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
|    Originally written by Conrad Scott <conrad.scott@dsl.pipex.com> | ||||
|    Copyright 2002, 2003 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -13,72 +11,72 @@ details. */ | ||||
| #ifndef __CYGSERVER_IPC_H__ | ||||
| #define __CYGSERVER_IPC_H__ | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <limits.h>		/* For OPEN_MAX. */ | ||||
|  | ||||
| /* | ||||
|  * The sysv ipc id's (msgid, semid, shmid) are integers arranged such | ||||
|  * that they no subsystem will generate the same id as some other | ||||
|  * subsystem; nor do these ids overlap file descriptors (the other | ||||
|  * common integer ids).  Since Cygwin can allocate more than OPEN_MAX | ||||
|  * file descriptors, it can't be guaranteed not to overlap, but it | ||||
|  * should help catch some errors. | ||||
|  * | ||||
|  * msgid's: OPEN_MAX,     OPEN_MAX + 3, OPEN_MAX + 6, . . . | ||||
|  * semid's: OPEN_MAX + 1, OPEN_MAX + 4, OPEN_MAX + 7, . . . | ||||
|  * shmid's: OPEN_MAX + 2, OPEN_MAX + 5, OPEN_MAX + 8, . . . | ||||
|  * | ||||
|  * To further ensure that ids are unique, if ipc objects are created | ||||
|  * and destroyed and then re-created, they are given new ids by | ||||
|  * munging the basic id (as above) with a sequence number. | ||||
|  * | ||||
|  * Internal ipc id's, which are 0, 1, ... within each subsystem (and | ||||
|  * not munged with a sequence number), are used solely by the ipcs(8) | ||||
|  * interface. | ||||
|  * Datastructure which is part of any IPC input parameter block. | ||||
|  */ | ||||
| struct vmspace { | ||||
|   void *vm_map;			/* UNUSED */ | ||||
|   struct shmmap_state *vm_shm; | ||||
| }; | ||||
|  | ||||
| enum ipc_subsys_t | ||||
|   { | ||||
|     IPC_MSGOP = 0, | ||||
|     IPC_SEMOP = 1, | ||||
|     IPC_SHMOP = 2, | ||||
|     IPC_SUBSYS_COUNT | ||||
| struct proc { | ||||
|   pid_t cygpid; | ||||
|   DWORD winpid; | ||||
|   __uid32_t uid; | ||||
|   __gid32_t gid; | ||||
|   int gidcnt; | ||||
|   __gid32_t *gidlist; | ||||
|   bool is_admin; | ||||
|   struct vmspace *p_vmspace; | ||||
| }; | ||||
|  | ||||
| #ifdef __INSIDE_CYGWIN__ | ||||
| inline void | ||||
| ipc_set_proc_info (proc &blk) | ||||
| { | ||||
|   blk.cygpid = getpid (); | ||||
|   blk.winpid = GetCurrentProcessId (); | ||||
|   blk.uid = geteuid32 (); | ||||
|   blk.gid = getegid32 (); | ||||
|   blk.gidcnt = 0; | ||||
|   blk.gidlist = NULL; | ||||
|   blk.is_admin = false; | ||||
| } | ||||
| #endif /* __INSIDE_CYGWIN__ */ | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| class ipc_retval { | ||||
| private: | ||||
|   union { | ||||
|     int i; | ||||
|     unsigned int u; | ||||
|     vm_offset_t off; | ||||
|     vm_object_t obj; | ||||
|   }; | ||||
|  | ||||
| /* | ||||
|  * IPCMNI - The absolute maximum number of simultaneous ipc ids for | ||||
|  * any one subsystem. | ||||
|  */ | ||||
| public: | ||||
|   ipc_retval (int ni) { i = ni; } | ||||
|  | ||||
| enum | ||||
|   { | ||||
|     IPCMNI = 0x10000		// Must be a power of two. | ||||
|   }; | ||||
|   operator int () const { return i; } | ||||
|   int operator = (int ni) { return i = ni; } | ||||
|  | ||||
| inline int | ||||
| ipc_int2ext (const int intid, const ipc_subsys_t subsys, long & sequence) | ||||
| { | ||||
|   assert (0 <= intid && intid < IPCMNI); | ||||
|   operator unsigned int () const { return u; } | ||||
|   unsigned int operator = (unsigned int nu) { return u = nu; } | ||||
|  | ||||
|   const long tmp = InterlockedIncrement (&sequence); | ||||
|   operator vm_offset_t () const { return off; } | ||||
|   vm_offset_t operator = (vm_offset_t noff) { return off = noff; } | ||||
|  | ||||
|   return (((tmp & 0x7fff) << 16) | ||||
| 	  | (OPEN_MAX + (intid * IPC_SUBSYS_COUNT) + subsys)); | ||||
| } | ||||
|   operator vm_object_t () const { return obj; } | ||||
|   vm_object_t operator = (vm_object_t nobj) { return obj = nobj; } | ||||
| }; | ||||
|  | ||||
| inline int | ||||
| ipc_ext2int_subsys (const int extid) | ||||
| { | ||||
|   return ((extid & (IPCMNI - 1)) - OPEN_MAX) % IPC_SUBSYS_COUNT; | ||||
| } | ||||
|  | ||||
| inline int | ||||
| ipc_ext2int (const int extid, const ipc_subsys_t subsys) | ||||
| { | ||||
|   if (ipc_ext2int_subsys (extid) != subsys) | ||||
|     return -1; | ||||
|   else | ||||
|     return ((extid & (IPCMNI - 1)) - OPEN_MAX) / IPC_SUBSYS_COUNT; | ||||
| } | ||||
| struct thread { | ||||
|   class process *client; | ||||
|   proc *ipcblk; | ||||
|   ipc_retval td_retval[2]; | ||||
| }; | ||||
| #define td_proc ipcblk | ||||
| #define p_pid cygpid | ||||
| #endif | ||||
|  | ||||
| #endif /* __CYGSERVER_IPC_H__ */ | ||||
|   | ||||
							
								
								
									
										91
									
								
								winsup/cygwin/cygserver_msg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								winsup/cygwin/cygserver_msg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,91 @@ | ||||
| /* cygserver_msg.h: Single unix specification 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. */ | ||||
|  | ||||
| #ifndef __CYGSERVER_MSG_H__ | ||||
| #define __CYGSERVER_MSG_H__ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/sysproto.h> | ||||
| #ifndef _KERNEL | ||||
| #define _KERNEL 1 | ||||
| #endif | ||||
| #include <cygwin/msg.h> | ||||
|  | ||||
| #include "cygserver.h" | ||||
| #include "cygserver_ipc.h" | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| class transport_layer_base; | ||||
| class process_cache; | ||||
| #endif | ||||
|  | ||||
| class client_request_msg : public client_request | ||||
| { | ||||
|   friend class client_request; | ||||
|  | ||||
| public: | ||||
|   enum msgop_t | ||||
|     { | ||||
|       MSGOP_msgctl, | ||||
|       MSGOP_msgget, | ||||
|       MSGOP_msgrcv, | ||||
|       MSGOP_msgsnd | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|   union | ||||
|   { | ||||
|     struct | ||||
|     { | ||||
|       msgop_t msgop; | ||||
|       proc ipcblk; | ||||
|       union | ||||
|       { | ||||
|         struct msgctl_args ctlargs; | ||||
| 	struct msgget_args getargs; | ||||
| 	struct msgrcv_args rcvargs; | ||||
| 	struct msgsnd_args sndargs; | ||||
|       }; | ||||
|     } in; | ||||
|  | ||||
|     union { | ||||
|       int ret; | ||||
|       ssize_t rcv; | ||||
|     } out; | ||||
|   } _parameters; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
|   client_request_msg (); | ||||
|   virtual void serve (transport_layer_base *, process_cache *); | ||||
| #endif | ||||
|  | ||||
| public: | ||||
|  | ||||
| #ifdef __INSIDE_CYGWIN__ | ||||
|   client_request_msg (int, int, struct msqid_ds *);	// msgctl | ||||
|   client_request_msg (key_t, int);			// msgget | ||||
|   client_request_msg (int, void *, size_t, long, int);	// msgrcv | ||||
|   client_request_msg (int, const void *, size_t, int);	// msgsnd | ||||
| #endif | ||||
|  | ||||
|   int retval (void) const { return _parameters.out.ret; } | ||||
|   ssize_t rcvval (void) const { return _parameters.out.rcv; } | ||||
| }; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| int msginit (void); | ||||
| int msgunload (void); | ||||
| int msgctl (struct thread *, struct msgctl_args *); | ||||
| int msgget (struct thread *, struct msgget_args *); | ||||
| int msgsnd (struct thread *, struct msgsnd_args *); | ||||
| int msgrcv (struct thread *, struct msgrcv_args *); | ||||
| #endif | ||||
|  | ||||
| #endif /* __CYGSERVER_MSG_H__ */ | ||||
							
								
								
									
										87
									
								
								winsup/cygwin/cygserver_sem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								winsup/cygwin/cygserver_sem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,87 @@ | ||||
| /* cygserver_sem.h: Single unix specification 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. */ | ||||
|  | ||||
| #ifndef __CYGSERVER_SEM_H__ | ||||
| #define __CYGSERVER_SEM_H__ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/sysproto.h> | ||||
| #ifndef _KERNEL | ||||
| #define _KERNEL 1 | ||||
| #endif | ||||
| #include <cygwin/sem.h> | ||||
|  | ||||
| #include "cygserver.h" | ||||
| #include "cygserver_ipc.h" | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| class transport_layer_base; | ||||
| class process_cache; | ||||
| #endif | ||||
|  | ||||
| class client_request_sem : public client_request | ||||
| { | ||||
|   friend class client_request; | ||||
|  | ||||
| public: | ||||
|   enum semop_t | ||||
|     { | ||||
|       SEMOP_semctl, | ||||
|       SEMOP_semget, | ||||
|       SEMOP_semop | ||||
|     }; | ||||
|  | ||||
| private: | ||||
|   union | ||||
|   { | ||||
|     struct | ||||
|     { | ||||
|       semop_t semop; | ||||
|       proc ipcblk; | ||||
|       union | ||||
|       { | ||||
|         struct semctl_args ctlargs; | ||||
| 	struct semget_args getargs; | ||||
| 	struct semop_args  opargs; | ||||
|       }; | ||||
|     } in; | ||||
|  | ||||
|     union { | ||||
|       int ret; | ||||
|     } out; | ||||
|   } _parameters; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
|   client_request_sem (); | ||||
|   virtual void serve (transport_layer_base *, process_cache *); | ||||
| #endif | ||||
|  | ||||
| public: | ||||
|  | ||||
| #ifdef __INSIDE_CYGWIN__ | ||||
|   client_request_sem (int, int, int, union semun *);	// semctl | ||||
|   client_request_sem (key_t, int, int);			// semget | ||||
|   client_request_sem (int, struct sembuf *, size_t);	// semop | ||||
| #endif | ||||
|  | ||||
|   int retval (void) const { return _parameters.out.ret; } | ||||
| }; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| int seminit (void); | ||||
| int semunload (void); | ||||
| void semexit_myhook(void *arg, struct proc *p); | ||||
|  | ||||
| int semctl (struct thread *, struct semctl_args *); | ||||
| int semget (struct thread *, struct semget_args *); | ||||
| int semop (struct thread *, struct semop_args *); | ||||
| #endif | ||||
|  | ||||
| #endif /* __CYGSERVER_SEM_H__ */ | ||||
| @@ -1,9 +1,6 @@ | ||||
| /* cygserver_shm.h: 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>. | ||||
|    Copyright 2003 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -15,38 +12,14 @@ details. */ | ||||
| #define __CYGSERVER_SHM_H__ | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <sys/sysproto.h> | ||||
| #ifndef _KERNEL | ||||
| #define _KERNEL 1 | ||||
| #endif | ||||
| #include <cygwin/shm.h> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <limits.h> | ||||
|  | ||||
| #include "cygserver_ipc.h" | ||||
|  | ||||
| #include "cygserver.h" | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * Values for the shminfo entries. | ||||
|  * | ||||
|  * Nb. The values are segregated between two enums so that the `small' | ||||
|  * values aren't promoted to `unsigned long' equivalents. | ||||
|  *---------------------------------------------------------------------------*/ | ||||
|  | ||||
| enum | ||||
|   { | ||||
|     SHMMAX = ULONG_MAX, | ||||
|     SHMSEG = ULONG_MAX, | ||||
|     SHMALL = ULONG_MAX | ||||
|   }; | ||||
|  | ||||
| enum | ||||
|   { | ||||
|     SHMMIN = 1, | ||||
|     SHMMNI = IPCMNI		// Must be <= IPCMNI. | ||||
|   }; | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * class client_request_shm | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| #include "cygserver_ipc.h" | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| class transport_layer_base; | ||||
| @@ -63,85 +36,63 @@ public: | ||||
|       SHMOP_shmat, | ||||
|       SHMOP_shmctl, | ||||
|       SHMOP_shmdt, | ||||
|       SHMOP_shmget | ||||
|       SHMOP_shmget, | ||||
|       SHMOP_shmfork	/* Called on fixup_after_fork */ | ||||
|     }; | ||||
|  | ||||
| #ifdef __INSIDE_CYGWIN__ | ||||
|   client_request_shm (int shmid, int shmflg); // shmat | ||||
|   client_request_shm (int shmid, int cmd, const struct shmid_ds *); // shmctl | ||||
|   client_request_shm (int shmid); // shmdt | ||||
|   client_request_shm (key_t, size_t, int shmflg); // shmget | ||||
| #endif | ||||
|  | ||||
|   // Accessors for out parameters. | ||||
|  | ||||
|   int shmid () const | ||||
|   { | ||||
|     assert (!error_code ()); | ||||
|     return _parameters.out.shmid; | ||||
|   } | ||||
|  | ||||
|   HANDLE hFileMap () const | ||||
|   { | ||||
|     assert (!error_code ()); | ||||
|     return _parameters.out.hFileMap; | ||||
|   } | ||||
|  | ||||
|   const struct shmid_ds & ds () const | ||||
|   { | ||||
|     assert (!error_code ()); | ||||
|     return _parameters.out.ds; | ||||
|   } | ||||
|  | ||||
|   const struct shminfo & shminfo () const | ||||
|   { | ||||
|     assert (!error_code ()); | ||||
|     return _parameters.out.shminfo; | ||||
|   } | ||||
|  | ||||
|   const struct shm_info & shm_info () const | ||||
|   { | ||||
|     assert (!error_code ()); | ||||
|     return _parameters.out.shm_info; | ||||
|   } | ||||
|  | ||||
| private: | ||||
|   union | ||||
|   { | ||||
|     struct | ||||
|     { | ||||
|       shmop_t shmop; | ||||
|       key_t key; | ||||
|       size_t size; | ||||
|       int shmflg; | ||||
|       int shmid; | ||||
|       int cmd; | ||||
|       pid_t cygpid; | ||||
|       DWORD winpid; | ||||
|       __uid32_t uid; | ||||
|       __gid32_t gid; | ||||
|       struct shmid_ds ds; | ||||
|       proc ipcblk; | ||||
|       struct shmat_args  atargs; | ||||
|       struct shmctl_args ctlargs; | ||||
|       struct shmdt_args  dtargs; | ||||
|       struct shmget_args getargs; | ||||
|       struct proc        forkargs; | ||||
|     } in; | ||||
|  | ||||
|     struct { | ||||
|       int shmid; | ||||
|       union | ||||
|       { | ||||
| 	HANDLE hFileMap; | ||||
| 	struct shmid_ds ds; | ||||
| 	struct shminfo shminfo; | ||||
| 	struct shm_info shm_info; | ||||
|       union { | ||||
| 	int ret; | ||||
| 	vm_offset_t ptr; | ||||
|       }; | ||||
|       vm_object_t obj; | ||||
|     } out; | ||||
|   } _parameters; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
|   client_request_shm (); | ||||
| #endif | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
|   virtual void serve (transport_layer_base *, process_cache *); | ||||
| #endif | ||||
|  | ||||
| public: | ||||
|  | ||||
| #ifdef __INSIDE_CYGWIN__ | ||||
|   client_request_shm (int, const void *, int);		// shmat | ||||
|   client_request_shm (int, int, struct shmid_ds *);	// shmctl | ||||
|   client_request_shm (const void *);			// shmdt | ||||
|   client_request_shm (key_t, size_t, int);		// shmget | ||||
|   client_request_shm (proc *);				// shmfork | ||||
| #endif | ||||
|  | ||||
|   int retval (void) const { return _parameters.out.ret; } | ||||
|   void *ptrval (void) const { return (void *)_parameters.out.ptr; } | ||||
|   vm_object_t objval (void) const { return _parameters.out.obj; } | ||||
| }; | ||||
|  | ||||
| #ifndef __INSIDE_CYGWIN__ | ||||
| void shminit (void); | ||||
| int shmunload (void); | ||||
| void shmexit_myhook (struct vmspace *vm); | ||||
| int cygwin_shmfork_myhook (struct thread *, struct proc *); | ||||
|  | ||||
| int shmat (struct thread *, struct shmat_args *); | ||||
| int shmctl (struct thread *, struct shmctl_args *); | ||||
| int shmdt (struct thread *, struct shmdt_args *); | ||||
| int shmget (struct thread *, struct shmget_args *); | ||||
| #endif | ||||
|  | ||||
| #endif /* __CYGSERVER_SHM_H__ */ | ||||
|   | ||||
| @@ -910,6 +910,10 @@ mount | ||||
| _mount = mount | ||||
| mprotect | ||||
| mrand48 | ||||
| msgctl | ||||
| msgget | ||||
| msgrcv | ||||
| msgsnd | ||||
| msync | ||||
| munmap | ||||
| nan | ||||
| @@ -1131,6 +1135,9 @@ _seed48 = seed48 | ||||
| seekdir | ||||
| _seekdir = seekdir | ||||
| _seekdir64 = seekdir64 | ||||
| semctl | ||||
| semget | ||||
| semop | ||||
| sem_close | ||||
| sem_destroy | ||||
| sem_getvalue | ||||
|   | ||||
| @@ -1106,7 +1106,7 @@ fhandler_socket::close () | ||||
|      solution but it helps in many cases. */ | ||||
|   struct linger linger; | ||||
|   linger.l_onoff = 1; | ||||
|   linger.l_linger = 240; /* seconds. default 2MSL value according to MSDN. */ | ||||
|   linger.l_linger = 240; /* secs. default 2MSL value according to MSDN. */ | ||||
|   setsockopt (get_socket (), SOL_SOCKET, SO_LINGER, | ||||
| 	      (const char *)&linger, sizeof linger); | ||||
|  | ||||
|   | ||||
| @@ -9,8 +9,8 @@ This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #ifndef _SYS_IPC_H | ||||
| #define _SYS_IPC_H | ||||
| #ifndef _CYGWIN_IPC_H | ||||
| #define _CYGWIN_IPC_H | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| @@ -25,6 +25,7 @@ struct ipc_perm | ||||
|   gid_t  cgid;			/* Creator's group ID. */ | ||||
|   mode_t mode;			/* Read/write permission. */ | ||||
|   key_t  key; | ||||
|   unsigned short seq; | ||||
| }; | ||||
|  | ||||
| /* Mode bits: | ||||
| @@ -44,10 +45,20 @@ struct ipc_perm | ||||
| #define IPC_STAT 0x1002		/* Get options. */ | ||||
| #define IPC_INFO 0x1003		/* For ipcs(8). */ | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| #define IPCID_TO_IX(id)         ((id) & 0xffff) | ||||
| #define IPCID_TO_SEQ(id)        (((id) >> 16) & 0xffff) | ||||
| #define IXSEQ_TO_IPCID(ix,perm) (((perm.seq) << 16) | (ix & 0xffff)) | ||||
|  | ||||
| #define IPC_R           000400  /* read permission */ | ||||
| #define IPC_W           000200  /* write/alter permission */ | ||||
| #define IPC_M           010000  /* permission to change control info */ | ||||
| #endif | ||||
|  | ||||
| key_t ftok (const char *path, int id); | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SYS_IPC_H */ | ||||
| #endif /* _CYGWIN_IPC_H */ | ||||
|   | ||||
| @@ -9,8 +9,8 @@ This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #ifndef _SYS_MSG_H | ||||
| #define _SYS_MSG_H | ||||
| #ifndef _CYGWIN_MSG_H | ||||
| #define _CYGWIN_MSG_H | ||||
|  | ||||
| #include <cygwin/ipc.h> | ||||
|  | ||||
| @@ -23,18 +23,20 @@ extern "C" | ||||
|  */ | ||||
| #define MSG_NOERROR 0x01	/* No error if big message. */ | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* Command definitions for the semctl () function: | ||||
|  */ | ||||
| #define MSG_STAT   0x2000	/* For ipcs(8) */ | ||||
| #define MSG_INFO   0x2001	/* For ipcs(8) */ | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| /* Used for the number of messages in the message queue. | ||||
|  */ | ||||
| typedef long int msgqnum_t; | ||||
| typedef unsigned long msgqnum_t; | ||||
|  | ||||
| /* Used for the number of bytes allowed in a message queue. | ||||
|  */ | ||||
| typedef long int msglen_t; | ||||
| typedef unsigned long msglen_t; | ||||
|  | ||||
| struct msqid_ds | ||||
| { | ||||
| @@ -47,38 +49,46 @@ struct msqid_ds | ||||
|   timestruc_t     msg_stim;	/* Time of last msgsnd (). */ | ||||
|   timestruc_t     msg_rtim;	/* Time of last msgrcv (). */ | ||||
|   timestruc_t     msg_ctim;	/* Time of last change. */ | ||||
| #ifdef _KERNEL | ||||
|   struct msg     *msg_first; | ||||
|   struct msg     *msg_last; | ||||
| #else | ||||
|   long            msg_spare4[2]; | ||||
| #endif /* _KERNEL */ | ||||
| }; | ||||
|  | ||||
| #define msg_stime msg_stim.tv_sec | ||||
| #define msg_rtime msg_rtim.tv_sec | ||||
| #define msg_ctime msg_ctim.tv_sec | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* Buffer type for msgctl (IPC_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct msginfo | ||||
| { | ||||
|   unsigned long msgpool;	/* Maximum number of message bytes, | ||||
| 				   system wide. */ | ||||
|   unsigned long msgmax;		/* Maximum number of bytes per | ||||
| 				   message. */ | ||||
|   unsigned long msgmnb;		/* Maximum number of bytes on any one | ||||
| 				   message queue. */ | ||||
|   unsigned long msgmni;		/* Maximum number of message queues, | ||||
| 				   system wide. */ | ||||
|   unsigned long msgtql;		/* Maximum number of messages, system | ||||
| 				   wide. */ | ||||
|   unsigned long msg_spare[4]; | ||||
|   long msgmax;		/* Maximum number of bytes per | ||||
| 			   message. */ | ||||
|   long msgmnb;		/* Maximum number of bytes on any one | ||||
| 			   message queue. */ | ||||
|   long msgmni;		/* Maximum number of message queues, | ||||
| 			   system wide. */ | ||||
|   long msgtql;		/* Maximum number of messages, system | ||||
| 			   wide. */ | ||||
|   long msgssz;		/* Size of a message segment, must be | ||||
| 			   small power of 2 greater than 4. */ | ||||
|   long msgseg;		/* Number of message segments */ | ||||
|   long msg_spare[2]; | ||||
| }; | ||||
|  | ||||
| /* Buffer type for msgctl (MSG_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct msg_info | ||||
| { | ||||
|   unsigned long msg_ids;	/* Number of allocated queues. */ | ||||
|   unsigned long msg_num;	/* Number of messages, system wide. */ | ||||
|   unsigned long msg_tot;	/* Size in bytes of messages, system wide. */ | ||||
|   long msg_ids;		/* Number of allocated queues. */ | ||||
|   long msg_num;		/* Number of messages, system wide. */ | ||||
|   long msg_tot;		/* Size in bytes of messages, system wide. */ | ||||
| }; | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| int     msgctl (int msqid, int cmd, struct msqid_ds *buf); | ||||
| int     msgget (key_t key, int msgflg); | ||||
| @@ -89,4 +99,4 @@ int     msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SYS_MSG_H */ | ||||
| #endif /* _CYGWIN_MSG_H */ | ||||
|   | ||||
| @@ -9,8 +9,8 @@ This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #ifndef _SYS_SEM_H | ||||
| #define _SYS_SEM_H | ||||
| #ifndef _CYGWIN_SEM_H | ||||
| #define _CYGWIN_SEM_H | ||||
|  | ||||
| #include <cygwin/ipc.h> | ||||
|  | ||||
| @@ -21,7 +21,7 @@ extern "C" | ||||
|  | ||||
| /* Semaphore operation flags: | ||||
|  */ | ||||
| #define SEM_UNDO		/* Set up adjust on exit entry. */ | ||||
| #define SEM_UNDO   010000	/* Set up adjust on exit entry. */ | ||||
|  | ||||
| /* Command definitions for the semctl () function: | ||||
|  */ | ||||
| @@ -33,8 +33,10 @@ extern "C" | ||||
| #define SETVAL     0x3005	/* Set semval. */ | ||||
| #define SETALL     0x3006	/* Set all cases of semval. */ | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| #define SEM_STAT   0x3010	/* For ipcs(8). */ | ||||
| #define SEM_INFO   0x3011	/* For ipcs(8). */ | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| struct semid_ds | ||||
| { | ||||
| @@ -42,7 +44,12 @@ struct semid_ds | ||||
|   unsigned short   sem_nsems;	/* Number of semaphores in set. */ | ||||
|   timestruc_t      sem_otim;	/* Last semop () time. */ | ||||
|   timestruc_t      sem_ctim;	/* Last time changed by semctl (). */ | ||||
| #ifdef _KERNEL | ||||
|   struct sem	  *sem_base;	/* pointer to first semaphore in set */ | ||||
|   long             sem_spare4[1]; | ||||
| #else | ||||
|   long             sem_spare4[2]; | ||||
| #endif /* _KERNEL */ | ||||
| }; | ||||
|  | ||||
| #define sem_otime sem_otim.tv_sec | ||||
| @@ -55,35 +62,61 @@ struct sembuf | ||||
|   short           sem_flg;	/* Operation flags. */ | ||||
| }; | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* Buffer type for semctl (IPC_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct seminfo | ||||
| { | ||||
|   unsigned long semmni;		/* Maximum number of unique semaphore | ||||
| 				   sets, system wide. */ | ||||
|   unsigned long semmns;		/* Maximum number of semaphores, | ||||
| 				   system wide. */ | ||||
|   unsigned long semmsl;		/* Maximum number of semaphores per | ||||
| 				   semaphore set. */ | ||||
|   unsigned long semopm;		/* Maximum number of operations per | ||||
| 				   semop call. */ | ||||
|   unsigned long semmnu;		/* Maximum number of undo structures, | ||||
| 				   system wide. */ | ||||
|   unsigned long semume;		/* Maximum number of undo entries per | ||||
| 				   undo structure. */ | ||||
|   unsigned long semvmx;		/* Maximum semaphore value. */ | ||||
|   unsigned long semaem;		/* Maximum adjust-on-exit value. */ | ||||
|   unsigned long sem_spare[4]; | ||||
|   long semmni;		/* Maximum number of unique semaphore | ||||
| 			   sets, system wide. */ | ||||
|   long semmns;		/* Maximum number of semaphores, | ||||
| 			   system wide. */ | ||||
|   long semmsl;		/* Maximum number of semaphores per | ||||
| 			   semaphore set. */ | ||||
|   long semopm;		/* Maximum number of operations per | ||||
| 			   semop call. */ | ||||
|   long semmnu;		/* Maximum number of undo structures, | ||||
| 			   system wide. */ | ||||
|   long semume;		/* Maximum number of undo entries per | ||||
| 			   undo structure. */ | ||||
|   long semvmx;		/* Maximum semaphore value. */ | ||||
|   long semaem;		/* Maximum adjust-on-exit value. */ | ||||
|   long semmap;		/* # of entries in semaphore map */ | ||||
|   long semusz;		/* size in bytes of undo structure */ | ||||
|   long sem_spare[2]; | ||||
| }; | ||||
|  | ||||
| /* Buffer type for semctl (SEM_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct sem_info | ||||
| { | ||||
|   unsigned long sem_ids;	/* Number of allocated semaphore sets. */ | ||||
|   unsigned long sem_num;	/* Number of allocated semaphores. */ | ||||
|   long sem_ids;		/* Number of allocated semaphore sets. */ | ||||
|   long sem_num;		/* Number of allocated semaphores. */ | ||||
| }; | ||||
|  | ||||
| /* Permission flags */ | ||||
| #define SEM_A		IPC_W	/* alter permission */ | ||||
| #define SEM_R		IPC_R	/* read permission */ | ||||
|  | ||||
| /* Internally used mode bits. */ | ||||
| #define	SEM_ALLOC	01000	/* semaphore is allocated */ | ||||
|  | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* According to SUSv3, "the fourth argument [to semctl()] is optional and | ||||
|    depends upon the operation requested. If required, it is of type | ||||
|    union semun, which the application shall explicitly declare:" */ | ||||
| union semun { | ||||
|     int val;			/* value for SETVAL */ | ||||
|     struct semid_ds *buf;	/* buffer for IPC_STAT, IPC_SET */ | ||||
|     unsigned short  *array;	/* array for GETALL, SETALL */ | ||||
| }; | ||||
| /* Therefore this union is only declared here if building internal code. | ||||
|    _KERNEL must not be defined in exernal applications!  Declare union | ||||
|    semun explicitely as required by SUSv3, please. */ | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| int semctl (int semid, int semnum, int cmd, ...); | ||||
| int semget (key_t key, int nsems, int semflg); | ||||
| int semop (int semid, struct sembuf *sops, size_t nsops); | ||||
| @@ -92,4 +125,4 @@ int semop (int semid, struct sembuf *sops, size_t nsops); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SYS_SEM_H */ | ||||
| #endif /* _CYGWIN_SEM_H */ | ||||
|   | ||||
| @@ -9,30 +9,34 @@ This software is a copyrighted work licensed under the terms of the | ||||
| Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #ifndef _SYS_SHM_H | ||||
| #define _SYS_SHM_H | ||||
| #ifndef _CYGWIN_SHM_H | ||||
| #define _CYGWIN_SHM_H | ||||
|  | ||||
| #include <cygwin/ipc.h> | ||||
| #include <sys/cygwin.h> | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" | ||||
| { | ||||
| #endif | ||||
|  | ||||
| /* 64 Kb was hardcoded for x86. MS states this may change, but we need | ||||
|  * it in the header file. | ||||
|  */ | ||||
| #define SHMLBA 65536		/* Segment low boundary address multiple. */ | ||||
| /* Segment low boundary address multiple. | ||||
|  * | ||||
|  * 64 Kb was hardcoded for x86. MS states this may change so the constant | ||||
|  * expression is replaced by a function call returning the correct value. */ | ||||
| #define SHMLBA	(cygwin_internal (CW_GET_SHMLBA)) | ||||
|  | ||||
| /* Shared memory operation flags: | ||||
|  */ | ||||
| #define SHM_RDONLY 0x01		/* Attach read-only (else read-write). */ | ||||
| #define SHM_RND    0x02		/* Round attach address to SHMLBA. */ | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* Command definitions for the semctl () function: | ||||
|  */ | ||||
| #define SHM_STAT   0x4000	/* For ipcs(8) */ | ||||
| #define SHM_INFO   0x4001	/* For ipcs(8) */ | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| /* Unsigned integer used for the number of current attaches. | ||||
|  */ | ||||
| @@ -40,47 +44,55 @@ typedef unsigned int shmatt_t; | ||||
|  | ||||
| struct shmid_ds | ||||
| { | ||||
|   struct ipc_perm shm_perm;	/* Operation permission structure. */ | ||||
|   size_t          shm_segsz;	/* Size of segment in bytes. */ | ||||
|   pid_t           shm_lpid;	/* Process ID of last operation. */ | ||||
|   pid_t           shm_cpid;	/* Process ID of creator. */ | ||||
|   shmatt_t        shm_nattch;	/* Number of current attaches. */ | ||||
|   timestruc_t     shm_atim;	/* Time of last shmat (). */ | ||||
|   timestruc_t     shm_dtim;	/* Time of last shmdt (). */ | ||||
|   timestruc_t     shm_ctim;	/* Time of last change by shmctl (). */ | ||||
|   long            shm_spare4[2]; | ||||
|   struct ipc_perm    shm_perm;	/* Operation permission structure. */ | ||||
|   size_t             shm_segsz;	/* Size of segment in bytes. */ | ||||
|   pid_t              shm_lpid;	/* Process ID of last operation. */ | ||||
|   pid_t              shm_cpid;	/* Process ID of creator. */ | ||||
|   shmatt_t           shm_nattch;/* Number of current attaches. */ | ||||
|   timestruc_t        shm_atim;	/* Time of last shmat (). */ | ||||
|   timestruc_t        shm_dtim;	/* Time of last shmdt (). */ | ||||
|   timestruc_t        shm_ctim;	/* Time of last change by shmctl (). */ | ||||
| #ifdef _KERNEL | ||||
|   struct shm_handle *shm_internal; | ||||
|   long               shm_spare4[1]; | ||||
| #else | ||||
|   long               shm_spare4[2]; | ||||
| #endif /* _KERNEL */ | ||||
| }; | ||||
|  | ||||
| #define shm_atime shm_atim.tv_sec | ||||
| #define shm_dtime shm_dtim.tv_sec | ||||
| #define shm_ctime shm_ctim.tv_sec | ||||
|  | ||||
| #ifdef _KERNEL | ||||
| /* Buffer type for shmctl (IPC_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct shminfo | ||||
| { | ||||
|   unsigned long shmmax;		/* Maximum size in bytes of a shared | ||||
| 				   memory segment. */ | ||||
|   unsigned long shmmin;		/* Minimum size in bytes of a shared | ||||
| 				   memory segment. */ | ||||
|   unsigned long shmmni;		/* Maximum number of shared memory | ||||
| 				   segments, system wide. */ | ||||
|   unsigned long shmseg;		/* Maximum number of shared memory | ||||
| 				   segments attached per process. */ | ||||
|   unsigned long shmall;		/* Maximum number of bytes of shared | ||||
| 				   memory, system wide. */ | ||||
|   unsigned long shm_spare[4]; | ||||
|   long shmmax;		/* Maximum size in bytes of a shared | ||||
| 			   memory segment. */ | ||||
|   long shmmin;		/* Minimum size in bytes of a shared | ||||
| 			   memory segment. */ | ||||
|   long shmmni;		/* Maximum number of shared memory | ||||
| 			   segments, system wide. */ | ||||
|   long shmseg;		/* Maximum number of shared memory | ||||
| 			   segments attached per process. */ | ||||
|   long shmall;		/* Maximum number of bytes of shared | ||||
| 			   memory, system wide. */ | ||||
|   long shm_spare[4]; | ||||
| }; | ||||
|  | ||||
| /* Buffer type for shmctl (SHM_INFO, ...) as used by ipcs(8). | ||||
|  */ | ||||
| struct shm_info | ||||
| { | ||||
|   unsigned long shm_ids;	/* Number of allocated segments. */ | ||||
|   unsigned long shm_tot;	/* Size in bytes of allocated segments. */ | ||||
|   unsigned long shm_atts;	/* Number of attached segments, system | ||||
| 				   wide. */ | ||||
| #define shm_ids used_ids | ||||
|   long used_ids;	/* Number of allocated segments. */ | ||||
|   long shm_tot;		/* Size in bytes of allocated segments. */ | ||||
|   long shm_atts;	/* Number of attached segments, system | ||||
| 			   wide. */ | ||||
| }; | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| void *shmat (int shmid, const void *shmaddr, int shmflg); | ||||
| int   shmctl (int shmid, int cmd, struct shmid_ds *buf); | ||||
| @@ -91,4 +103,4 @@ int   shmget (key_t key, size_t size, int shmflg); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _SYS_SHM_H */ | ||||
| #endif /* _CYGWIN_SHM_H */ | ||||
|   | ||||
							
								
								
									
										94
									
								
								winsup/cygwin/include/cygwin/sysproto.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										94
									
								
								winsup/cygwin/include/cygwin/sysproto.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,94 @@ | ||||
| /* cygwin/sysproto.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* cygwin/sysproto.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _CYGWIN_SYSPROTO_H | ||||
| #define _CYGWIN_SYSPROTO_H | ||||
| #define _SYS_SYSPROTO_H_ /* Keep it, used by BSD files */ | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| extern "C" { | ||||
| #endif | ||||
|  | ||||
| #include <sys/types.h> | ||||
|  | ||||
| struct msgctl_args { | ||||
|   int     msqid; | ||||
|   int     cmd; | ||||
|   struct  msqid_ds *buf; | ||||
| }; | ||||
|  | ||||
| struct msgget_args { | ||||
|   key_t   key; | ||||
|   int     msgflg; | ||||
| }; | ||||
|  | ||||
| struct msgrcv_args { | ||||
|   int     msqid; | ||||
|   void    *msgp; | ||||
|   size_t  msgsz; | ||||
|   long    msgtyp; | ||||
|   int     msgflg; | ||||
| }; | ||||
|  | ||||
| struct msgsnd_args { | ||||
|   int     msqid; | ||||
|   const void *msgp; | ||||
|   size_t  msgsz; | ||||
|   int     msgflg; | ||||
| }; | ||||
|  | ||||
| struct semctl_args { | ||||
|   int     semid; | ||||
|   int     semnum; | ||||
|   int     cmd; | ||||
|   union   semun *arg; | ||||
| }; | ||||
|  | ||||
| struct semget_args { | ||||
|   key_t   key;  | ||||
|   int     nsems; | ||||
|   int     semflg; | ||||
| }; | ||||
|  | ||||
| struct semop_args { | ||||
|   int     semid; | ||||
|   struct  sembuf *sops; | ||||
|   size_t  nsops; | ||||
| };               | ||||
|  | ||||
| struct shmat_args { | ||||
|   int     shmid; | ||||
|   const void *shmaddr; | ||||
|   int     shmflg; | ||||
| }; | ||||
|  | ||||
| struct shmctl_args { | ||||
|   int     shmid; | ||||
|   int     cmd; | ||||
|   struct shmid_ds *buf; | ||||
| }; | ||||
|  | ||||
| struct shmdt_args { | ||||
|   const void *shmaddr; | ||||
| }; | ||||
|  | ||||
| struct shmget_args { | ||||
|   key_t   key; | ||||
|   size_t  size; | ||||
|   int     shmflg; | ||||
| }; | ||||
|  | ||||
| #ifdef __cplusplus | ||||
| } | ||||
| #endif | ||||
|  | ||||
| #endif /* _CYGWIN_SYSPROTO_H */ | ||||
| @@ -228,13 +228,14 @@ details. */ | ||||
|       101: Export err, errx, verr, verrx, warn, warnx, vwarn, vwarnx. | ||||
|       102: CW_GET_UID_FROM_SID and CW_GET_GID_FROM_SID addition to external.cc. | ||||
|       103: Export getprogname, setprogname. | ||||
|       104: Export msgctl, msgget, msgrcv, msgsnd, semctl, semget, semop. | ||||
|  | ||||
|      */ | ||||
|  | ||||
|      /* Note that we forgot to bump the api for ualarm, strtoll, strtoull */ | ||||
|  | ||||
| #define CYGWIN_VERSION_API_MAJOR 0 | ||||
| #define CYGWIN_VERSION_API_MINOR 103 | ||||
| #define CYGWIN_VERSION_API_MINOR 104 | ||||
|  | ||||
|      /* There is also a compatibity version number associated with the | ||||
| 	shared memory regions.  It is incremented when incompatible | ||||
|   | ||||
							
								
								
									
										18
									
								
								winsup/cygwin/include/sys/ipc.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								winsup/cygwin/include/sys/ipc.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* sys/ipc.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* sys/ipc.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _SYS_IPC_H | ||||
| #define _SYS_IPC_H | ||||
|  | ||||
| #include <cygwin/ipc.h> | ||||
|  | ||||
| #endif /* _SYS_IPC_H */ | ||||
							
								
								
									
										18
									
								
								winsup/cygwin/include/sys/msg.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								winsup/cygwin/include/sys/msg.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* sys/msg.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* sys/msg.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _SYS_MSG_H | ||||
| #define _SYS_MSG_H | ||||
|  | ||||
| #include <cygwin/msg.h> | ||||
|  | ||||
| #endif /* _SYS_MSG_H */ | ||||
							
								
								
									
										557
									
								
								winsup/cygwin/include/sys/queue.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										557
									
								
								winsup/cygwin/include/sys/queue.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,557 @@ | ||||
| /* | ||||
|  * Copyright (c) 1991, 1993 | ||||
|  *	The Regents of the University of California.  All rights reserved. | ||||
|  * | ||||
|  * Redistribution and use in source and binary forms, with or without | ||||
|  * modification, are permitted provided that the following conditions | ||||
|  * are met: | ||||
|  * 1. Redistributions of source code must retain the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer. | ||||
|  * 2. Redistributions in binary form must reproduce the above copyright | ||||
|  *    notice, this list of conditions and the following disclaimer in the | ||||
|  *    documentation and/or other materials provided with the distribution. | ||||
|  * 3. All advertising materials mentioning features or use of this software | ||||
|  *    must display the following acknowledgement: | ||||
|  *	This product includes software developed by the University of | ||||
|  *	California, Berkeley and its contributors. | ||||
|  * 4. Neither the name of the University nor the names of its contributors | ||||
|  *    may be used to endorse or promote products derived from this software | ||||
|  *    without specific prior written permission. | ||||
|  * | ||||
|  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND | ||||
|  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | ||||
|  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | ||||
|  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE | ||||
|  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||||
|  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||||
|  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||||
|  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | ||||
|  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | ||||
|  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | ||||
|  * SUCH DAMAGE. | ||||
|  * | ||||
|  *	@(#)queue.h	8.5 (Berkeley) 8/20/94 | ||||
|  * $FreeBSD: /repoman/r/ncvs/src/sys/sys/queue.h,v 1.56 2003/08/14 14:49:26 kan Exp $ | ||||
|  */ | ||||
|  | ||||
| #ifndef _SYS_QUEUE_H_ | ||||
| #define	_SYS_QUEUE_H_ | ||||
|  | ||||
| #include <sys/cdefs.h> | ||||
|  | ||||
| /* | ||||
|  * This file defines four types of data structures: singly-linked lists, | ||||
|  * singly-linked tail queues, lists and tail queues. | ||||
|  * | ||||
|  * A singly-linked list is headed by a single forward pointer. The elements | ||||
|  * are singly linked for minimum space and pointer manipulation overhead at | ||||
|  * the expense of O(n) removal for arbitrary elements. New elements can be | ||||
|  * added to the list after an existing element or at the head of the list. | ||||
|  * Elements being removed from the head of the list should use the explicit | ||||
|  * macro for this purpose for optimum efficiency. A singly-linked list may | ||||
|  * only be traversed in the forward direction.  Singly-linked lists are ideal | ||||
|  * for applications with large datasets and few or no removals or for | ||||
|  * implementing a LIFO queue. | ||||
|  * | ||||
|  * A singly-linked tail queue is headed by a pair of pointers, one to the | ||||
|  * head of the list and the other to the tail of the list. The elements are | ||||
|  * singly linked for minimum space and pointer manipulation overhead at the | ||||
|  * expense of O(n) removal for arbitrary elements. New elements can be added | ||||
|  * to the list after an existing element, at the head of the list, or at the | ||||
|  * end of the list. Elements being removed from the head of the tail queue | ||||
|  * should use the explicit macro for this purpose for optimum efficiency. | ||||
|  * A singly-linked tail queue may only be traversed in the forward direction. | ||||
|  * Singly-linked tail queues are ideal for applications with large datasets | ||||
|  * and few or no removals or for implementing a FIFO queue. | ||||
|  * | ||||
|  * A list is headed by a single forward pointer (or an array of forward | ||||
|  * pointers for a hash table header). The elements are doubly linked | ||||
|  * so that an arbitrary element can be removed without a need to | ||||
|  * traverse the list. New elements can be added to the list before | ||||
|  * or after an existing element or at the head of the list. A list | ||||
|  * may only be traversed in the forward direction. | ||||
|  * | ||||
|  * A tail queue is headed by a pair of pointers, one to the head of the | ||||
|  * list and the other to the tail of the list. The elements are doubly | ||||
|  * linked so that an arbitrary element can be removed without a need to | ||||
|  * traverse the list. New elements can be added to the list before or | ||||
|  * after an existing element, at the head of the list, or at the end of | ||||
|  * the list. A tail queue may be traversed in either direction. | ||||
|  * | ||||
|  * For details on the use of these macros, see the queue(3) manual page. | ||||
|  * | ||||
|  * | ||||
|  *				SLIST	LIST	STAILQ	TAILQ | ||||
|  * _HEAD			+	+	+	+ | ||||
|  * _HEAD_INITIALIZER		+	+	+	+ | ||||
|  * _ENTRY			+	+	+	+ | ||||
|  * _INIT			+	+	+	+ | ||||
|  * _EMPTY			+	+	+	+ | ||||
|  * _FIRST			+	+	+	+ | ||||
|  * _NEXT			+	+	+	+ | ||||
|  * _PREV			-	-	-	+ | ||||
|  * _LAST			-	-	+	+ | ||||
|  * _FOREACH			+	+	+	+ | ||||
|  * _FOREACH_SAFE		+	+	+	+ | ||||
|  * _FOREACH_REVERSE		-	-	-	+ | ||||
|  * _FOREACH_REVERSE_SAFE	-	-	-	+ | ||||
|  * _INSERT_HEAD			+	+	+	+ | ||||
|  * _INSERT_BEFORE		-	+	-	+ | ||||
|  * _INSERT_AFTER		+	+	+	+ | ||||
|  * _INSERT_TAIL			-	-	+	+ | ||||
|  * _CONCAT			-	-	+	+ | ||||
|  * _REMOVE_HEAD			+	-	+	- | ||||
|  * _REMOVE			+	+	+	+ | ||||
|  * | ||||
|  */ | ||||
| #define	QUEUE_MACRO_DEBUG 0 | ||||
| #if QUEUE_MACRO_DEBUG | ||||
| /* Store the last 2 places the queue element or head was altered */ | ||||
| struct qm_trace { | ||||
| 	char * lastfile; | ||||
| 	int lastline; | ||||
| 	char * prevfile; | ||||
| 	int prevline; | ||||
| }; | ||||
|  | ||||
| #define	TRACEBUF	struct qm_trace trace; | ||||
| #define	TRASHIT(x)	do {(x) = (void *)-1;} while (0) | ||||
|  | ||||
| #define	QMD_TRACE_HEAD(head) do {					\ | ||||
| 	(head)->trace.prevline = (head)->trace.lastline;		\ | ||||
| 	(head)->trace.prevfile = (head)->trace.lastfile;		\ | ||||
| 	(head)->trace.lastline = __LINE__;				\ | ||||
| 	(head)->trace.lastfile = __FILE__;				\ | ||||
| } while (0) | ||||
|  | ||||
| #define	QMD_TRACE_ELEM(elem) do {					\ | ||||
| 	(elem)->trace.prevline = (elem)->trace.lastline;		\ | ||||
| 	(elem)->trace.prevfile = (elem)->trace.lastfile;		\ | ||||
| 	(elem)->trace.lastline = __LINE__;				\ | ||||
| 	(elem)->trace.lastfile = __FILE__;				\ | ||||
| } while (0) | ||||
|  | ||||
| #else | ||||
| #define	QMD_TRACE_ELEM(elem) | ||||
| #define	QMD_TRACE_HEAD(head) | ||||
| #define	TRACEBUF | ||||
| #define	TRASHIT(x) | ||||
| #endif	/* QUEUE_MACRO_DEBUG */ | ||||
|  | ||||
| /* | ||||
|  * Singly-linked List declarations. | ||||
|  */ | ||||
| #define	SLIST_HEAD(name, type)						\ | ||||
| struct name {								\ | ||||
| 	struct type *slh_first;	/* first element */			\ | ||||
| } | ||||
|  | ||||
| #define	SLIST_HEAD_INITIALIZER(head)					\ | ||||
| 	{ NULL } | ||||
|  | ||||
| #define	SLIST_ENTRY(type)						\ | ||||
| struct {								\ | ||||
| 	struct type *sle_next;	/* next element */			\ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Singly-linked List functions. | ||||
|  */ | ||||
| #define	SLIST_EMPTY(head)	((head)->slh_first == NULL) | ||||
|  | ||||
| #define	SLIST_FIRST(head)	((head)->slh_first) | ||||
|  | ||||
| #define	SLIST_FOREACH(var, head, field)					\ | ||||
| 	for ((var) = SLIST_FIRST((head));				\ | ||||
| 	    (var);							\ | ||||
| 	    (var) = SLIST_NEXT((var), field)) | ||||
|  | ||||
| #define	SLIST_FOREACH_SAFE(var, head, field, tvar)			\ | ||||
| 	for ((var) = SLIST_FIRST((head));				\ | ||||
| 	    (var) && ((tvar) = SLIST_NEXT((var), field), 1);		\ | ||||
| 	    (var) = (tvar)) | ||||
|  | ||||
| #define	SLIST_FOREACH_PREVPTR(var, varp, head, field)			\ | ||||
| 	for ((varp) = &SLIST_FIRST((head));				\ | ||||
| 	    ((var) = *(varp)) != NULL;					\ | ||||
| 	    (varp) = &SLIST_NEXT((var), field)) | ||||
|  | ||||
| #define	SLIST_INIT(head) do {						\ | ||||
| 	SLIST_FIRST((head)) = NULL;					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	SLIST_INSERT_AFTER(slistelm, elm, field) do {			\ | ||||
| 	SLIST_NEXT((elm), field) = SLIST_NEXT((slistelm), field);	\ | ||||
| 	SLIST_NEXT((slistelm), field) = (elm);				\ | ||||
| } while (0) | ||||
|  | ||||
| #define	SLIST_INSERT_HEAD(head, elm, field) do {			\ | ||||
| 	SLIST_NEXT((elm), field) = SLIST_FIRST((head));			\ | ||||
| 	SLIST_FIRST((head)) = (elm);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	SLIST_NEXT(elm, field)	((elm)->field.sle_next) | ||||
|  | ||||
| #define	SLIST_REMOVE(head, elm, type, field) do {			\ | ||||
| 	if (SLIST_FIRST((head)) == (elm)) {				\ | ||||
| 		SLIST_REMOVE_HEAD((head), field);			\ | ||||
| 	}								\ | ||||
| 	else {								\ | ||||
| 		struct type *curelm = SLIST_FIRST((head));		\ | ||||
| 		while (SLIST_NEXT(curelm, field) != (elm))		\ | ||||
| 			curelm = SLIST_NEXT(curelm, field);		\ | ||||
| 		SLIST_NEXT(curelm, field) =				\ | ||||
| 		    SLIST_NEXT(SLIST_NEXT(curelm, field), field);	\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
|  | ||||
| #define	SLIST_REMOVE_HEAD(head, field) do {				\ | ||||
| 	SLIST_FIRST((head)) = SLIST_NEXT(SLIST_FIRST((head)), field);	\ | ||||
| } while (0) | ||||
|  | ||||
| /* | ||||
|  * Singly-linked Tail queue declarations. | ||||
|  */ | ||||
| #define	STAILQ_HEAD(name, type)						\ | ||||
| struct name {								\ | ||||
| 	struct type *stqh_first;/* first element */			\ | ||||
| 	struct type **stqh_last;/* addr of last next element */		\ | ||||
| } | ||||
|  | ||||
| #define	STAILQ_HEAD_INITIALIZER(head)					\ | ||||
| 	{ NULL, &(head).stqh_first } | ||||
|  | ||||
| #define	STAILQ_ENTRY(type)						\ | ||||
| struct {								\ | ||||
| 	struct type *stqe_next;	/* next element */			\ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Singly-linked Tail queue functions. | ||||
|  */ | ||||
| #define	STAILQ_CONCAT(head1, head2) do {				\ | ||||
| 	if (!STAILQ_EMPTY((head2))) {					\ | ||||
| 		*(head1)->stqh_last = (head2)->stqh_first;		\ | ||||
| 		(head1)->stqh_last = (head2)->stqh_last;		\ | ||||
| 		STAILQ_INIT((head2));					\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_EMPTY(head)	((head)->stqh_first == NULL) | ||||
|  | ||||
| #define	STAILQ_FIRST(head)	((head)->stqh_first) | ||||
|  | ||||
| #define	STAILQ_FOREACH(var, head, field)				\ | ||||
| 	for((var) = STAILQ_FIRST((head));				\ | ||||
| 	   (var);							\ | ||||
| 	   (var) = STAILQ_NEXT((var), field)) | ||||
|  | ||||
|  | ||||
| #define	STAILQ_FOREACH_SAFE(var, head, field, tvar)			\ | ||||
| 	for ((var) = STAILQ_FIRST((head));				\ | ||||
| 	    (var) && ((tvar) = STAILQ_NEXT((var), field), 1);		\ | ||||
| 	    (var) = (tvar)) | ||||
|  | ||||
| #define	STAILQ_INIT(head) do {						\ | ||||
| 	STAILQ_FIRST((head)) = NULL;					\ | ||||
| 	(head)->stqh_last = &STAILQ_FIRST((head));			\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_INSERT_AFTER(head, tqelm, elm, field) do {		\ | ||||
| 	if ((STAILQ_NEXT((elm), field) = STAILQ_NEXT((tqelm), field)) == NULL)\ | ||||
| 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\ | ||||
| 	STAILQ_NEXT((tqelm), field) = (elm);				\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_INSERT_HEAD(head, elm, field) do {			\ | ||||
| 	if ((STAILQ_NEXT((elm), field) = STAILQ_FIRST((head))) == NULL)	\ | ||||
| 		(head)->stqh_last = &STAILQ_NEXT((elm), field);		\ | ||||
| 	STAILQ_FIRST((head)) = (elm);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_INSERT_TAIL(head, elm, field) do {			\ | ||||
| 	STAILQ_NEXT((elm), field) = NULL;				\ | ||||
| 	*(head)->stqh_last = (elm);					\ | ||||
| 	(head)->stqh_last = &STAILQ_NEXT((elm), field);			\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_LAST(head, type, field)					\ | ||||
| 	(STAILQ_EMPTY((head)) ?						\ | ||||
| 		NULL :							\ | ||||
| 	        ((struct type *)					\ | ||||
| 		((char *)((head)->stqh_last) - __offsetof(struct type, field)))) | ||||
|  | ||||
| #define	STAILQ_NEXT(elm, field)	((elm)->field.stqe_next) | ||||
|  | ||||
| #define	STAILQ_REMOVE(head, elm, type, field) do {			\ | ||||
| 	if (STAILQ_FIRST((head)) == (elm)) {				\ | ||||
| 		STAILQ_REMOVE_HEAD((head), field);			\ | ||||
| 	}								\ | ||||
| 	else {								\ | ||||
| 		struct type *curelm = STAILQ_FIRST((head));		\ | ||||
| 		while (STAILQ_NEXT(curelm, field) != (elm))		\ | ||||
| 			curelm = STAILQ_NEXT(curelm, field);		\ | ||||
| 		if ((STAILQ_NEXT(curelm, field) =			\ | ||||
| 		     STAILQ_NEXT(STAILQ_NEXT(curelm, field), field)) == NULL)\ | ||||
| 			(head)->stqh_last = &STAILQ_NEXT((curelm), field);\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_REMOVE_HEAD(head, field) do {				\ | ||||
| 	if ((STAILQ_FIRST((head)) =					\ | ||||
| 	     STAILQ_NEXT(STAILQ_FIRST((head)), field)) == NULL)		\ | ||||
| 		(head)->stqh_last = &STAILQ_FIRST((head));		\ | ||||
| } while (0) | ||||
|  | ||||
| #define	STAILQ_REMOVE_HEAD_UNTIL(head, elm, field) do {			\ | ||||
| 	if ((STAILQ_FIRST((head)) = STAILQ_NEXT((elm), field)) == NULL)	\ | ||||
| 		(head)->stqh_last = &STAILQ_FIRST((head));		\ | ||||
| } while (0) | ||||
|  | ||||
| /* | ||||
|  * List declarations. | ||||
|  */ | ||||
| #define	LIST_HEAD(name, type)						\ | ||||
| struct name {								\ | ||||
| 	struct type *lh_first;	/* first element */			\ | ||||
| } | ||||
|  | ||||
| #define	LIST_HEAD_INITIALIZER(head)					\ | ||||
| 	{ NULL } | ||||
|  | ||||
| #define	LIST_ENTRY(type)						\ | ||||
| struct {								\ | ||||
| 	struct type *le_next;	/* next element */			\ | ||||
| 	struct type **le_prev;	/* address of previous next element */	\ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * List functions. | ||||
|  */ | ||||
|  | ||||
| #define	LIST_EMPTY(head)	((head)->lh_first == NULL) | ||||
|  | ||||
| #define	LIST_FIRST(head)	((head)->lh_first) | ||||
|  | ||||
| #define	LIST_FOREACH(var, head, field)					\ | ||||
| 	for ((var) = LIST_FIRST((head));				\ | ||||
| 	    (var);							\ | ||||
| 	    (var) = LIST_NEXT((var), field)) | ||||
|  | ||||
| #define	LIST_FOREACH_SAFE(var, head, field, tvar)			\ | ||||
| 	for ((var) = LIST_FIRST((head));				\ | ||||
| 	    (var) && ((tvar) = LIST_NEXT((var), field), 1);		\ | ||||
| 	    (var) = (tvar)) | ||||
|  | ||||
| #define	LIST_INIT(head) do {						\ | ||||
| 	LIST_FIRST((head)) = NULL;					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	LIST_INSERT_AFTER(listelm, elm, field) do {			\ | ||||
| 	if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\ | ||||
| 		LIST_NEXT((listelm), field)->field.le_prev =		\ | ||||
| 		    &LIST_NEXT((elm), field);				\ | ||||
| 	LIST_NEXT((listelm), field) = (elm);				\ | ||||
| 	(elm)->field.le_prev = &LIST_NEXT((listelm), field);		\ | ||||
| } while (0) | ||||
|  | ||||
| #define	LIST_INSERT_BEFORE(listelm, elm, field) do {			\ | ||||
| 	(elm)->field.le_prev = (listelm)->field.le_prev;		\ | ||||
| 	LIST_NEXT((elm), field) = (listelm);				\ | ||||
| 	*(listelm)->field.le_prev = (elm);				\ | ||||
| 	(listelm)->field.le_prev = &LIST_NEXT((elm), field);		\ | ||||
| } while (0) | ||||
|  | ||||
| #define	LIST_INSERT_HEAD(head, elm, field) do {				\ | ||||
| 	if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)	\ | ||||
| 		LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\ | ||||
| 	LIST_FIRST((head)) = (elm);					\ | ||||
| 	(elm)->field.le_prev = &LIST_FIRST((head));			\ | ||||
| } while (0) | ||||
|  | ||||
| #define	LIST_NEXT(elm, field)	((elm)->field.le_next) | ||||
|  | ||||
| #define	LIST_REMOVE(elm, field) do {					\ | ||||
| 	if (LIST_NEXT((elm), field) != NULL)				\ | ||||
| 		LIST_NEXT((elm), field)->field.le_prev = 		\ | ||||
| 		    (elm)->field.le_prev;				\ | ||||
| 	*(elm)->field.le_prev = LIST_NEXT((elm), field);		\ | ||||
| } while (0) | ||||
|  | ||||
| /* | ||||
|  * Tail queue declarations. | ||||
|  */ | ||||
| #define	TAILQ_HEAD(name, type)						\ | ||||
| struct name {								\ | ||||
| 	struct type *tqh_first;	/* first element */			\ | ||||
| 	struct type **tqh_last;	/* addr of last next element */		\ | ||||
| 	TRACEBUF							\ | ||||
| } | ||||
|  | ||||
| #define	TAILQ_HEAD_INITIALIZER(head)					\ | ||||
| 	{ NULL, &(head).tqh_first } | ||||
|  | ||||
| #define	TAILQ_ENTRY(type)						\ | ||||
| struct {								\ | ||||
| 	struct type *tqe_next;	/* next element */			\ | ||||
| 	struct type **tqe_prev;	/* address of previous next element */	\ | ||||
| 	TRACEBUF							\ | ||||
| } | ||||
|  | ||||
| /* | ||||
|  * Tail queue functions. | ||||
|  */ | ||||
| #define	TAILQ_CONCAT(head1, head2, field) do {				\ | ||||
| 	if (!TAILQ_EMPTY(head2)) {					\ | ||||
| 		*(head1)->tqh_last = (head2)->tqh_first;		\ | ||||
| 		(head2)->tqh_first->field.tqe_prev = (head1)->tqh_last;	\ | ||||
| 		(head1)->tqh_last = (head2)->tqh_last;			\ | ||||
| 		TAILQ_INIT((head2));					\ | ||||
| 		QMD_TRACE_HEAD(head);					\ | ||||
| 		QMD_TRACE_HEAD(head2);					\ | ||||
| 	}								\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_EMPTY(head)	((head)->tqh_first == NULL) | ||||
|  | ||||
| #define	TAILQ_FIRST(head)	((head)->tqh_first) | ||||
|  | ||||
| #define	TAILQ_FOREACH(var, head, field)					\ | ||||
| 	for ((var) = TAILQ_FIRST((head));				\ | ||||
| 	    (var);							\ | ||||
| 	    (var) = TAILQ_NEXT((var), field)) | ||||
|  | ||||
| #define	TAILQ_FOREACH_SAFE(var, head, field, tvar)			\ | ||||
| 	for ((var) = TAILQ_FIRST((head));				\ | ||||
| 	    (var) && ((tvar) = TAILQ_NEXT((var), field), 1);		\ | ||||
| 	    (var) = (tvar)) | ||||
|  | ||||
| #define	TAILQ_FOREACH_REVERSE(var, head, headname, field)		\ | ||||
| 	for ((var) = TAILQ_LAST((head), headname);			\ | ||||
| 	    (var);							\ | ||||
| 	    (var) = TAILQ_PREV((var), headname, field)) | ||||
|  | ||||
| #define	TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)	\ | ||||
| 	for ((var) = TAILQ_LAST((head), headname);			\ | ||||
| 	    (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);	\ | ||||
| 	    (var) = (tvar)) | ||||
|  | ||||
| #define	TAILQ_INIT(head) do {						\ | ||||
| 	TAILQ_FIRST((head)) = NULL;					\ | ||||
| 	(head)->tqh_last = &TAILQ_FIRST((head));			\ | ||||
| 	QMD_TRACE_HEAD(head);						\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_INSERT_AFTER(head, listelm, elm, field) do {		\ | ||||
| 	if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\ | ||||
| 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\ | ||||
| 		    &TAILQ_NEXT((elm), field);				\ | ||||
| 	else {								\ | ||||
| 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\ | ||||
| 		QMD_TRACE_HEAD(head);					\ | ||||
| 	}								\ | ||||
| 	TAILQ_NEXT((listelm), field) = (elm);				\ | ||||
| 	(elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);		\ | ||||
| 	QMD_TRACE_ELEM(&(elm)->field);					\ | ||||
| 	QMD_TRACE_ELEM(&listelm->field);				\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_INSERT_BEFORE(listelm, elm, field) do {			\ | ||||
| 	(elm)->field.tqe_prev = (listelm)->field.tqe_prev;		\ | ||||
| 	TAILQ_NEXT((elm), field) = (listelm);				\ | ||||
| 	*(listelm)->field.tqe_prev = (elm);				\ | ||||
| 	(listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);		\ | ||||
| 	QMD_TRACE_ELEM(&(elm)->field);					\ | ||||
| 	QMD_TRACE_ELEM(&listelm->field);				\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_INSERT_HEAD(head, elm, field) do {			\ | ||||
| 	if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)	\ | ||||
| 		TAILQ_FIRST((head))->field.tqe_prev =			\ | ||||
| 		    &TAILQ_NEXT((elm), field);				\ | ||||
| 	else								\ | ||||
| 		(head)->tqh_last = &TAILQ_NEXT((elm), field);		\ | ||||
| 	TAILQ_FIRST((head)) = (elm);					\ | ||||
| 	(elm)->field.tqe_prev = &TAILQ_FIRST((head));			\ | ||||
| 	QMD_TRACE_HEAD(head);						\ | ||||
| 	QMD_TRACE_ELEM(&(elm)->field);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_INSERT_TAIL(head, elm, field) do {			\ | ||||
| 	TAILQ_NEXT((elm), field) = NULL;				\ | ||||
| 	(elm)->field.tqe_prev = (head)->tqh_last;			\ | ||||
| 	*(head)->tqh_last = (elm);					\ | ||||
| 	(head)->tqh_last = &TAILQ_NEXT((elm), field);			\ | ||||
| 	QMD_TRACE_HEAD(head);						\ | ||||
| 	QMD_TRACE_ELEM(&(elm)->field);					\ | ||||
| } while (0) | ||||
|  | ||||
| #define	TAILQ_LAST(head, headname)					\ | ||||
| 	(*(((struct headname *)((head)->tqh_last))->tqh_last)) | ||||
|  | ||||
| #define	TAILQ_NEXT(elm, field) ((elm)->field.tqe_next) | ||||
|  | ||||
| #define	TAILQ_PREV(elm, headname, field)				\ | ||||
| 	(*(((struct headname *)((elm)->field.tqe_prev))->tqh_last)) | ||||
|  | ||||
| #define	TAILQ_REMOVE(head, elm, field) do {				\ | ||||
| 	if ((TAILQ_NEXT((elm), field)) != NULL)				\ | ||||
| 		TAILQ_NEXT((elm), field)->field.tqe_prev = 		\ | ||||
| 		    (elm)->field.tqe_prev;				\ | ||||
| 	else {								\ | ||||
| 		(head)->tqh_last = (elm)->field.tqe_prev;		\ | ||||
| 		QMD_TRACE_HEAD(head);					\ | ||||
| 	}								\ | ||||
| 	*(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);		\ | ||||
| 	TRASHIT((elm)->field.tqe_next);					\ | ||||
| 	TRASHIT((elm)->field.tqe_prev);					\ | ||||
| 	QMD_TRACE_ELEM(&(elm)->field);					\ | ||||
| } while (0) | ||||
|  | ||||
|  | ||||
| #ifdef _KERNEL | ||||
|  | ||||
| /* | ||||
|  * XXX insque() and remque() are an old way of handling certain queues. | ||||
|  * They bogusly assumes that all queue heads look alike. | ||||
|  */ | ||||
|  | ||||
| struct quehead { | ||||
| 	struct quehead *qh_link; | ||||
| 	struct quehead *qh_rlink; | ||||
| }; | ||||
|  | ||||
| #ifdef	__GNUC__ | ||||
|  | ||||
| static __inline void | ||||
| insque(void *a, void *b) | ||||
| { | ||||
| 	struct quehead *element = (struct quehead *)a, | ||||
| 		 *head = (struct quehead *)b; | ||||
|  | ||||
| 	element->qh_link = head->qh_link; | ||||
| 	element->qh_rlink = head; | ||||
| 	head->qh_link = element; | ||||
| 	element->qh_link->qh_rlink = element; | ||||
| } | ||||
|  | ||||
| static __inline void | ||||
| remque(void *a) | ||||
| { | ||||
| 	struct quehead *element = (struct quehead *)a; | ||||
|  | ||||
| 	element->qh_link->qh_rlink = element->qh_rlink; | ||||
| 	element->qh_rlink->qh_link = element->qh_link; | ||||
| 	element->qh_rlink = 0; | ||||
| } | ||||
|  | ||||
| #else /* !__GNUC__ */ | ||||
|  | ||||
| void	insque(void *a, void *b); | ||||
| void	remque(void *a); | ||||
|  | ||||
| #endif /* __GNUC__ */ | ||||
|  | ||||
| #endif /* _KERNEL */ | ||||
|  | ||||
| #endif /* !_SYS_QUEUE_H_ */ | ||||
							
								
								
									
										18
									
								
								winsup/cygwin/include/sys/sem.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								winsup/cygwin/include/sys/sem.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* sys/sem.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* sys/sem.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _SYS_SEM_H | ||||
| #define _SYS_SEM_H | ||||
|  | ||||
| #include <cygwin/sem.h> | ||||
|  | ||||
| #endif /* _SYS_SEM_H */ | ||||
							
								
								
									
										18
									
								
								winsup/cygwin/include/sys/shm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								winsup/cygwin/include/sys/shm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* sys/shm.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* sys/shm.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _SYS_SHM_H | ||||
| #define _SYS_SHM_H | ||||
|  | ||||
| #include <cygwin/shm.h> | ||||
|  | ||||
| #endif /* _SYS_SHM_H */ | ||||
							
								
								
									
										18
									
								
								winsup/cygwin/include/sys/sysproto.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								winsup/cygwin/include/sys/sysproto.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| /* sys/sysproto.h | ||||
|  | ||||
|    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. */ | ||||
|  | ||||
| /* sys/sysproto.h header file for Cygwin.  */ | ||||
|  | ||||
| #ifndef _SYS_SYSPROTO_H | ||||
| #define _SYS_SYSPROTO_H | ||||
|  | ||||
| #include <cygwin/sysproto.h> | ||||
|  | ||||
| #endif /* _SYS_SYSPROTO_H */ | ||||
| @@ -1,8 +1,6 @@ | ||||
| /* msg.cc: Single unix specification IPC interface for Cygwin. | ||||
| /* msg.cc: XSI IPC interface for Cygwin. | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
|    Written by Conrad Scott <conrad.scott@dsl.pipex.com>. | ||||
|    Copyright 2003 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -11,37 +9,205 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <cygwin/msg.h> | ||||
|  | ||||
|  | ||||
| #include "cygerrno.h" | ||||
| #ifdef USE_SERVER | ||||
| #include <sys/types.h> | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "sigproc.h" | ||||
|  | ||||
| #include "cygserver_ipc.h" | ||||
| #include "cygserver_msg.h" | ||||
|  | ||||
| /* | ||||
|  * client_request_msg Constructors | ||||
|  */ | ||||
|  | ||||
| client_request_msg::client_request_msg (int msqid, | ||||
| 					int cmd, | ||||
| 					struct msqid_ds *buf) | ||||
|   : client_request (CYGSERVER_REQUEST_MSG, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.msgop = MSGOP_msgctl; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|    _parameters.in.ctlargs.msqid = msqid; | ||||
|    _parameters.in.ctlargs.cmd = cmd; | ||||
|    _parameters.in.ctlargs.buf = buf; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| client_request_msg::client_request_msg (key_t key, | ||||
| 					int msgflg) | ||||
|   : client_request (CYGSERVER_REQUEST_MSG, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.msgop = MSGOP_msgget; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|   _parameters.in.getargs.key = key; | ||||
|   _parameters.in.getargs.msgflg = msgflg; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| client_request_msg::client_request_msg (int msqid, | ||||
| 					void *msgp, | ||||
| 					size_t msgsz, | ||||
| 					long msgtyp, | ||||
| 					int msgflg) | ||||
|   : client_request (CYGSERVER_REQUEST_MSG, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.msgop = MSGOP_msgrcv; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|   _parameters.in.rcvargs.msqid = msqid; | ||||
|   _parameters.in.rcvargs.msgp = msgp; | ||||
|   _parameters.in.rcvargs.msgsz = msgsz; | ||||
|   _parameters.in.rcvargs.msgtyp = msgtyp; | ||||
|   _parameters.in.rcvargs.msgflg = msgflg; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| client_request_msg::client_request_msg (int msqid, | ||||
| 					const void *msgp, | ||||
| 					size_t msgsz, | ||||
| 					int msgflg) | ||||
|   : client_request (CYGSERVER_REQUEST_MSG, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.msgop = MSGOP_msgsnd; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|   _parameters.in.sndargs.msqid = msqid; | ||||
|   _parameters.in.sndargs.msgp = msgp; | ||||
|   _parameters.in.sndargs.msgsz = msgsz; | ||||
|   _parameters.in.sndargs.msgflg = msgflg; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
| #endif /* USE_SERVER */ | ||||
|  | ||||
| /* | ||||
|  * XSI message queue API.  These are exported by the DLL. | ||||
|  */ | ||||
|  | ||||
| extern "C" int | ||||
| msgctl (int msqid, int cmd, struct msqid_ds *buf) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("msgctl (msqid = %d, cmd = 0x%x, buf = %p)", | ||||
| 		  msqid, cmd, buf); | ||||
|   switch (cmd) | ||||
|     { | ||||
|       case IPC_STAT: | ||||
| 	if (__check_null_invalid_struct_errno (buf, sizeof *buf)) | ||||
| 	  return -1; | ||||
|         break; | ||||
|       case IPC_SET: | ||||
| 	if (__check_invalid_read_ptr_errno (buf, sizeof *buf)) | ||||
| 	  return -1; | ||||
|         break; | ||||
|       case IPC_RMID: | ||||
|         break; | ||||
|       case IPC_INFO: | ||||
| 	/* msqid == 0: Request for msginfo struct. */ | ||||
| 	if (!msqid | ||||
| 	    && __check_null_invalid_struct_errno (buf, sizeof (struct msginfo))) | ||||
| 	    return -1; | ||||
| 	/* Otherwise, request msqid entries from internal msqid_ds array. */ | ||||
|         if (msqid) | ||||
| 	  if (__check_null_invalid_struct_errno (buf, msqid * sizeof (struct msqid_ds))) | ||||
| 	    return -1; | ||||
|         break; | ||||
|       case MSG_INFO: | ||||
|         if (__check_null_invalid_struct_errno (buf, sizeof (struct msg_info))) | ||||
| 	  return -1; | ||||
|         break; | ||||
|       default: | ||||
|         syscall_printf ("-1 [%d] = msgctl ()", EINVAL); | ||||
| 	set_errno (EINVAL); | ||||
| 	return -1; | ||||
|     } | ||||
|   client_request_msg request (msqid, cmd, buf); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = msgctl ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| msgget (key_t key, int msgflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("msgget (key = %U, msgflg = 0x%x)", key, msgflg); | ||||
|   client_request_msg request (key, msgflg); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = msgget ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| extern "C" ssize_t | ||||
| msgrcv (int msqid, void *msgp, size_t msgsz, long msgtyp, int msgflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("msgrcv (msqid = %d, msgp = %p, msgsz = %d, " | ||||
|   		  "msgtyp = %d, msgflg = 0x%x)", | ||||
| 		  msqid, msgp, msgsz, msgtyp, msgflg); | ||||
|   if (__check_null_invalid_struct_errno (msgp, msgsz)) | ||||
|     return -1; | ||||
|   client_request_msg request (msqid, msgp, msgsz, msgtyp, msgflg); | ||||
|   if (request.make_request () == -1 || request.rcvval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = msgrcv ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.rcvval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("msgsnd (msqid = %d, msgp = %p, msgsz = %d, msgflg = 0x%x)", | ||||
| 		  msqid, msgp, msgsz, msgflg); | ||||
|   if (__check_invalid_read_ptr_errno (msgp, msgsz)) | ||||
|     return -1; | ||||
|   client_request_msg request (msqid, msgp, msgsz, msgflg); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = msgsnd ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|   | ||||
| @@ -1,53 +0,0 @@ | ||||
| /* safe_memory.h | ||||
|  | ||||
|    Copyright 2002 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. */ | ||||
|  | ||||
| #ifndef __SAFE_MEMORY_H__ | ||||
| #define __SAFE_MEMORY_H__ | ||||
|  | ||||
| /*****************************************************************************/ | ||||
|  | ||||
| /* Temporary hack to get around the thread-unsafe new/delete in cygwin | ||||
|  * gcc 2.95.3.  This should all be binned at the first opportunity, | ||||
|  * e.g. gcc 3.1 or sooner. | ||||
|  * | ||||
|  * The trick here is to do contruction via malloc(3) and then the | ||||
|  * placement new operator, and destruction via an explicit call to the | ||||
|  * destructor and then free(3). | ||||
|  */ | ||||
|  | ||||
| #include <stdlib.h> | ||||
|  | ||||
| inline void *operator new (size_t, void *__p) throw () { return __p; } | ||||
|  | ||||
| #define safe_new0(T) (new (malloc (sizeof (T))) T) | ||||
|  | ||||
| #ifdef NEW_MACRO_VARARGS | ||||
|  | ||||
| #define safe_new(T, ...)			\ | ||||
|   (new (malloc (sizeof (T))) T (__VA_ARGS__)) | ||||
|  | ||||
| #else /* !NEW_MACRO_VARARGS */ | ||||
|  | ||||
| #define safe_new(T, args...)			\ | ||||
|   (new (malloc (sizeof (T))) T (## args)) | ||||
|  | ||||
| #endif /* !NEW_MACRO_VARARGS */ | ||||
|  | ||||
| template <typename T> void | ||||
| safe_delete (T *const object) | ||||
| { | ||||
|   if (object) | ||||
|     { | ||||
|       object->~T (); | ||||
|       free (object); | ||||
|     } | ||||
| } | ||||
|  | ||||
| #endif /* __SAFE_MEMORY_H__ */ | ||||
| @@ -1,8 +1,6 @@ | ||||
| /* sem.cc: Single unix specification IPC interface for Cygwin. | ||||
| /* sem.cc: XSI IPC interface for Cygwin. | ||||
|  | ||||
|    Copyright 2002 Red Hat, Inc. | ||||
|  | ||||
|    Written by Conrad Scott <conrad.scott@dsl.pipex.com>. | ||||
|    Copyright 2003 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -11,30 +9,161 @@ Cygwin license.  Please consult the file "CYGWIN_LICENSE" for | ||||
| details. */ | ||||
|  | ||||
| #include "winsup.h" | ||||
|  | ||||
| #include <sys/types.h> | ||||
| #include <cygwin/sem.h> | ||||
|  | ||||
|  | ||||
| #include "cygerrno.h" | ||||
| #ifdef USE_SERVER | ||||
| #include <sys/types.h> | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
| #include <stdarg.h> | ||||
|  | ||||
| #include "sigproc.h" | ||||
|  | ||||
| #include "cygserver_ipc.h" | ||||
| #include "cygserver_sem.h" | ||||
|  | ||||
| /* | ||||
|  * client_request_sem Constructors | ||||
|  */ | ||||
|  | ||||
| client_request_sem::client_request_sem (int semid, | ||||
| 					int semnum, | ||||
| 					int cmd, | ||||
| 					union semun *arg) | ||||
|   : client_request (CYGSERVER_REQUEST_SEM, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.semop = SEMOP_semctl; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|    _parameters.in.ctlargs.semid = semid; | ||||
|    _parameters.in.ctlargs.semnum = semnum; | ||||
|    _parameters.in.ctlargs.cmd = cmd; | ||||
|    _parameters.in.ctlargs.arg = arg; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| client_request_sem::client_request_sem (key_t key, | ||||
| 					int nsems, | ||||
| 					int semflg) | ||||
|   : client_request (CYGSERVER_REQUEST_SEM, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.semop = SEMOP_semget; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|   _parameters.in.getargs.key = key; | ||||
|   _parameters.in.getargs.nsems = nsems; | ||||
|   _parameters.in.getargs.semflg = semflg; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| client_request_sem::client_request_sem (int semid, | ||||
| 					struct sembuf *sops, | ||||
| 					size_t nsops) | ||||
|   : client_request (CYGSERVER_REQUEST_SEM, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
|   _parameters.in.semop = SEMOP_semop; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|   _parameters.in.opargs.semid = semid; | ||||
|   _parameters.in.opargs.sops = sops; | ||||
|   _parameters.in.opargs.nsops = nsops; | ||||
|  | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
| #endif /* USE_SERVER */ | ||||
|  | ||||
| /* | ||||
|  * XSI semaphore API.  These are exported by the DLL. | ||||
|  */ | ||||
|  | ||||
| extern "C" int | ||||
| semctl (int semid, int semnum, int cmd, ...) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   union semun arg = {0}; | ||||
|   if (cmd == IPC_STAT || cmd == IPC_SET || cmd == IPC_INFO || cmd == SEM_INFO | ||||
|       || cmd == GETALL || cmd == SETALL || cmd == SETVAL) | ||||
|     { | ||||
|       va_list ap; | ||||
|       va_start (ap, cmd); | ||||
|       arg = va_arg (ap, union semun); | ||||
|       va_end (ap); | ||||
|     } | ||||
|   syscall_printf ("semctl (semid = %d, semnum = %d, cmd = %d, arg.val = 0x%x)", | ||||
| 		  semid, semnum, cmd, arg.val); | ||||
|   if ((cmd == IPC_STAT || cmd == IPC_SET) | ||||
|       && __check_null_invalid_struct_errno (arg.buf, sizeof (struct semid_ds))) | ||||
|     return -1; | ||||
|   if (cmd == IPC_INFO) | ||||
|     { | ||||
|       /* semid == 0: Request for seminfo struct. */ | ||||
|       if (!semid | ||||
| 	  && __check_null_invalid_struct_errno (arg.buf, sizeof (struct seminfo))) | ||||
| 	  return -1; | ||||
|       /* Otherwise, request semid entries from internal semid_ds array. */ | ||||
|       if (semid) | ||||
| 	if (__check_null_invalid_struct_errno (arg.buf, semid * sizeof (struct semid_ds))) | ||||
| 	  return -1; | ||||
|     } | ||||
|   if (cmd == SEM_INFO | ||||
|       && __check_null_invalid_struct_errno (arg.buf, sizeof (struct sem_info))) | ||||
|     return -1; | ||||
|   client_request_sem request (semid, semnum, cmd, &arg); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = semctl ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| semget (key_t key, int nsems, int semflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("semget (key = %U, nsems = %d, semflg = 0x%x)", | ||||
| 		  key, nsems, semflg); | ||||
|   client_request_sem request (key, nsems, semflg); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = semctl ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| extern "C" int | ||||
| semop (int semid, struct sembuf *sops, size_t nsops) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   syscall_printf ("semop (semid = %d, sops = %p, nsops = %d)", | ||||
| 		  semid, sops, nsops); | ||||
|   if (__check_null_invalid_struct_errno (sops, nsops * sizeof (struct sembuf))) | ||||
|     return -1; | ||||
|   client_request_sem request (semid, sops, nsops); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = semctl ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|   | ||||
| @@ -1,9 +1,6 @@ | ||||
| /* shm.cc: Single unix specification IPC interface for Cygwin. | ||||
| /* shm.cc: XSI IPC interface for Cygwin. | ||||
|  | ||||
|    Copyright 2002,2003 Red Hat, Inc. | ||||
|  | ||||
|    Written by Conrad Scott <conrad.scott@dsl.pipex.com>. | ||||
|    Based on code by Robert Collins <robert.collins@hotmail.com>. | ||||
|    Copyright 2003 Red Hat, Inc. | ||||
|  | ||||
| This file is part of Cygwin. | ||||
|  | ||||
| @@ -15,697 +12,349 @@ details. */ | ||||
| #include "cygerrno.h" | ||||
| #ifdef USE_SERVER | ||||
| #include <sys/types.h> | ||||
|  | ||||
| #include <assert.h> | ||||
| #include <sys/queue.h> | ||||
| #include <stdio.h> | ||||
| #include <unistd.h> | ||||
|  | ||||
| #include "safe_memory.h" | ||||
| #include "pinfo.h" | ||||
| #include "sigproc.h" | ||||
|  | ||||
| #include "cygserver_ipc.h" | ||||
| #include "cygserver_shm.h" | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * class client_shmmgr | ||||
|  * | ||||
|  * A singleton class. | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| /* | ||||
|  * client_request_shm Constructors | ||||
|  */ | ||||
|  | ||||
| #define shmmgr (client_shmmgr::instance ()) | ||||
|  | ||||
| class client_shmmgr | ||||
| client_request_shm::client_request_shm (int shmid, | ||||
| 					const void *shmaddr, | ||||
| 					int shmflg) | ||||
|   : client_request (CYGSERVER_REQUEST_SHM, &_parameters, sizeof (_parameters)) | ||||
| { | ||||
| private: | ||||
|   class segment_t | ||||
|   { | ||||
|   public: | ||||
|     const int shmid; | ||||
|     const void *const shmaddr; | ||||
|     const int shmflg; | ||||
|     HANDLE hFileMap;		// Updated by fixup_shms_after_fork (). | ||||
|   _parameters.in.shmop = SHMOP_shmat; | ||||
|   ipc_set_proc_info (_parameters.in.ipcblk); | ||||
|  | ||||
|     segment_t *next; | ||||
|   _parameters.in.atargs.shmid = shmid; | ||||
|   _parameters.in.atargs.shmaddr = shmaddr; | ||||
|   _parameters.in.atargs.shmflg = shmflg; | ||||
|  | ||||
|     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) | ||||
|     {} | ||||
|   }; | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| public: | ||||
|   static client_shmmgr & instance (); | ||||
| 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); | ||||
|  | ||||
|   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); | ||||
|    _parameters.in.ctlargs.shmid = shmid; | ||||
|    _parameters.in.ctlargs.cmd = cmd; | ||||
|    _parameters.in.ctlargs.buf = buf; | ||||
|  | ||||
|   int fixup_shms_after_fork (); | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
| private: | ||||
|   static NO_COPY client_shmmgr *_instance; | ||||
| 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); | ||||
|  | ||||
|   CRITICAL_SECTION _segments_lock; | ||||
|   static segment_t *_segments_head; // List of attached segs by shmaddr. | ||||
|   _parameters.in.dtargs.shmaddr = shmaddr; | ||||
|  | ||||
|   static long _shmat_cnt;	// No. of attached segs; for info. only. | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
|   client_shmmgr (); | ||||
|   ~client_shmmgr (); | ||||
| 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); | ||||
|  | ||||
|   // Undefined (as this class is a singleton): | ||||
|   client_shmmgr (const client_shmmgr &); | ||||
|   client_shmmgr & operator= (const client_shmmgr &); | ||||
|   _parameters.in.getargs.key = key; | ||||
|   _parameters.in.getargs.size = size; | ||||
|   _parameters.in.getargs.shmflg = shmflg; | ||||
|  | ||||
|   segment_t *find (const void *, segment_t **previous = NULL); | ||||
|   msglen (sizeof (_parameters.in)); | ||||
| } | ||||
|  | ||||
|   void *attach (int shmid, const void *, int shmflg, HANDLE & hFileMap); | ||||
| 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); | ||||
|  | ||||
|   segment_t *new_segment (int shmid, const void *, int shmflg, HANDLE); | ||||
|   _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; | ||||
| }; | ||||
|  | ||||
| /* 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; | ||||
| } | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * fixup_shms_after_fork () | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| 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; | ||||
|   vm_object_t hdl; | ||||
|   size_t size; | ||||
|   int access; | ||||
| }; | ||||
|  | ||||
| static SLIST_HEAD(, shm_attached_list) sph_list; | ||||
|  | ||||
| int __stdcall | ||||
| fixup_shms_after_fork () | ||||
| { | ||||
|   return shmmgr.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::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)); | ||||
|   client_request_shm request (&parent); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = shmctl ()", 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->hdl, sph_entry->access, | ||||
|       					0, 0, sph_entry->size, sph_entry->ptr); | ||||
|       if (ptr != sph_entry->ptr) | ||||
|         api_fatal ("MapViewOfFileEx (%p), %E.  Terminating.", sph_entry->ptr); | ||||
|     } | ||||
|   return 0; | ||||
| } | ||||
| #endif /* USE_SERVER */ | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * shmat () | ||||
|  *---------------------------------------------------------------------------*/ | ||||
| /* | ||||
|  * XSI shmaphore API.  These are exported by the DLL. | ||||
|  */ | ||||
|  | ||||
| extern "C" void * | ||||
| shmat (const int shmid, const void *const shmaddr, const int shmflg) | ||||
| shmat (int shmid, const void *shmaddr, int shmflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   return shmmgr.shmat (shmid, shmaddr, shmflg); | ||||
|   syscall_printf ("shmat (shmid = %d, shmaddr = %p, shmflg = 0x%x)", | ||||
| 		  shmid, shmaddr, shmflg); | ||||
|  | ||||
|   shm_shmid_list *ssh_entry; | ||||
|   SLIST_FOREACH (ssh_entry, &ssh_list, ssh_next) | ||||
|     { | ||||
|       if (ssh_entry->shmid == shmid) | ||||
| 	break; | ||||
|     } | ||||
|   if (!ssh_entry) | ||||
|     { | ||||
|       /* Invalid shmid */ | ||||
|       set_errno (EINVAL); | ||||
|       return NULL; | ||||
|     } | ||||
|   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); | ||||
| 	  return NULL; | ||||
| 	} | ||||
|     } | ||||
|   /* Try allocating memory before calling cygserver. */ | ||||
|   shm_attached_list *sph_entry = new (shm_attached_list); | ||||
|   if (!sph_entry) | ||||
|     { | ||||
|       set_errno (ENOMEM); | ||||
|       return NULL; | ||||
|     } | ||||
|   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; | ||||
|       return NULL; | ||||
|     } | ||||
|   /* 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] = shmctl ()", request.error_code ()); | ||||
|       UnmapViewOfFile (ptr); | ||||
|       delete sph_entry; | ||||
|       set_errno (request.error_code ()); | ||||
|       return NULL; | ||||
|     } | ||||
|   sph_entry->ptr = ptr; | ||||
|   sph_entry->hdl = ssh_entry->hdl; | ||||
|   sph_entry->size = ssh_entry->size; | ||||
|   sph_entry->access = access; | ||||
|   SLIST_INSERT_HEAD (&sph_list, sph_entry, sph_next); | ||||
|   return ptr; | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return (void *) -1; | ||||
|   return NULL; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * shmctl () | ||||
|  *---------------------------------------------------------------------------*/ | ||||
|  | ||||
| extern "C" int | ||||
| shmctl (const int shmid, const int cmd, struct shmid_ds *const buf) | ||||
| shmctl (int shmid, int cmd, struct shmid_ds *buf) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   return shmmgr.shmctl (shmid, cmd, buf); | ||||
|   syscall_printf ("shmctl (shmid = %d, cmd = %d, buf = 0x%x)", | ||||
| 		  shmid, cmd, buf); | ||||
|   switch (cmd) | ||||
|     { | ||||
|       case IPC_STAT: | ||||
|       case IPC_SET: | ||||
| 	if (__check_null_invalid_struct_errno (buf, sizeof (struct shmid_ds))) | ||||
| 	  return -1; | ||||
|         break; | ||||
|       case IPC_INFO: | ||||
| 	/* shmid == 0: Request for shminfo struct. */ | ||||
| 	if (!shmid | ||||
| 	    && __check_null_invalid_struct_errno (buf, sizeof (struct shminfo))) | ||||
| 	    return -1; | ||||
| 	/* Otherwise, request shmid entries from internal shmid_ds array. */ | ||||
| 	if (shmid) | ||||
| 	  if (__check_null_invalid_struct_errno (buf, shmid * sizeof (struct shmid_ds))) | ||||
| 	    return -1; | ||||
|         break; | ||||
|       case SHM_INFO: | ||||
|         if (__check_null_invalid_struct_errno (buf, sizeof (struct shm_info))) | ||||
| 	  return -1; | ||||
|         break; | ||||
|     } | ||||
|   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 ()); | ||||
|       return -1; | ||||
|     } | ||||
|   if (cmd == IPC_RMID) | ||||
|     { | ||||
|       /* The process must cleanup its own storage... */ | ||||
|       shm_shmid_list *ssh_entry, *ssh_next_entry; | ||||
|       SLIST_FOREACH_SAFE (ssh_entry, &ssh_list, ssh_next, ssh_next_entry) | ||||
|         { | ||||
| 	  if (ssh_entry->shmid == shmid) | ||||
| 	    { | ||||
| 	      SLIST_REMOVE (&ssh_list, ssh_entry, shm_shmid_list, ssh_next); | ||||
| 	      /* ...and close the handle. */ | ||||
| 	      CloseHandle (ssh_entry->hdl); | ||||
| 	      delete ssh_entry; | ||||
| 	      break; | ||||
| 	    } | ||||
| 	} | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * shmdt () | ||||
|  *---------------------------------------------------------------------------*/ | ||||
|  | ||||
| extern "C" int | ||||
| shmdt (const void *const shmaddr) | ||||
| shmdt (const void *shmaddr) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   return shmmgr.shmdt (shmaddr); | ||||
|   syscall_printf ("shmget (shmaddr = %p)", shmaddr); | ||||
|   client_request_shm request (shmaddr); | ||||
|   if (request.make_request () == -1 || request.retval () == -1) | ||||
|     { | ||||
|       syscall_printf ("-1 [%d] = shmctl ()", request.error_code ()); | ||||
|       set_errno (request.error_code ()); | ||||
|       return -1; | ||||
|     } | ||||
|   shm_attached_list *sph_entry, *sph_next_entry; | ||||
|   /* Remove map from list... */ | ||||
|   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); | ||||
| 	  /* ...and unmap view. */ | ||||
| 	  UnmapViewOfFile (sph_entry->ptr); | ||||
| 	  delete sph_entry; | ||||
| 	  break; | ||||
| 	} | ||||
|     } | ||||
|   return request.retval (); | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| /*---------------------------------------------------------------------------* | ||||
|  * shmget () | ||||
|  *---------------------------------------------------------------------------*/ | ||||
|  | ||||
| extern "C" int | ||||
| shmget (const key_t key, const size_t size, const int shmflg) | ||||
| shmget (key_t key, size_t size, int shmflg) | ||||
| { | ||||
| #ifdef USE_SERVER | ||||
|   sigframe thisframe (mainthread); | ||||
|   return shmmgr.shmget (key, size, shmflg); | ||||
|   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] = shmctl ()", request.error_code ()); | ||||
|       delete ssh_new_entry; | ||||
|       set_errno (request.error_code ()); | ||||
|       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_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; | ||||
| 	  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; | ||||
|   SLIST_INSERT_HEAD (&ssh_list, ssh_new_entry, ssh_next); | ||||
|   return shmid; | ||||
| #else | ||||
|   set_errno (ENOSYS); | ||||
|   return -1; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user