+/*
+ * Routine: ipc_get_pthpriority_from_kmsg_voucher
+ * Purpose:
+ * Get the canonicalized pthread priority from the voucher attached in the kmsg.
+ */
+kern_return_t
+ipc_get_pthpriority_from_kmsg_voucher(
+ ipc_kmsg_t kmsg,
+ ipc_pthread_priority_value_t *canonicalize_priority_value)
+{
+ ipc_voucher_t pthread_priority_voucher;
+ mach_voucher_attr_raw_recipe_size_t content_size =
+ sizeof(mach_voucher_attr_recipe_data_t) + sizeof(ipc_pthread_priority_value_t);
+ uint8_t content_data[content_size];
+ mach_voucher_attr_recipe_t cur_content;
+ kern_return_t kr = KERN_SUCCESS;
+
+ if (!IP_VALID(kmsg->ikm_voucher)) {
+ return KERN_FAILURE;
+ }
+
+ pthread_priority_voucher = (ipc_voucher_t)kmsg->ikm_voucher->ip_kobject;
+ kr = mach_voucher_extract_attr_recipe(pthread_priority_voucher,
+ MACH_VOUCHER_ATTR_KEY_PTHPRIORITY,
+ content_data,
+ &content_size);
+ if (kr != KERN_SUCCESS) {
+ return kr;
+ }
+
+ /* return KERN_INVALID_VALUE for default value */
+ if (content_size < sizeof(mach_voucher_attr_recipe_t)) {
+ return KERN_INVALID_VALUE;
+ }
+
+ cur_content = (mach_voucher_attr_recipe_t) (void *) &content_data[0];
+ assert(cur_content->content_size == sizeof(ipc_pthread_priority_value_t));
+ memcpy(canonicalize_priority_value, cur_content->content, sizeof(ipc_pthread_priority_value_t));
+
+ return KERN_SUCCESS;
+}
+
+