2 * Copyright (c) 2012-2016 Apple 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@
29 #include <voucher/ipc_pthread_priority_types.h>
30 #include <voucher/ipc_pthread_priority_internal.h>
31 #include <mach/mach_types.h>
32 #include <mach/kern_return.h>
33 #include <ipc/ipc_port.h>
34 #include <mach/mach_vm.h>
35 #include <mach/vm_map.h>
36 #include <vm/vm_map.h>
37 #include <mach/host_priv.h>
38 #include <mach/host_special_ports.h>
39 #include <kern/host.h>
40 #include <kern/ledger.h>
41 #include <sys/kdebug.h>
42 #include <IOKit/IOBSD.h>
43 #include <mach/mach_voucher_attr_control.h>
44 #include <pthread/priority_private.h>
46 ipc_voucher_attr_control_t ipc_pthread_priority_voucher_attr_control
; /* communication channel from PTHPRIORITY to voucher system */
48 #define IPC_PTHREAD_PRIORITY_VALUE_TO_HANDLE(x) ((mach_voucher_attr_value_handle_t)(x))
49 #define HANDLE_TO_IPC_PTHREAD_PRIORITY_VALUE(x) ((ipc_pthread_priority_value_t)(x))
52 ipc_pthread_priority_release_value(
53 ipc_voucher_attr_manager_t __assert_only manager
,
54 mach_voucher_attr_key_t __assert_only key
,
55 mach_voucher_attr_value_handle_t value
,
56 mach_voucher_attr_value_reference_t sync
);
59 ipc_pthread_priority_get_value(
60 ipc_voucher_attr_manager_t __assert_only manager
,
61 mach_voucher_attr_key_t __assert_only key
,
62 mach_voucher_attr_recipe_command_t command
,
63 mach_voucher_attr_value_handle_array_t prev_values
,
64 mach_msg_type_number_t __assert_only prev_value_count
,
65 mach_voucher_attr_content_t recipe
,
66 mach_voucher_attr_content_size_t recipe_size
,
67 mach_voucher_attr_value_handle_t
*out_value
,
68 mach_voucher_attr_value_flags_t
*out_flags
,
69 ipc_voucher_t
*out_value_voucher
);
72 ipc_pthread_priority_extract_content(
73 ipc_voucher_attr_manager_t __assert_only manager
,
74 mach_voucher_attr_key_t __assert_only key
,
75 mach_voucher_attr_value_handle_array_t values
,
76 mach_msg_type_number_t value_count
,
77 mach_voucher_attr_recipe_command_t
*out_command
,
78 mach_voucher_attr_content_t out_recipe
,
79 mach_voucher_attr_content_size_t
*in_out_recipe_size
);
82 ipc_pthread_priority_command(
83 ipc_voucher_attr_manager_t __assert_only manager
,
84 mach_voucher_attr_key_t __assert_only key
,
85 mach_voucher_attr_value_handle_array_t values
,
86 mach_msg_type_number_t value_count
,
87 mach_voucher_attr_command_t command
,
88 mach_voucher_attr_content_t in_content
,
89 mach_voucher_attr_content_size_t in_content_size
,
90 mach_voucher_attr_content_t out_content
,
91 mach_voucher_attr_content_size_t
*in_out_content_size
);
94 ipc_pthread_priority_release(ipc_voucher_attr_manager_t __assert_only manager
);
97 * communication channel from voucher system to IPC_PTHREAD_PRIORITY
99 const struct ipc_voucher_attr_manager ipc_pthread_priority_manager
= {
100 .ivam_release_value
= ipc_pthread_priority_release_value
,
101 .ivam_get_value
= ipc_pthread_priority_get_value
,
102 .ivam_extract_content
= ipc_pthread_priority_extract_content
,
103 .ivam_command
= ipc_pthread_priority_command
,
104 .ivam_release
= ipc_pthread_priority_release
,
105 .ivam_flags
= IVAM_FLAGS_NONE
,
109 * Routine: ipc_pthread_priority_init
110 * Purpose: Initialize the IPC_PTHREAD_PRIORITY subsystem.
114 ipc_pthread_priority_init()
116 kern_return_t kr
= KERN_SUCCESS
;
118 /* Register the ipc_pthread_priority manager with the Vouchers sub system. */
119 kr
= ipc_register_well_known_mach_voucher_attr_manager(
120 &ipc_pthread_priority_manager
,
122 MACH_VOUCHER_ATTR_KEY_PTHPRIORITY
,
123 &ipc_pthread_priority_voucher_attr_control
);
124 if (kr
!= KERN_SUCCESS
) {
125 panic("IPC_PTHREAD_PRIORITY subsystem initialization failed");
128 kprintf("IPC_PTHREAD_PRIORITY subsystem is initialized\n");
133 * IPC_PTHREAD_PRIORITY Resource Manager Routines.
138 * Routine: ipc_pthread_priority_release_value
139 * Purpose: Release a value, if sync matches the sync count in value.
140 * Returns: KERN_SUCCESS: on Successful deletion.
141 * KERN_FAILURE: if sync value does not matches.
144 ipc_pthread_priority_release_value(
145 ipc_voucher_attr_manager_t __assert_only manager
,
146 mach_voucher_attr_key_t __assert_only key
,
147 mach_voucher_attr_value_handle_t value
,
148 mach_voucher_attr_value_reference_t sync
)
150 assert(MACH_VOUCHER_ATTR_KEY_PTHPRIORITY
== key
);
151 assert(manager
== &ipc_pthread_priority_manager
);
153 ipc_pthread_priority_value_t ipc_pthread_priority_value
= HANDLE_TO_IPC_PTHREAD_PRIORITY_VALUE(value
);
155 panic("ipc_pthread_priority_release_value called for a persistent PTHPRIORITY value %x with sync value %d\n", ipc_pthread_priority_value
, sync
);
160 * Routine: ipc_pthread_priority_get_value
163 ipc_pthread_priority_get_value(
164 ipc_voucher_attr_manager_t __assert_only manager
,
165 mach_voucher_attr_key_t __assert_only key
,
166 mach_voucher_attr_recipe_command_t command
,
167 mach_voucher_attr_value_handle_array_t __unused prev_values
,
168 mach_msg_type_number_t __unused prev_value_count
,
169 mach_voucher_attr_content_t recipe
,
170 mach_voucher_attr_content_size_t recipe_size
,
171 mach_voucher_attr_value_handle_t
*out_value
,
172 mach_voucher_attr_value_flags_t
*out_flags
,
173 ipc_voucher_t
*out_value_voucher
)
175 kern_return_t kr
= KERN_SUCCESS
;
176 ipc_pthread_priority_value_t ipc_pthread_priority_value
;
177 ipc_pthread_priority_value_t canonicalize_priority_value
;
179 assert(MACH_VOUCHER_ATTR_KEY_PTHPRIORITY
== key
);
180 assert(manager
== &ipc_pthread_priority_manager
);
182 /* never an out voucher */
183 *out_value_voucher
= IPC_VOUCHER_NULL
;
184 *out_flags
= MACH_VOUCHER_ATTR_VALUE_FLAGS_NONE
;
187 case MACH_VOUCHER_ATTR_PTHPRIORITY_CREATE
:
189 if (recipe_size
!= sizeof(ipc_pthread_priority_value_t
)) {
190 return KERN_INVALID_ARGUMENT
;
193 memcpy(&ipc_pthread_priority_value
, recipe
, recipe_size
);
195 if (ipc_pthread_priority_value
== PTHPRIORITY_ATTR_DEFAULT_VALUE
) {
196 *out_value
= IPC_PTHREAD_PRIORITY_VALUE_TO_HANDLE(PTHPRIORITY_ATTR_DEFAULT_VALUE
);
200 /* Callout to pthread kext to get the canonicalized value */
201 canonicalize_priority_value
= (ipc_pthread_priority_value_t
)
202 _pthread_priority_normalize_for_ipc((unsigned long)ipc_pthread_priority_value
);
204 *out_value
= IPC_PTHREAD_PRIORITY_VALUE_TO_HANDLE(canonicalize_priority_value
);
205 *out_flags
= MACH_VOUCHER_ATTR_VALUE_FLAGS_PERSIST
;
209 kr
= KERN_INVALID_ARGUMENT
;
217 * Routine: ipc_pthread_priority_extract_content
218 * Purpose: Extract a set of pthread_priority value from an array of voucher values.
219 * Returns: KERN_SUCCESS: on Success.
220 * KERN_NO_SPACE: insufficeint buffer provided to fill an array of pthread_priority values.
223 ipc_pthread_priority_extract_content(
224 ipc_voucher_attr_manager_t __assert_only manager
,
225 mach_voucher_attr_key_t __assert_only key
,
226 mach_voucher_attr_value_handle_array_t values
,
227 mach_msg_type_number_t value_count
,
228 mach_voucher_attr_recipe_command_t
*out_command
,
229 mach_voucher_attr_content_t out_recipe
,
230 mach_voucher_attr_content_size_t
*in_out_recipe_size
)
232 kern_return_t kr
= KERN_SUCCESS
;
233 mach_msg_type_number_t i
;
234 ipc_pthread_priority_value_t ipc_pthread_priority_value
;
236 assert(MACH_VOUCHER_ATTR_KEY_PTHPRIORITY
== key
);
237 assert(manager
== &ipc_pthread_priority_manager
);
239 for (i
= 0; i
< value_count
&& *in_out_recipe_size
> 0; i
++) {
240 ipc_pthread_priority_value
= HANDLE_TO_IPC_PTHREAD_PRIORITY_VALUE(values
[i
]);
242 if (ipc_pthread_priority_value
== PTHPRIORITY_ATTR_DEFAULT_VALUE
) {
246 if (MACH_VOUCHER_PTHPRIORITY_CONTENT_SIZE
> *in_out_recipe_size
) {
247 *in_out_recipe_size
= 0;
248 return KERN_NO_SPACE
;
251 memcpy(&out_recipe
[0], &ipc_pthread_priority_value
, sizeof(ipc_pthread_priority_value
));
252 *out_command
= MACH_VOUCHER_ATTR_PTHPRIORITY_NULL
;
253 *in_out_recipe_size
= (mach_voucher_attr_content_size_t
)sizeof(ipc_pthread_priority_value
);
257 *in_out_recipe_size
= 0;
258 return KERN_INVALID_VALUE
;
262 * Routine: ipc_pthread_priority_command
263 * Purpose: Execute a command against a set of PTHPRIORITY values.
264 * Returns: KERN_SUCCESS: On successful execution of command.
265 * KERN_FAILURE: On failure.
268 ipc_pthread_priority_command(
269 ipc_voucher_attr_manager_t __assert_only manager
,
270 mach_voucher_attr_key_t __assert_only key
,
271 mach_voucher_attr_value_handle_array_t __unused values
,
272 mach_msg_type_number_t __unused value_count
,
273 mach_voucher_attr_command_t __unused command
,
274 mach_voucher_attr_content_t __unused in_content
,
275 mach_voucher_attr_content_size_t __unused in_content_size
,
276 mach_voucher_attr_content_t __unused out_content
,
277 mach_voucher_attr_content_size_t __unused
*out_content_size
)
279 assert(MACH_VOUCHER_ATTR_KEY_PTHPRIORITY
== key
);
280 assert(manager
== &ipc_pthread_priority_manager
);
286 ipc_pthread_priority_release(
287 ipc_voucher_attr_manager_t __assert_only manager
)
289 assert(manager
== &ipc_pthread_priority_manager
);