xref: /illumos-gate/usr/src/uts/common/sys/ipc_impl.h (revision a19609f8)
17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5824c205fSml93401  * Common Development and Distribution License (the "License").
6824c205fSml93401  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
22*a19609f8Sjv227347  * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate #ifndef	_IPC_IMPL_H
267c478bd9Sstevel@tonic-gate #define	_IPC_IMPL_H
277c478bd9Sstevel@tonic-gate 
287c478bd9Sstevel@tonic-gate #include <sys/types.h>
297c478bd9Sstevel@tonic-gate #include <sys/ipc.h>
307c478bd9Sstevel@tonic-gate #include <sys/mutex.h>
31824c205fSml93401 #include <sys/ipc_rctl.h>
327c478bd9Sstevel@tonic-gate #include <sys/project.h>
33824c205fSml93401 #include <sys/zone.h>
347c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h>
357c478bd9Sstevel@tonic-gate #include <sys/avl.h>
367c478bd9Sstevel@tonic-gate #include <sys/id_space.h>
377c478bd9Sstevel@tonic-gate #include <sys/cred.h>
387c478bd9Sstevel@tonic-gate #include <sys/list.h>
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
417c478bd9Sstevel@tonic-gate extern "C" {
427c478bd9Sstevel@tonic-gate #endif
437c478bd9Sstevel@tonic-gate 
447c478bd9Sstevel@tonic-gate typedef uint64_t ipc_time_t;
457c478bd9Sstevel@tonic-gate 
467c478bd9Sstevel@tonic-gate /* For xxxctl64 */
477c478bd9Sstevel@tonic-gate #define	IPC_SET64	13	/* set options */
487c478bd9Sstevel@tonic-gate #define	IPC_STAT64	14	/* get options */
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate /*
517c478bd9Sstevel@tonic-gate  * There are two versions of the userland ipc_perm structure:
527c478bd9Sstevel@tonic-gate  *   ipc_perm     - the version used by user applications and by the kernel
537c478bd9Sstevel@tonic-gate  *		    when the user and kernel data models match (in ipc.h)
547c478bd9Sstevel@tonic-gate  *   ipc_perm32   - the 64-bit kernel's view of a 32-bit struct ipc_perm
557c478bd9Sstevel@tonic-gate  */
567c478bd9Sstevel@tonic-gate #if	defined(_SYSCALL32)
577c478bd9Sstevel@tonic-gate struct ipc_perm32 {
587c478bd9Sstevel@tonic-gate 	uid32_t		uid;	/* owner's user id */
597c478bd9Sstevel@tonic-gate 	gid32_t		gid;	/* owner's group id */
607c478bd9Sstevel@tonic-gate 	uid32_t		cuid;	/* creator's user id */
617c478bd9Sstevel@tonic-gate 	gid32_t		cgid;	/* creator's group id */
627c478bd9Sstevel@tonic-gate 	mode32_t	mode;	/* access modes */
637c478bd9Sstevel@tonic-gate 	uint32_t	seq;	/* slot usage sequence number */
647c478bd9Sstevel@tonic-gate 	key32_t		key;	/* key */
657c478bd9Sstevel@tonic-gate 	int32_t		pad[4];	/* reserve area */
667c478bd9Sstevel@tonic-gate };
677c478bd9Sstevel@tonic-gate #endif	/* _SYSCALL32 */
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * This is the ipc_perm equivalent used in the xxxid_ds64 structures.
717c478bd9Sstevel@tonic-gate  * It, like the structures it is used in, is intended only for use in
727c478bd9Sstevel@tonic-gate  * communication between the kernel and user programs, and has the same
737c478bd9Sstevel@tonic-gate  * layout across all data models.
747c478bd9Sstevel@tonic-gate  *
757c478bd9Sstevel@tonic-gate  * The xxxid_ds64 structures rely on ipc_perm64 being a multiple of
767c478bd9Sstevel@tonic-gate  * 8 bytes so subsequent fields are 64-bit aligned on x86.
777c478bd9Sstevel@tonic-gate  */
787c478bd9Sstevel@tonic-gate typedef struct ipc_perm64 {
797c478bd9Sstevel@tonic-gate 	uid_t	ipcx_uid;	/* owner's user id */
807c478bd9Sstevel@tonic-gate 	gid_t	ipcx_gid;	/* owner's group id */
817c478bd9Sstevel@tonic-gate 	uid_t	ipcx_cuid;	/* creator's user id */
827c478bd9Sstevel@tonic-gate 	gid_t	ipcx_cgid;	/* creator's group id */
837c478bd9Sstevel@tonic-gate 	mode_t	ipcx_mode;	/* access modes */
847c478bd9Sstevel@tonic-gate 	key_t	ipcx_key;	/* key */
857c478bd9Sstevel@tonic-gate 	projid_t ipcx_projid;	/* allocating project id */
867c478bd9Sstevel@tonic-gate 	zoneid_t ipcx_zoneid;	/* creator's zone id */
877c478bd9Sstevel@tonic-gate } ipc_perm64_t;
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate /*
907c478bd9Sstevel@tonic-gate  * These are versions of xxxid_ds which are intended only for use in
917c478bd9Sstevel@tonic-gate  * communication between the kernel and user programs, and therefore
927c478bd9Sstevel@tonic-gate  * have the same layout across all data models.  Omitted are all
937c478bd9Sstevel@tonic-gate  * implementation-specific fields which would be of no use to user
947c478bd9Sstevel@tonic-gate  * programs.
957c478bd9Sstevel@tonic-gate  */
967c478bd9Sstevel@tonic-gate struct shmid_ds64 {
977c478bd9Sstevel@tonic-gate 	ipc_perm64_t	shmx_perm;	/* operation permission struct */
987c478bd9Sstevel@tonic-gate 	pid_t		shmx_lpid;	/* pid of last shmop */
997c478bd9Sstevel@tonic-gate 	pid_t		shmx_cpid;	/* pid of creator */
1007c478bd9Sstevel@tonic-gate 	uint64_t	shmx_segsz;	/* size of segment in bytes */
1017c478bd9Sstevel@tonic-gate 	uint64_t	shmx_nattch;	/* # of attaches */
1027c478bd9Sstevel@tonic-gate 	uint64_t	shmx_cnattch;	/* # of ISM attaches */
1037c478bd9Sstevel@tonic-gate 	uint64_t	shmx_lkcnt;	/* lock count ??? */
1047c478bd9Sstevel@tonic-gate 	ipc_time_t	shmx_atime;	/* last shmat time */
1057c478bd9Sstevel@tonic-gate 	ipc_time_t	shmx_dtime;	/* last shmdt time */
1067c478bd9Sstevel@tonic-gate 	ipc_time_t	shmx_ctime;	/* last change time */
1077c478bd9Sstevel@tonic-gate };
1087c478bd9Sstevel@tonic-gate 
1097c478bd9Sstevel@tonic-gate struct semid_ds64 {
1107c478bd9Sstevel@tonic-gate 	ipc_perm64_t	semx_perm;	/* operation permission struct */
1117c478bd9Sstevel@tonic-gate 	ushort_t	semx_nsems;	/* # of semaphores in set */
1127c478bd9Sstevel@tonic-gate 	ushort_t	_semx_pad[3];	/* pad to 8-byte multiple */
1137c478bd9Sstevel@tonic-gate 	ipc_time_t	semx_otime;	/* last semop time */
1147c478bd9Sstevel@tonic-gate 	ipc_time_t	semx_ctime;	/* last change time */
1157c478bd9Sstevel@tonic-gate };
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate struct msqid_ds64 {
1187c478bd9Sstevel@tonic-gate 	ipc_perm64_t	msgx_perm;	/* operation permission struct */
1197c478bd9Sstevel@tonic-gate 	uint64_t	msgx_cbytes;	/* current # bytes on q */
1207c478bd9Sstevel@tonic-gate 	uint64_t	msgx_qnum;	/* # of messages on q */
1217c478bd9Sstevel@tonic-gate 	uint64_t	msgx_qbytes;	/* max # of bytes on q */
1227c478bd9Sstevel@tonic-gate 	pid_t		msgx_lspid;	/* pid of last msgsnd */
1237c478bd9Sstevel@tonic-gate 	pid_t		msgx_lrpid;	/* pid of last msgrcv */
1247c478bd9Sstevel@tonic-gate 	ipc_time_t	msgx_stime;	/* last msgsnd time */
1257c478bd9Sstevel@tonic-gate 	ipc_time_t	msgx_rtime;	/* last msgrcv time */
1267c478bd9Sstevel@tonic-gate 	ipc_time_t	msgx_ctime;	/* last change time */
1277c478bd9Sstevel@tonic-gate };
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate #ifdef _KERNEL
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate /*
1327c478bd9Sstevel@tonic-gate  * Implementation macros
1337c478bd9Sstevel@tonic-gate  */
1347c478bd9Sstevel@tonic-gate #define	IPC_FREE(x)	(((x)->ipc_mode & IPC_ALLOC) == 0)
1357c478bd9Sstevel@tonic-gate 
1367c478bd9Sstevel@tonic-gate #define	IPC_SEQ_BITS	7
1377c478bd9Sstevel@tonic-gate #define	IPC_SEQ_MASK	((1 << IPC_SEQ_BITS) - 1)
1387c478bd9Sstevel@tonic-gate #define	IPC_SEQ_SHIFT	(31 - IPC_SEQ_BITS)
1397c478bd9Sstevel@tonic-gate #define	IPC_INDEX_MASK	((1 << IPC_SEQ_SHIFT) - 1)
1407c478bd9Sstevel@tonic-gate #define	IPC_SEQ(x)	((unsigned int)(x) >> IPC_SEQ_SHIFT)
1417c478bd9Sstevel@tonic-gate #define	IPC_INDEX(x)	((unsigned int)(x) & IPC_INDEX_MASK)
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate #define	IPC_IDS_MIN	(PAGESIZE / 64)		/* starting # of entries */
1447c478bd9Sstevel@tonic-gate #define	IPC_IDS_MAX	(1 << IPC_SEQ_SHIFT)	/* maximum # of entries */
1457c478bd9Sstevel@tonic-gate #define	IPC_ID_INVAL	UINT_MAX
1467c478bd9Sstevel@tonic-gate 
147824c205fSml93401 #define	IPC_PROJ_USAGE(p, s) \
148824c205fSml93401 	(*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data.kpd_ipc) + \
149824c205fSml93401 	s->ipcs_rctlofs))
150824c205fSml93401 #define	IPC_ZONE_USAGE(p, s) \
151*a19609f8Sjv227347 	(*(rctl_qty_t *)(((char *)&p->ipc_zone_ref.zref_zone->zone_ipc) + \
152824c205fSml93401 	s->ipcs_rctlofs))
1537c478bd9Sstevel@tonic-gate #define	IPC_LOCKED(s, o) \
1547c478bd9Sstevel@tonic-gate 	MUTEX_HELD(&s->ipcs_table[IPC_INDEX(o->ipc_id)].ipct_lock)
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate /*
1577c478bd9Sstevel@tonic-gate  * The kernel's ipc_perm structure.
1587c478bd9Sstevel@tonic-gate  */
1597c478bd9Sstevel@tonic-gate typedef struct kipc_perm {
1607c478bd9Sstevel@tonic-gate 	avl_node_t ipc_avl;	/* avl node if key is non-private */
1617c478bd9Sstevel@tonic-gate 	list_node_t ipc_list;	/* list node in list of all ids */
1627c478bd9Sstevel@tonic-gate 	uint_t	ipc_ref;	/* reference count		*/
1637c478bd9Sstevel@tonic-gate 	uid_t	ipc_uid;	/* owner's user id		*/
1647c478bd9Sstevel@tonic-gate 	gid_t	ipc_gid;	/* owner's group id		*/
1657c478bd9Sstevel@tonic-gate 	uid_t	ipc_cuid;	/* creator's user id		*/
1667c478bd9Sstevel@tonic-gate 	gid_t	ipc_cgid;	/* creator's group id		*/
1677c478bd9Sstevel@tonic-gate 	mode_t	ipc_mode;	/* access modes			*/
1687c478bd9Sstevel@tonic-gate 	key_t	ipc_key;	/* key				*/
1697c478bd9Sstevel@tonic-gate 	kproject_t *ipc_proj;	/* creator's project		*/
1707c478bd9Sstevel@tonic-gate 	uint_t	ipc_id;		/* id				*/
1717c478bd9Sstevel@tonic-gate 	zoneid_t ipc_zoneid;	/* creator's zone id		*/
172*a19609f8Sjv227347 	zone_ref_t ipc_zone_ref; /* reference to creator's zone */
1737c478bd9Sstevel@tonic-gate } kipc_perm_t;
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate typedef struct ipc_slot {
1767c478bd9Sstevel@tonic-gate 	kmutex_t	ipct_lock;	/* bucket lock		*/
1777c478bd9Sstevel@tonic-gate 	kipc_perm_t	*ipct_data;	/* data			*/
1787c478bd9Sstevel@tonic-gate 	uint_t		ipct_seq;	/* sequence number	*/
1797c478bd9Sstevel@tonic-gate 	struct ipc_slot	*ipct_chain;	/* for stale arrays	*/
1807c478bd9Sstevel@tonic-gate 	char		ipct_pad[64 - sizeof (kmutex_t) - 3 * sizeof (void *)];
1817c478bd9Sstevel@tonic-gate } ipc_slot_t;
1827c478bd9Sstevel@tonic-gate 
1837c478bd9Sstevel@tonic-gate typedef void(ipc_func_t)(kipc_perm_t *);
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate typedef struct ipc_service {
1867c478bd9Sstevel@tonic-gate 	kmutex_t	ipcs_lock;	/* lock for (de)allocation, keys */
1877c478bd9Sstevel@tonic-gate 	avl_tree_t	ipcs_keys;	/* objects sorted by key	*/
1887c478bd9Sstevel@tonic-gate 	ipc_slot_t	*ipcs_table;	/* table of objects		*/
1897c478bd9Sstevel@tonic-gate 	uint_t		ipcs_tabsz;	/* size of table		*/
1907c478bd9Sstevel@tonic-gate 	uint_t		ipcs_count;	/* # of objects allocated	*/
191824c205fSml93401 	rctl_hndl_t	ipcs_proj_rctl;	/* id limiting rctl handle	*/
192824c205fSml93401 	rctl_hndl_t	ipcs_zone_rctl;	/* id limiting rctl handle	*/
1937c478bd9Sstevel@tonic-gate 	size_t		ipcs_rctlofs;	/* offset in kproject_data_t	*/
1947c478bd9Sstevel@tonic-gate 	id_space_t	*ipcs_ids;	/* id space for objects		*/
1957c478bd9Sstevel@tonic-gate 	size_t		ipcs_ssize;	/* object size (for allocation)	*/
1967c478bd9Sstevel@tonic-gate 	ipc_func_t	*ipcs_dtor;	/* object destructor		*/
1977c478bd9Sstevel@tonic-gate 	ipc_func_t	*ipcs_rmid;	/* object removal		*/
1987c478bd9Sstevel@tonic-gate 	list_t		ipcs_usedids;	/* list of allocated ids	*/
1997c478bd9Sstevel@tonic-gate 	int		ipcs_atype;	/* audit type (see c2/audit.h)	*/
2007c478bd9Sstevel@tonic-gate } ipc_service_t;
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate int ipcperm_access(kipc_perm_t *, int, cred_t *);
2037c478bd9Sstevel@tonic-gate int ipcperm_set(ipc_service_t *, struct cred *, kipc_perm_t *,
2047c478bd9Sstevel@tonic-gate     struct ipc_perm *, model_t);
2057c478bd9Sstevel@tonic-gate void ipcperm_stat(struct ipc_perm *, kipc_perm_t *, model_t);
2067c478bd9Sstevel@tonic-gate int ipcperm_set64(ipc_service_t *, struct cred *, kipc_perm_t *,
2077c478bd9Sstevel@tonic-gate     ipc_perm64_t *);
2087c478bd9Sstevel@tonic-gate void ipcperm_stat64(ipc_perm64_t *, kipc_perm_t *);
2097c478bd9Sstevel@tonic-gate 
210824c205fSml93401 ipc_service_t *ipcs_create(const char *, rctl_hndl_t, rctl_hndl_t, size_t,
211824c205fSml93401     ipc_func_t *, ipc_func_t *, int, size_t);
2127c478bd9Sstevel@tonic-gate void ipcs_destroy(ipc_service_t *);
2137c478bd9Sstevel@tonic-gate void ipcs_lock(ipc_service_t *);
2147c478bd9Sstevel@tonic-gate void ipcs_unlock(ipc_service_t *);
2157c478bd9Sstevel@tonic-gate 
2167c478bd9Sstevel@tonic-gate kmutex_t *ipc_lock(ipc_service_t *, int);
2177c478bd9Sstevel@tonic-gate kmutex_t *ipc_relock(ipc_service_t *, int, kmutex_t *);
2187c478bd9Sstevel@tonic-gate kmutex_t *ipc_lookup(ipc_service_t *, int, kipc_perm_t **);
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate void ipc_hold(ipc_service_t *, kipc_perm_t *);
2217c478bd9Sstevel@tonic-gate void ipc_rele(ipc_service_t *, kipc_perm_t *);
2227c478bd9Sstevel@tonic-gate void ipc_rele_locked(ipc_service_t *, kipc_perm_t *);
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate int ipc_get(ipc_service_t *, key_t, int, kipc_perm_t **, kmutex_t **);
2257c478bd9Sstevel@tonic-gate int ipc_commit_begin(ipc_service_t *, key_t, int, kipc_perm_t *);
2267c478bd9Sstevel@tonic-gate kmutex_t *ipc_commit_end(ipc_service_t *, kipc_perm_t *);
2277c478bd9Sstevel@tonic-gate void ipc_cleanup(ipc_service_t *, kipc_perm_t *);
2287c478bd9Sstevel@tonic-gate 
2297c478bd9Sstevel@tonic-gate int ipc_rmid(ipc_service_t *, int, cred_t *);
2307c478bd9Sstevel@tonic-gate int ipc_ids(ipc_service_t *, int *, uint_t, uint_t *);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate void ipc_remove_zone(ipc_service_t *, zoneid_t);
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate #else	/* _KERNEL */
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate int msgctl64(int, int, struct msqid_ds64 *);
2377c478bd9Sstevel@tonic-gate int semctl64(int, int, int, ...);
2387c478bd9Sstevel@tonic-gate int shmctl64(int, int, struct shmid_ds64 *);
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate #endif	/* _KERNEL */
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 
2437c478bd9Sstevel@tonic-gate #ifdef	__cplusplus
2447c478bd9Sstevel@tonic-gate }
2457c478bd9Sstevel@tonic-gate #endif
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate #endif	/* _IPC_IMPL_H */
248