]> git.saurik.com Git - apple/xnu.git/blame - osfmk/ipc/ipc_voucher.h
xnu-4903.270.47.tar.gz
[apple/xnu.git] / osfmk / ipc / ipc_voucher.h
CommitLineData
fe8ab488
A
1/*
2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
0a7de745 5 *
fe8ab488
A
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
0a7de745 14 *
fe8ab488
A
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
0a7de745 17 *
fe8ab488
A
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
0a7de745 25 *
fe8ab488
A
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
0a7de745
A
28#ifndef _IPC_IPC_VOUCHER_H_
29#define _IPC_IPC_VOUCHER_H_
fe8ab488
A
30
31#include <mach/mach_types.h>
32#include <mach/mach_voucher_types.h>
33#include <mach/boolean.h>
34#include <ipc/ipc_types.h>
d9a64523 35#include <os/refcnt.h>
fe8ab488
A
36
37#ifdef MACH_KERNEL_PRIVATE
38
39#include <kern/queue.h>
40#include <kern/locks.h>
41#include <kern/simple_lock.h>
39037602 42#include <voucher/ipc_pthread_priority_types.h>
fe8ab488
A
43
44/* locking */
0a7de745
A
45extern lck_grp_t ipc_lck_grp;
46extern lck_attr_t ipc_lck_attr;
fe8ab488
A
47
48extern void ipc_voucher_init(void);
49
50/* some shorthand for longer types */
51typedef mach_voucher_attr_value_handle_t iv_value_handle_t;
52typedef mach_voucher_attr_value_reference_t iv_value_refs_t;
53
0a7de745
A
54typedef natural_t iv_index_t;
55#define IV_UNUSED_VALINDEX ((iv_index_t) 0)
56#define IV_UNUSED_KEYINDEX ((iv_index_t) ~0)
fe8ab488 57
0a7de745
A
58typedef iv_index_t *iv_entry_t;
59#define IVE_NULL ((iv_entry_t) 0)
fe8ab488
A
60
61#define IV_ENTRIES_INLINE MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN
62
63/*
64 * IPC Voucher
65 *
66 * Vouchers are a reference counted immutable (once-created) set of
67 * indexes to particular resource manager attribute values
68 * (which themselves are reference counted).
69 */
70struct ipc_voucher {
0a7de745
A
71 iv_index_t iv_hash; /* checksum hash */
72 iv_index_t iv_sum; /* checksum of values */
73 os_refcnt_t iv_refs; /* reference count */
74 iv_index_t iv_table_size; /* size of the voucher table */
75 iv_index_t iv_inline_table[IV_ENTRIES_INLINE];
76 iv_entry_t iv_table; /* table of voucher attr entries */
77 ipc_port_t iv_port; /* port representing the voucher */
78 queue_chain_t iv_hash_link; /* link on hash chain */
fe8ab488
A
79};
80
0a7de745 81#define IV_NULL IPC_VOUCHER_NULL
fe8ab488
A
82
83
84/*
85 * Voucher Attribute Cache Control Object
86 *
87 * This is where the Voucher system stores its caches/references to
88 * returned resource manager attribute values. Each value only appears
89 * once in the table. If a value is returned more than once by the
90 * resource manager, the voucher system will increase the reference
0a7de745 91 * on the previous value.
fe8ab488
A
92 *
93 * The voucher itself contains one entry per key, that indexes into
94 * this table.
95 *
96 * A voucher that does not have an explicit index for a given key
97 * is assumed to have a reference on slot zero - which is where the
98 * voucher system stores the default value for the given attribute
99 * (specified at the time of resource manager registration).
100 *
101 * The ivace_releasing field limits the entry to a single concurrent
102 * return. Without it, a previous release's reply might still be
103 * working its way back to the voucher code, and a subsequent get-
104 * value could return the same value as was previously returned. If
105 * the resource manager already knew that, it would return a failure
106 * on the return, and all is well. We just treat the additional made
107 * references on the value as we normally would. However, if the resource
108 * manager accepted the return, and the get-value response raced the
109 * release's reply, the newly made references will look like an extension
110 * of the old value's cache lifetime, rather than a new one. Dropping
0a7de745 111 * that new lifetime's references to zero would result in a second
fe8ab488
A
112 * release callback to the resource manager - this time with the wrong
113 * "made" reference count. We avoid the race with this flag.
114 */
115
116struct ivac_entry_s {
117 iv_value_handle_t ivace_value;
118 iv_value_refs_t ivace_layered:1, /* layered effective entry */
0a7de745
A
119 ivace_releasing:1, /* release in progress */
120 ivace_free:1, /* on freelist */
121 ivace_persist:1, /* Persist the entry, don't count made refs */
122 ivace_refs:28; /* reference count */
fe8ab488
A
123 union {
124 iv_value_refs_t ivaceu_made; /* made count (non-layered) */
125 iv_index_t ivaceu_layer; /* next effective layer (layered) */
126 } ivace_u;
127 iv_index_t ivace_next; /* hash or freelist */
128 iv_index_t ivace_index; /* hash head (independent) */
129};
130typedef struct ivac_entry_s ivac_entry;
131typedef ivac_entry *ivac_entry_t;
132
133#define ivace_made ivace_u.ivaceu_made
134#define ivace_layer ivace_u.ivaceu_layer
135
136#define IVACE_NULL ((ivac_entry_t) 0);
137
490019cf 138#define IVACE_REFS_MAX ((1 << 28) - 1)
fe8ab488
A
139
140#define IVAC_ENTRIES_MIN 512
141#define IVAC_ENTRIES_MAX 524288
142
143struct ipc_voucher_attr_control {
d9a64523 144 os_refcnt_t ivac_refs;
0a7de745
A
145 boolean_t ivac_is_growing; /* is the table being grown */
146 ivac_entry_t ivac_table; /* table of voucher attr value entries */
147 iv_index_t ivac_table_size; /* size of the attr value table */
148 iv_index_t ivac_init_table_size; /* size of the attr value table */
149 iv_index_t ivac_freelist; /* index of the first free element */
150 ipc_port_t ivac_port; /* port for accessing the cache control */
fe8ab488 151 lck_spin_t ivac_lock_data;
0a7de745 152 iv_index_t ivac_key_index; /* key index for this value */
fe8ab488
A
153};
154typedef ipc_voucher_attr_control_t iv_attr_control_t;
155
156#define IVAC_NULL IPC_VOUCHER_ATTR_CONTROL_NULL
157
158extern ipc_voucher_attr_control_t ivac_alloc(iv_index_t);
490019cf
A
159extern void ipc_voucher_receive_postprocessing(ipc_kmsg_t kmsg, mach_msg_option_t option);
160extern void ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg);
39037602
A
161extern void mach_init_activity_id(void);
162extern kern_return_t ipc_get_pthpriority_from_kmsg_voucher(ipc_kmsg_t kmsg, ipc_pthread_priority_value_t *qos);
fe8ab488
A
163#define ivac_lock_init(ivac) \
164 lck_spin_init(&(ivac)->ivac_lock_data, &ipc_lck_grp, &ipc_lck_attr)
165#define ivac_lock_destroy(ivac) \
166 lck_spin_destroy(&(ivac)->ivac_lock_data, &ipc_lck_grp)
0a7de745
A
167#define ivac_lock(ivac) \
168 lck_spin_lock_grp(&(ivac)->ivac_lock_data, &ipc_lck_grp)
169#define ivac_lock_try(ivac) \
170 lck_spin_try_lock_grp(&(ivac)->ivac_lock_data, &ipc_lck_grp)
171#define ivac_unlock(ivac) \
fe8ab488 172 lck_spin_unlock(&(ivac)->ivac_lock_data)
0a7de745
A
173#define ivac_sleep(ivac) lck_spin_sleep_grp(&(ivac)->ivac_lock_data, \
174 LCK_SLEEP_DEFAULT, \
175 (event_t)(ivac), \
176 THREAD_UNINT, &ipc_lck_grp)
fe8ab488
A
177#define ivac_wakeup(ivac) thread_wakeup((event_t)(ivac))
178
179extern void ivac_dealloc(ipc_voucher_attr_control_t ivac);
180
181static inline void
182ivac_reference(ipc_voucher_attr_control_t ivac)
183{
0a7de745 184 if (ivac == IVAC_NULL) {
d9a64523 185 return;
0a7de745 186 }
d9a64523 187 os_ref_retain(&ivac->ivac_refs);
fe8ab488
A
188}
189
190static inline void
191ivac_release(ipc_voucher_attr_control_t ivac)
192{
0a7de745 193 if (IVAC_NULL == ivac) {
fe8ab488 194 return;
0a7de745 195 }
fe8ab488 196
d9a64523 197 if (os_ref_release(&ivac->ivac_refs) == 0) {
fe8ab488 198 ivac_dealloc(ivac);
d9a64523 199 }
fe8ab488
A
200}
201
202#define IVAM_NULL IPC_VOUCHER_ATTR_MANAGER_NULL
203
204/*
205 * IPC voucher Resource Manager table element
206 *
207 * Information Associated with a specific registration of
208 * a voucher resource manager.
209 *
210 * NOTE: For now, this table is indexed directly by the key. In the future,
211 * it will have to be growable and sparse by key. When that is implemented
212 * the index will be independent from the key (but there will be a hash to
213 * find the index by key).
214 */
215typedef struct ipc_voucher_global_table_element {
0a7de745
A
216 ipc_voucher_attr_manager_t ivgte_manager;
217 ipc_voucher_attr_control_t ivgte_control;
218 mach_voucher_attr_key_t ivgte_key;
fe8ab488
A
219} ipc_voucher_global_table_element;
220
221typedef ipc_voucher_global_table_element *ipc_voucher_global_table_element_t;
222
223#endif /* MACH_KERNEL_PRIVATE */
224
225/*
226 * IPC voucher attribute recipe
227 *
228 * In-kernel recipe format with an ipc_voucher_t pointer for the previous
229 * voucher reference.
230 */
231#pragma pack(1)
232typedef struct ipc_voucher_attr_recipe_data {
0a7de745 233 mach_voucher_attr_key_t key;
fe8ab488 234 mach_voucher_attr_recipe_command_t command;
0a7de745
A
235 ipc_voucher_t previous_voucher;
236 mach_voucher_attr_content_size_t content_size;
237 uint8_t content[];
fe8ab488
A
238} ipc_voucher_attr_recipe_data_t;
239typedef ipc_voucher_attr_recipe_data_t *ipc_voucher_attr_recipe_t;
240typedef mach_msg_type_number_t ipc_voucher_attr_recipe_size_t;
241
242typedef uint8_t *ipc_voucher_attr_raw_recipe_t;
243typedef ipc_voucher_attr_raw_recipe_t ipc_voucher_attr_raw_recipe_array_t;
244typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_size_t;
245typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_array_size_t;
246
247#pragma pack()
248
249/*
250 * In-kernel Resource Manager Definition
251 *
252 * In-kernel resource managers are defined by a v-table like structure for
253 * the three callouts supported by a resource manager (and release function).
254 *
255 * There is a single in-kernel resource manager that represents all the
256 * outside kernel managers (and reflects the calls through MIG to user-space).
257 */
258
259typedef kern_return_t (*ipc_voucher_attr_manager_release_value_t)(ipc_voucher_attr_manager_t,
0a7de745
A
260 mach_voucher_attr_key_t,
261 mach_voucher_attr_value_handle_t,
262 mach_voucher_attr_value_reference_t);
fe8ab488
A
263
264typedef kern_return_t (*ipc_voucher_attr_manager_get_value_t)(ipc_voucher_attr_manager_t,
0a7de745
A
265 mach_voucher_attr_key_t,
266 mach_voucher_attr_recipe_command_t,
267 mach_voucher_attr_value_handle_array_t,
268 mach_voucher_attr_value_handle_array_size_t,
269 mach_voucher_attr_content_t,
270 mach_voucher_attr_content_size_t,
271 mach_voucher_attr_value_handle_t *,
272 mach_voucher_attr_value_flags_t *,
273 ipc_voucher_t *);
fe8ab488
A
274
275typedef kern_return_t (*ipc_voucher_attr_manager_extract_content_t)(ipc_voucher_attr_manager_t,
0a7de745
A
276 mach_voucher_attr_key_t,
277 mach_voucher_attr_value_handle_array_t,
278 mach_voucher_attr_value_handle_array_size_t,
279 mach_voucher_attr_recipe_command_t *,
280 mach_voucher_attr_content_t,
281 mach_voucher_attr_content_size_t *);
fe8ab488
A
282
283typedef kern_return_t (*ipc_voucher_attr_manager_command_t)(ipc_voucher_attr_manager_t,
0a7de745
A
284 mach_voucher_attr_key_t,
285 mach_voucher_attr_value_handle_array_t,
286 mach_voucher_attr_value_handle_array_size_t,
287 mach_voucher_attr_command_t,
288 mach_voucher_attr_content_t,
289 mach_voucher_attr_content_size_t,
290 mach_voucher_attr_content_t,
291 mach_voucher_attr_content_size_t *);
fe8ab488
A
292
293typedef void (*ipc_voucher_attr_manager_release_t)(ipc_voucher_attr_manager_t);
294
490019cf
A
295typedef uint32_t ipc_voucher_attr_manager_flags;
296
fe8ab488 297struct ipc_voucher_attr_manager {
0a7de745
A
298 ipc_voucher_attr_manager_release_value_t ivam_release_value;
299 ipc_voucher_attr_manager_get_value_t ivam_get_value;
300 ipc_voucher_attr_manager_extract_content_t ivam_extract_content;
301 ipc_voucher_attr_manager_command_t ivam_command;
302 ipc_voucher_attr_manager_release_t ivam_release;
303 ipc_voucher_attr_manager_flags ivam_flags;
fe8ab488
A
304};
305
490019cf
A
306#define IVAM_FLAGS_NONE 0
307#define IVAM_FLAGS_SUPPORT_SEND_PREPROCESS 0x1
308#define IVAM_FLAGS_SUPPORT_RECEIVE_POSTPROCESS 0x2
309
fe8ab488
A
310__BEGIN_DECLS
311
312/* DEBUG/TRACE Convert from a port to a voucher */
313extern uintptr_t unsafe_convert_port_to_voucher(
0a7de745 314 ipc_port_t port);
fe8ab488
A
315
316/* Convert from a port to a voucher */
317extern ipc_voucher_t convert_port_to_voucher(
0a7de745 318 ipc_port_t port);
fe8ab488
A
319
320/* Convert from a port name to an ipc_voucher */
321extern ipc_voucher_t convert_port_name_to_voucher(
0a7de745 322 mach_port_name_t name);
fe8ab488
A
323
324/* add a reference to the specified voucher */
325extern void ipc_voucher_reference(
0a7de745 326 ipc_voucher_t voucher);
fe8ab488
A
327
328/* drop the voucher reference picked up above */
329extern void ipc_voucher_release(
0a7de745 330 ipc_voucher_t voucher);
fe8ab488
A
331
332/* deliver voucher notifications */
333extern void ipc_voucher_notify(
0a7de745 334 mach_msg_header_t *msg);
fe8ab488
A
335
336/* Convert from a voucher to a port */
337extern ipc_port_t convert_voucher_to_port(
0a7de745 338 ipc_voucher_t voucher);
fe8ab488
A
339
340/* convert from a voucher attribute control to a port */
341extern ipc_port_t convert_voucher_attr_control_to_port(
0a7de745 342 ipc_voucher_attr_control_t control);
fe8ab488
A
343
344/* add a reference to the specified voucher */
345extern void ipc_voucher_attr_control_reference(
0a7de745 346 ipc_voucher_attr_control_t control);
fe8ab488
A
347
348/* drop the reference picked up above */
349extern void ipc_voucher_attr_control_release(
0a7de745 350 ipc_voucher_attr_control_t control);
fe8ab488
A
351
352/* deliver voucher control notifications */
353extern void ipc_voucher_attr_control_notify(
0a7de745 354 mach_msg_header_t *msg);
fe8ab488
A
355
356/* convert from a port to a voucher attribute control */
357extern ipc_voucher_attr_control_t convert_port_to_voucher_attr_control(
0a7de745 358 ipc_port_t port);
fe8ab488
A
359
360/*
361 * In-kernel equivalents to the user syscalls
362 */
363extern kern_return_t
364ipc_create_mach_voucher(
0a7de745
A
365 ipc_voucher_attr_raw_recipe_array_t recipes,
366 ipc_voucher_attr_raw_recipe_array_size_t recipe_size,
367 ipc_voucher_t *new_voucher);
fe8ab488
A
368
369extern kern_return_t
370ipc_voucher_attr_control_create_mach_voucher(
0a7de745
A
371 ipc_voucher_attr_control_t control,
372 ipc_voucher_attr_raw_recipe_array_t recipes,
373 ipc_voucher_attr_raw_recipe_array_size_t recipe_size,
374 ipc_voucher_t *new_voucher);
fe8ab488 375
0a7de745 376extern kern_return_t
fe8ab488 377ipc_register_well_known_mach_voucher_attr_manager(
0a7de745
A
378 ipc_voucher_attr_manager_t manager,
379 mach_voucher_attr_value_handle_t default_value,
380 mach_voucher_attr_key_t key,
381 ipc_voucher_attr_control_t *control);
fe8ab488
A
382
383
384extern kern_return_t
385ipc_register_mach_voucher_attr_manager(
0a7de745
A
386 ipc_voucher_attr_manager_t manager,
387 mach_voucher_attr_value_handle_t default_value,
388 mach_voucher_attr_key_t *key,
389 ipc_voucher_attr_control_t *control);
fe8ab488
A
390
391__END_DECLS
0a7de745
A
392
393#endif /* _IPC_IPC_VOUCHER_H_ */