Merge commit '7e3488dc6cdcb0c04e1ce167a1a3bfef83b5f2e0'
[unleashed.git] / include / sys / ipc_impl.h
blob0569c3e967198bbc68c9485c0614217d6f6f6ce7
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
25 #ifndef _IPC_IMPL_H
26 #define _IPC_IMPL_H
28 #include <sys/types.h>
29 #include <sys/ipc.h>
30 #include <sys/mutex.h>
31 #include <sys/ipc_rctl.h>
32 #include <sys/project.h>
33 #include <sys/zone.h>
34 #include <sys/sysmacros.h>
35 #include <sys/avl.h>
36 #include <sys/id_space.h>
37 #include <sys/cred.h>
38 #include <sys/list.h>
40 #ifdef __cplusplus
41 extern "C" {
42 #endif
44 typedef uint64_t ipc_time_t;
46 /* For xxxctl64 */
47 #define IPC_SET64 13 /* set options */
48 #define IPC_STAT64 14 /* get options */
51 * There are two versions of the userland ipc_perm structure:
52 * ipc_perm - the version used by user applications and by the kernel
53 * when the user and kernel data models match (in ipc.h)
54 * ipc_perm32 - the 64-bit kernel's view of a 32-bit struct ipc_perm
56 #if defined(_SYSCALL32)
57 struct ipc_perm32 {
58 uid32_t uid; /* owner's user id */
59 gid32_t gid; /* owner's group id */
60 uid32_t cuid; /* creator's user id */
61 gid32_t cgid; /* creator's group id */
62 mode32_t mode; /* access modes */
63 uint32_t seq; /* slot usage sequence number */
64 key32_t key; /* key */
65 int32_t pad[4]; /* reserve area */
67 #endif /* _SYSCALL32 */
70 * This is the ipc_perm equivalent used in the xxxid_ds64 structures.
71 * It, like the structures it is used in, is intended only for use in
72 * communication between the kernel and user programs, and has the same
73 * layout across all data models.
75 * The xxxid_ds64 structures rely on ipc_perm64 being a multiple of
76 * 8 bytes so subsequent fields are 64-bit aligned on x86.
78 typedef struct ipc_perm64 {
79 uid_t ipcx_uid; /* owner's user id */
80 gid_t ipcx_gid; /* owner's group id */
81 uid_t ipcx_cuid; /* creator's user id */
82 gid_t ipcx_cgid; /* creator's group id */
83 mode_t ipcx_mode; /* access modes */
84 key_t ipcx_key; /* key */
85 projid_t ipcx_projid; /* allocating project id */
86 zoneid_t ipcx_zoneid; /* creator's zone id */
87 } ipc_perm64_t;
90 * These are versions of xxxid_ds which are intended only for use in
91 * communication between the kernel and user programs, and therefore
92 * have the same layout across all data models. Omitted are all
93 * implementation-specific fields which would be of no use to user
94 * programs.
96 struct shmid_ds64 {
97 ipc_perm64_t shmx_perm; /* operation permission struct */
98 pid_t shmx_lpid; /* pid of last shmop */
99 pid_t shmx_cpid; /* pid of creator */
100 uint64_t shmx_segsz; /* size of segment in bytes */
101 uint64_t shmx_nattch; /* # of attaches */
102 uint64_t shmx_cnattch; /* # of ISM attaches */
103 uint64_t shmx_lkcnt; /* lock count ??? */
104 ipc_time_t shmx_atime; /* last shmat time */
105 ipc_time_t shmx_dtime; /* last shmdt time */
106 ipc_time_t shmx_ctime; /* last change time */
109 struct semid_ds64 {
110 ipc_perm64_t semx_perm; /* operation permission struct */
111 ushort_t semx_nsems; /* # of semaphores in set */
112 ushort_t _semx_pad[3]; /* pad to 8-byte multiple */
113 ipc_time_t semx_otime; /* last semop time */
114 ipc_time_t semx_ctime; /* last change time */
117 struct msqid_ds64 {
118 ipc_perm64_t msgx_perm; /* operation permission struct */
119 uint64_t msgx_cbytes; /* current # bytes on q */
120 uint64_t msgx_qnum; /* # of messages on q */
121 uint64_t msgx_qbytes; /* max # of bytes on q */
122 pid_t msgx_lspid; /* pid of last msgsnd */
123 pid_t msgx_lrpid; /* pid of last msgrcv */
124 ipc_time_t msgx_stime; /* last msgsnd time */
125 ipc_time_t msgx_rtime; /* last msgrcv time */
126 ipc_time_t msgx_ctime; /* last change time */
129 #ifdef _KERNEL
132 * Implementation macros
134 #define IPC_FREE(x) (((x)->ipc_mode & IPC_ALLOC) == 0)
136 #define IPC_SEQ_BITS 7
137 #define IPC_SEQ_MASK ((1 << IPC_SEQ_BITS) - 1)
138 #define IPC_SEQ_SHIFT (31 - IPC_SEQ_BITS)
139 #define IPC_INDEX_MASK ((1 << IPC_SEQ_SHIFT) - 1)
140 #define IPC_SEQ(x) ((unsigned int)(x) >> IPC_SEQ_SHIFT)
141 #define IPC_INDEX(x) ((unsigned int)(x) & IPC_INDEX_MASK)
143 #define IPC_IDS_MIN (PAGESIZE / 64) /* starting # of entries */
144 #define IPC_IDS_MAX (1 << IPC_SEQ_SHIFT) /* maximum # of entries */
145 #define IPC_ID_INVAL UINT_MAX
147 #define IPC_PROJ_USAGE(p, s) \
148 (*(rctl_qty_t *)(((char *)&p->ipc_proj->kpj_data.kpd_ipc) + \
149 s->ipcs_rctlofs))
150 #define IPC_ZONE_USAGE(p, s) \
151 (*(rctl_qty_t *)(((char *)&p->ipc_zone_ref.zref_zone->zone_ipc) + \
152 s->ipcs_rctlofs))
153 #define IPC_LOCKED(s, o) \
154 MUTEX_HELD(&s->ipcs_table[IPC_INDEX(o->ipc_id)].ipct_lock)
157 * The kernel's ipc_perm structure.
159 typedef struct kipc_perm {
160 avl_node_t ipc_avl; /* avl node if key is non-private */
161 list_node_t ipc_list; /* list node in list of all ids */
162 uint_t ipc_ref; /* reference count */
163 uid_t ipc_uid; /* owner's user id */
164 gid_t ipc_gid; /* owner's group id */
165 uid_t ipc_cuid; /* creator's user id */
166 gid_t ipc_cgid; /* creator's group id */
167 mode_t ipc_mode; /* access modes */
168 key_t ipc_key; /* key */
169 kproject_t *ipc_proj; /* creator's project */
170 uint_t ipc_id; /* id */
171 zoneid_t ipc_zoneid; /* creator's zone id */
172 zone_ref_t ipc_zone_ref; /* reference to creator's zone */
173 } kipc_perm_t;
175 typedef struct ipc_slot {
176 kmutex_t ipct_lock; /* bucket lock */
177 kipc_perm_t *ipct_data; /* data */
178 uint_t ipct_seq; /* sequence number */
179 struct ipc_slot *ipct_chain; /* for stale arrays */
180 char ipct_pad[64 - sizeof (kmutex_t) - 3 * sizeof (void *)];
181 } ipc_slot_t;
183 typedef void(ipc_func_t)(kipc_perm_t *);
185 typedef struct ipc_service {
186 kmutex_t ipcs_lock; /* lock for (de)allocation, keys */
187 avl_tree_t ipcs_keys; /* objects sorted by key */
188 ipc_slot_t *ipcs_table; /* table of objects */
189 uint_t ipcs_tabsz; /* size of table */
190 uint_t ipcs_count; /* # of objects allocated */
191 rctl_hndl_t ipcs_proj_rctl; /* id limiting rctl handle */
192 rctl_hndl_t ipcs_zone_rctl; /* id limiting rctl handle */
193 size_t ipcs_rctlofs; /* offset in kproject_data_t */
194 id_space_t *ipcs_ids; /* id space for objects */
195 size_t ipcs_ssize; /* object size (for allocation) */
196 ipc_func_t *ipcs_dtor; /* object destructor */
197 ipc_func_t *ipcs_rmid; /* object removal */
198 list_t ipcs_usedids; /* list of allocated ids */
199 int ipcs_atype; /* audit type (see c2/audit.h) */
200 } ipc_service_t;
202 int ipcperm_access(kipc_perm_t *, int, cred_t *);
203 int ipcperm_set(ipc_service_t *, struct cred *, kipc_perm_t *,
204 struct ipc_perm *, model_t);
205 void ipcperm_stat(struct ipc_perm *, kipc_perm_t *, model_t);
206 int ipcperm_set64(ipc_service_t *, struct cred *, kipc_perm_t *,
207 ipc_perm64_t *);
208 void ipcperm_stat64(ipc_perm64_t *, kipc_perm_t *);
210 ipc_service_t *ipcs_create(const char *, rctl_hndl_t, rctl_hndl_t, size_t,
211 ipc_func_t *, ipc_func_t *, int, size_t);
212 void ipcs_destroy(ipc_service_t *);
213 void ipcs_lock(ipc_service_t *);
214 void ipcs_unlock(ipc_service_t *);
216 kmutex_t *ipc_lock(ipc_service_t *, int);
217 kmutex_t *ipc_relock(ipc_service_t *, int, kmutex_t *);
218 kmutex_t *ipc_lookup(ipc_service_t *, int, kipc_perm_t **);
220 void ipc_hold(ipc_service_t *, kipc_perm_t *);
221 void ipc_rele(ipc_service_t *, kipc_perm_t *);
222 void ipc_rele_locked(ipc_service_t *, kipc_perm_t *);
224 int ipc_get(ipc_service_t *, key_t, int, kipc_perm_t **, kmutex_t **);
225 int ipc_commit_begin(ipc_service_t *, key_t, int, kipc_perm_t *);
226 kmutex_t *ipc_commit_end(ipc_service_t *, kipc_perm_t *);
227 void ipc_cleanup(ipc_service_t *, kipc_perm_t *);
229 int ipc_rmid(ipc_service_t *, int, cred_t *);
230 int ipc_ids(ipc_service_t *, int *, uint_t, uint_t *);
232 void ipc_remove_zone(ipc_service_t *, zoneid_t);
234 #else /* _KERNEL */
236 int msgctl64(int, int, struct msqid_ds64 *);
237 int semctl64(int, int, int, ...);
238 int shmctl64(int, int, struct shmid_ds64 *);
240 #endif /* _KERNEL */
243 #ifdef __cplusplus
245 #endif
247 #endif /* _IPC_IMPL_H */