+void *
+thread_iokit_tls_get(uint32_t index)
+{
+ assert(index < THREAD_SAVE_IOKIT_TLS_COUNT);
+ return current_thread()->saved.iokit.tls[index];
+}
+
+void
+thread_iokit_tls_set(uint32_t index, void * data)
+{
+ assert(index < THREAD_SAVE_IOKIT_TLS_COUNT);
+ current_thread()->saved.iokit.tls[index] = data;
+}
+
+uint64_t
+thread_get_last_wait_duration(thread_t thread)
+{
+ return thread->last_made_runnable_time - thread->last_run_time;
+}
+
+integer_t
+thread_kern_get_pri(thread_t thr)
+{
+ return thr->base_pri;
+}
+
+void
+thread_kern_set_pri(thread_t thr, integer_t pri)
+{
+ sched_set_kernel_thread_priority(thr, pri);
+}
+
+integer_t
+thread_kern_get_kernel_maxpri(void)
+{
+ return MAXPRI_KERNEL;
+}
+/*
+ * thread_port_with_flavor_notify
+ *
+ * Called whenever the Mach port system detects no-senders on
+ * the thread inspect or read port. These ports are allocated lazily and
+ * should be deallocated here when there are no senders remaining.
+ */
+void
+thread_port_with_flavor_notify(mach_msg_header_t *msg)
+{
+ mach_no_senders_notification_t *notification = (void *)msg;
+ ipc_port_t port = notification->not_header.msgh_remote_port;
+ thread_t thread;
+ mach_thread_flavor_t flavor;
+ ipc_kobject_type_t kotype;
+
+ ip_lock(port);
+ if (port->ip_srights > 0) {
+ ip_unlock(port);
+ return;
+ }
+ thread = (thread_t)ipc_kobject_get(port);
+ kotype = ip_kotype(port);
+ if (thread != THREAD_NULL) {
+ assert((IKOT_THREAD_READ == kotype) || (IKOT_THREAD_INSPECT == kotype));
+ thread_reference_internal(thread);
+ }
+ ip_unlock(port);
+
+ if (thread == THREAD_NULL) {
+ /* The thread is exiting or disabled; it will eventually deallocate the port */
+ return;
+ }
+
+ if (kotype == IKOT_THREAD_READ) {
+ flavor = THREAD_FLAVOR_READ;
+ } else {
+ flavor = THREAD_FLAVOR_INSPECT;
+ }
+
+ thread_mtx_lock(thread);
+ ip_lock(port);
+ /*
+ * If the port is no longer active, then ipc_thread_terminate() ran
+ * and destroyed the kobject already. Just deallocate the task
+ * ref we took and go away.
+ *
+ * It is also possible that several nsrequests are in flight,
+ * only one shall NULL-out the port entry, and this is the one
+ * that gets to dealloc the port.
+ *
+ * Check for a stale no-senders notification. A call to any function
+ * that vends out send rights to this port could resurrect it between
+ * this notification being generated and actually being handled here.
+ */
+ if (!ip_active(port) ||
+ thread->ith_thread_ports[flavor] != port ||
+ port->ip_srights > 0) {
+ ip_unlock(port);
+ thread_mtx_unlock(thread);
+ thread_deallocate(thread);
+ return;
+ }
+
+ assert(thread->ith_thread_ports[flavor] == port);
+ thread->ith_thread_ports[flavor] = IP_NULL;
+ ipc_kobject_set_atomically(port, IKO_NULL, IKOT_NONE);
+ ip_unlock(port);
+ thread_mtx_unlock(thread);
+ thread_deallocate(thread);
+
+ ipc_port_dealloc_kernel(port);
+}
+
+/*
+ * The 'thread_region_page_shift' is used by footprint
+ * to specify the page size that it will use to
+ * accomplish its accounting work on the task being
+ * inspected. Since footprint uses a thread for each
+ * task that it works on, we need to keep the page_shift
+ * on a per-thread basis.
+ */
+
+int
+thread_self_region_page_shift(void)
+{
+ /*
+ * Return the page shift that this thread
+ * would like to use for its accounting work.
+ */
+ return current_thread()->thread_region_page_shift;
+}
+
+void
+thread_self_region_page_shift_set(
+ int pgshift)
+{
+ /*
+ * Set the page shift that this thread
+ * would like to use for its accounting work
+ * when dealing with a task.
+ */
+ current_thread()->thread_region_page_shift = pgshift;
+}
+