2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
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.
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
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.
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
28 #ifndef _IPC_IPC_VOUCHER_H_
29 #define _IPC_IPC_VOUCHER_H_
31 #include <mach/mach_types.h>
32 #include <mach/mach_voucher_types.h>
33 #include <mach/boolean.h>
34 #include <ipc/ipc_types.h>
36 #ifdef MACH_KERNEL_PRIVATE
38 #include <kern/queue.h>
39 #include <kern/locks.h>
40 #include <kern/simple_lock.h>
41 #include <voucher/ipc_pthread_priority_types.h>
44 extern lck_grp_t ipc_lck_grp
;
45 extern lck_attr_t ipc_lck_attr
;
47 extern void ipc_voucher_init(void);
49 /* some shorthand for longer types */
50 typedef mach_voucher_attr_value_handle_t iv_value_handle_t
;
51 typedef mach_voucher_attr_value_reference_t iv_value_refs_t
;
53 typedef natural_t iv_refs_t
;
55 typedef natural_t iv_index_t
;
56 #define IV_UNUSED_VALINDEX ((iv_index_t) 0)
57 #define IV_UNUSED_KEYINDEX ((iv_index_t) ~0)
59 typedef iv_index_t
*iv_entry_t
;
60 #define IVE_NULL ((iv_entry_t) 0)
62 #define IV_ENTRIES_INLINE MACH_VOUCHER_ATTR_KEY_NUM_WELL_KNOWN
67 * Vouchers are a reference counted immutable (once-created) set of
68 * indexes to particular resource manager attribute values
69 * (which themselves are reference counted).
72 iv_index_t iv_hash
; /* checksum hash */
73 iv_index_t iv_sum
; /* checksum of values */
74 iv_refs_t iv_refs
; /* reference count */
75 iv_index_t iv_table_size
; /* size of the voucher table */
76 iv_index_t iv_inline_table
[IV_ENTRIES_INLINE
];
77 iv_entry_t iv_table
; /* table of voucher attr entries */
78 ipc_port_t iv_port
; /* port representing the voucher */
79 queue_chain_t iv_hash_link
; /* link on hash chain */
82 #define IV_NULL IPC_VOUCHER_NULL
86 * Voucher Attribute Cache Control Object
88 * This is where the Voucher system stores its caches/references to
89 * returned resource manager attribute values. Each value only appears
90 * once in the table. If a value is returned more than once by the
91 * resource manager, the voucher system will increase the reference
92 * on the previous value.
94 * The voucher itself contains one entry per key, that indexes into
97 * A voucher that does not have an explicit index for a given key
98 * is assumed to have a reference on slot zero - which is where the
99 * voucher system stores the default value for the given attribute
100 * (specified at the time of resource manager registration).
102 * The ivace_releasing field limits the entry to a single concurrent
103 * return. Without it, a previous release's reply might still be
104 * working its way back to the voucher code, and a subsequent get-
105 * value could return the same value as was previously returned. If
106 * the resource manager already knew that, it would return a failure
107 * on the return, and all is well. We just treat the additional made
108 * references on the value as we normally would. However, if the resource
109 * manager accepted the return, and the get-value response raced the
110 * release's reply, the newly made references will look like an extension
111 * of the old value's cache lifetime, rather than a new one. Dropping
112 * that new lifetime's references to zero would result in a second
113 * release callback to the resource manager - this time with the wrong
114 * "made" reference count. We avoid the race with this flag.
117 struct ivac_entry_s
{
118 iv_value_handle_t ivace_value
;
119 iv_value_refs_t ivace_layered
:1, /* layered effective entry */
120 ivace_releasing
:1, /* release in progress */
121 ivace_free
:1, /* on freelist */
122 ivace_persist
:1, /* Persist the entry, don't count made refs */
123 ivace_refs
:28; /* reference count */
125 iv_value_refs_t ivaceu_made
; /* made count (non-layered) */
126 iv_index_t ivaceu_layer
; /* next effective layer (layered) */
128 iv_index_t ivace_next
; /* hash or freelist */
129 iv_index_t ivace_index
; /* hash head (independent) */
131 typedef struct ivac_entry_s ivac_entry
;
132 typedef ivac_entry
*ivac_entry_t
;
134 #define ivace_made ivace_u.ivaceu_made
135 #define ivace_layer ivace_u.ivaceu_layer
137 #define IVACE_NULL ((ivac_entry_t) 0);
139 #define IVACE_REFS_MAX ((1 << 28) - 1)
141 #define IVAC_ENTRIES_MIN 512
142 #define IVAC_ENTRIES_MAX 524288
144 struct ipc_voucher_attr_control
{
146 boolean_t ivac_is_growing
; /* is the table being grown */
147 ivac_entry_t ivac_table
; /* table of voucher attr value entries */
148 iv_index_t ivac_table_size
; /* size of the attr value table */
149 iv_index_t ivac_init_table_size
; /* size of the attr value table */
150 iv_index_t ivac_freelist
; /* index of the first free element */
151 ipc_port_t ivac_port
; /* port for accessing the cache control */
152 lck_spin_t ivac_lock_data
;
153 iv_index_t ivac_key_index
; /* key index for this value */
155 typedef ipc_voucher_attr_control_t iv_attr_control_t
;
157 #define IVAC_NULL IPC_VOUCHER_ATTR_CONTROL_NULL
159 extern ipc_voucher_attr_control_t
ivac_alloc(iv_index_t
);
160 extern void ipc_voucher_receive_postprocessing(ipc_kmsg_t kmsg
, mach_msg_option_t option
);
161 extern void ipc_voucher_send_preprocessing(ipc_kmsg_t kmsg
);
162 extern void mach_init_activity_id(void);
163 extern kern_return_t
ipc_get_pthpriority_from_kmsg_voucher(ipc_kmsg_t kmsg
, ipc_pthread_priority_value_t
*qos
);
164 #define ivac_lock_init(ivac) \
165 lck_spin_init(&(ivac)->ivac_lock_data, &ipc_lck_grp, &ipc_lck_attr)
166 #define ivac_lock_destroy(ivac) \
167 lck_spin_destroy(&(ivac)->ivac_lock_data, &ipc_lck_grp)
168 #define ivac_lock(ivac) \
169 lck_spin_lock(&(ivac)->ivac_lock_data)
170 #define ivac_lock_try(ivac) \
171 lck_spin_try_lock(&(ivac)->ivac_lock_data)
172 #define ivac_unlock(ivac) \
173 lck_spin_unlock(&(ivac)->ivac_lock_data)
174 #define ivac_sleep(ivac) lck_spin_sleep(&(ivac)->ivac_lock_data, \
178 #define ivac_wakeup(ivac) thread_wakeup((event_t)(ivac))
180 extern void ivac_dealloc(ipc_voucher_attr_control_t ivac
);
183 ivac_reference(ipc_voucher_attr_control_t ivac
)
185 (void)hw_atomic_add(&ivac
->ivac_refs
, 1);
189 ivac_release(ipc_voucher_attr_control_t ivac
)
193 if (IVAC_NULL
== ivac
)
196 refs
= hw_atomic_sub(&ivac
->ivac_refs
, 1);
201 #define IVAM_NULL IPC_VOUCHER_ATTR_MANAGER_NULL
204 * IPC voucher Resource Manager table element
206 * Information Associated with a specific registration of
207 * a voucher resource manager.
209 * NOTE: For now, this table is indexed directly by the key. In the future,
210 * it will have to be growable and sparse by key. When that is implemented
211 * the index will be independent from the key (but there will be a hash to
212 * find the index by key).
214 typedef struct ipc_voucher_global_table_element
{
215 ipc_voucher_attr_manager_t ivgte_manager
;
216 ipc_voucher_attr_control_t ivgte_control
;
217 mach_voucher_attr_key_t ivgte_key
;
218 } ipc_voucher_global_table_element
;
220 typedef ipc_voucher_global_table_element
*ipc_voucher_global_table_element_t
;
222 #endif /* MACH_KERNEL_PRIVATE */
225 * IPC voucher attribute recipe
227 * In-kernel recipe format with an ipc_voucher_t pointer for the previous
231 typedef struct ipc_voucher_attr_recipe_data
{
232 mach_voucher_attr_key_t key
;
233 mach_voucher_attr_recipe_command_t command
;
234 ipc_voucher_t previous_voucher
;
235 mach_voucher_attr_content_size_t content_size
;
237 } ipc_voucher_attr_recipe_data_t
;
238 typedef ipc_voucher_attr_recipe_data_t
*ipc_voucher_attr_recipe_t
;
239 typedef mach_msg_type_number_t ipc_voucher_attr_recipe_size_t
;
241 typedef uint8_t *ipc_voucher_attr_raw_recipe_t
;
242 typedef ipc_voucher_attr_raw_recipe_t ipc_voucher_attr_raw_recipe_array_t
;
243 typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_size_t
;
244 typedef mach_msg_type_number_t ipc_voucher_attr_raw_recipe_array_size_t
;
249 * In-kernel Resource Manager Definition
251 * In-kernel resource managers are defined by a v-table like structure for
252 * the three callouts supported by a resource manager (and release function).
254 * There is a single in-kernel resource manager that represents all the
255 * outside kernel managers (and reflects the calls through MIG to user-space).
258 typedef kern_return_t (*ipc_voucher_attr_manager_release_value_t
)(ipc_voucher_attr_manager_t
,
259 mach_voucher_attr_key_t
,
260 mach_voucher_attr_value_handle_t
,
261 mach_voucher_attr_value_reference_t
);
263 typedef kern_return_t (*ipc_voucher_attr_manager_get_value_t
)(ipc_voucher_attr_manager_t
,
264 mach_voucher_attr_key_t
,
265 mach_voucher_attr_recipe_command_t
,
266 mach_voucher_attr_value_handle_array_t
,
267 mach_voucher_attr_value_handle_array_size_t
,
268 mach_voucher_attr_content_t
,
269 mach_voucher_attr_content_size_t
,
270 mach_voucher_attr_value_handle_t
*,
271 mach_voucher_attr_value_flags_t
*,
274 typedef kern_return_t (*ipc_voucher_attr_manager_extract_content_t
)(ipc_voucher_attr_manager_t
,
275 mach_voucher_attr_key_t
,
276 mach_voucher_attr_value_handle_array_t
,
277 mach_voucher_attr_value_handle_array_size_t
,
278 mach_voucher_attr_recipe_command_t
*,
279 mach_voucher_attr_content_t
,
280 mach_voucher_attr_content_size_t
*);
282 typedef kern_return_t (*ipc_voucher_attr_manager_command_t
)(ipc_voucher_attr_manager_t
,
283 mach_voucher_attr_key_t
,
284 mach_voucher_attr_value_handle_array_t
,
285 mach_voucher_attr_value_handle_array_size_t
,
286 mach_voucher_attr_command_t
,
287 mach_voucher_attr_content_t
,
288 mach_voucher_attr_content_size_t
,
289 mach_voucher_attr_content_t
,
290 mach_voucher_attr_content_size_t
*);
292 typedef void (*ipc_voucher_attr_manager_release_t
)(ipc_voucher_attr_manager_t
);
294 typedef uint32_t ipc_voucher_attr_manager_flags
;
296 struct ipc_voucher_attr_manager
{
297 ipc_voucher_attr_manager_release_value_t ivam_release_value
;
298 ipc_voucher_attr_manager_get_value_t ivam_get_value
;
299 ipc_voucher_attr_manager_extract_content_t ivam_extract_content
;
300 ipc_voucher_attr_manager_command_t ivam_command
;
301 ipc_voucher_attr_manager_release_t ivam_release
;
302 ipc_voucher_attr_manager_flags ivam_flags
;
305 #define IVAM_FLAGS_NONE 0
306 #define IVAM_FLAGS_SUPPORT_SEND_PREPROCESS 0x1
307 #define IVAM_FLAGS_SUPPORT_RECEIVE_POSTPROCESS 0x2
311 /* DEBUG/TRACE Convert from a port to a voucher */
312 extern uintptr_t unsafe_convert_port_to_voucher(
315 /* Convert from a port to a voucher */
316 extern ipc_voucher_t
convert_port_to_voucher(
319 /* Convert from a port name to an ipc_voucher */
320 extern ipc_voucher_t
convert_port_name_to_voucher(
321 mach_port_name_t name
);
323 /* add a reference to the specified voucher */
324 extern void ipc_voucher_reference(
325 ipc_voucher_t voucher
);
327 /* drop the voucher reference picked up above */
328 extern void ipc_voucher_release(
329 ipc_voucher_t voucher
);
331 /* deliver voucher notifications */
332 extern void ipc_voucher_notify(
333 mach_msg_header_t
*msg
);
335 /* Convert from a voucher to a port */
336 extern ipc_port_t
convert_voucher_to_port(
337 ipc_voucher_t voucher
);
339 /* convert from a voucher attribute control to a port */
340 extern ipc_port_t
convert_voucher_attr_control_to_port(
341 ipc_voucher_attr_control_t control
);
343 /* add a reference to the specified voucher */
344 extern void ipc_voucher_attr_control_reference(
345 ipc_voucher_attr_control_t control
);
347 /* drop the reference picked up above */
348 extern void ipc_voucher_attr_control_release(
349 ipc_voucher_attr_control_t control
);
351 /* deliver voucher control notifications */
352 extern void ipc_voucher_attr_control_notify(
353 mach_msg_header_t
*msg
);
355 /* convert from a port to a voucher attribute control */
356 extern ipc_voucher_attr_control_t
convert_port_to_voucher_attr_control(
360 * In-kernel equivalents to the user syscalls
363 ipc_create_mach_voucher(
364 ipc_voucher_attr_raw_recipe_array_t recipes
,
365 ipc_voucher_attr_raw_recipe_array_size_t recipe_size
,
366 ipc_voucher_t
*new_voucher
);
369 ipc_voucher_attr_control_create_mach_voucher(
370 ipc_voucher_attr_control_t control
,
371 ipc_voucher_attr_raw_recipe_array_t recipes
,
372 ipc_voucher_attr_raw_recipe_array_size_t recipe_size
,
373 ipc_voucher_t
*new_voucher
);
376 ipc_register_well_known_mach_voucher_attr_manager(
377 ipc_voucher_attr_manager_t manager
,
378 mach_voucher_attr_value_handle_t default_value
,
379 mach_voucher_attr_key_t key
,
380 ipc_voucher_attr_control_t
*control
);
384 ipc_register_mach_voucher_attr_manager(
385 ipc_voucher_attr_manager_t manager
,
386 mach_voucher_attr_value_handle_t default_value
,
387 mach_voucher_attr_key_t
*key
,
388 ipc_voucher_attr_control_t
*control
);
392 #endif /* _IPC_IPC_VOUCHER_H_ */