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]
22 * Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
28 #include <sys/types.h>
30 #include <sys/mutex.h>
31 #include <sys/ipc_rctl.h>
32 #include <sys/project.h>
34 #include <sys/sysmacros.h>
36 #include <sys/id_space.h>
44 typedef uint64_t ipc_time_t
;
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)
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 */
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
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 */
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 */
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 */
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) + \
150 #define IPC_ZONE_USAGE(p, s) \
151 (*(rctl_qty_t *)(((char *)&p->ipc_zone_ref.zref_zone->zone_ipc) + \
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 */
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 *)];
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) */
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
*,
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
);
236 int msgctl64(int, int, struct msqid_ds64
*);
237 int semctl64(int, int, int, ...);
238 int shmctl64(int, int, struct shmid_ds64
*);
247 #endif /* _IPC_IMPL_H */