Loading...
/* * Copyright (c) 2025 Apple Inc. All rights reserved. * * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ * * This file contains Original Code and/or Modifications of Original Code * as defined in and that are subject to the Apple Public Source License * Version 2.0 (the 'License'). You may not use this file except in * compliance with the License. The rights granted to you under the License * may not be used to create, or enable the creation or redistribution of, * unlawful or unlicensed copies of an Apple operating system, or to * circumvent, violate, or enable the circumvention or violation of, any * terms of an Apple operating system software license agreement. * * Please obtain a copy of the License at * http://www.opensource.apple.com/apsl/ and read it before using this file. * * The Original Code and all software distributed under the License are * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. * Please see the License for the specific language governing rights and * limitations under the License. * * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ */ #ifndef _VM_STACKSHOT_UTILITIES_XNU_H_ #define _VM_STACKSHOT_UTILITIES_XNU_H_ #include <stdbool.h> #include <vm/vm_map_xnu.h> /*! * @file vm_stackshot_utilities.c * * @discussion * This module implements VM-related routines called from stackshot. * * It's meant to act as a bridge between VM and stackshot. */ #ifdef XNU_KERNEL_PRIVATE struct vm_map_lock_ctx; typedef struct vm_map_lock_ctx *vm_map_lock_ctx_t; __BEGIN_DECLS #define STACKSHOT_VMRL_MAX_OWNERS 512 #define STACKSHOT_VMRL_MAX_WAITERS 256 #define STACKSHOT_VMRL_MAX_BLOCKING_RELATIONSHIPS 256 /* Meant for use in stackshot to record vmrl owners, eventually helping us to get vmrl_rels */ typedef struct stackshot_thread_vmrl_owner_info { uint64_t owner_tid; vm_map_t map; vm_offset_t start; vm_offset_t end; uint32_t flags; } thread_vmrl_owner_info_t; typedef struct stackshot_thread_vmrl_waiter_info { uint64_t waiter_tid; vm_map_t map; uint64_t entry_hash; vm_offset_t start; vm_offset_t end; uint32_t flags; uint32_t num_blockers; } thread_vmrl_waiter_info_t; struct stackshot_vmrl_state { thread_vmrl_owner_info_t *owners; /* Info about threads that are owners of some vm range */ uint32_t _Atomic num_owners; thread_vmrl_waiter_info_t *waiters; /* Info about threads that are waiting for some vm range */ uint32_t _Atomic num_waiters; vmrl_blocking_relationship_t relationships[STACKSHOT_VMRL_MAX_BLOCKING_RELATIONSHIPS]; /* Each of these denotes a dependency, i.e. one thread waiting for another thread to unlock a vm range. This is what ends up in the stackshot buffer. */ uint32_t _Atomic exp_num_relationships; /* When going over all found waiters, we count how many other threads are owners og the entry they requested. This is the sum of all of these. */ }; void vmrl_stackshot_collect_intermediary_info( thread_t thread, struct stackshot_vmrl_state *state); /*! * This gets called outside the debugger trap. * Blockers' and waiters' data was collected under the stackshot debugger trap, * and now we can match waiters to their blockers based on that. */ uint32_t vmrl_stackshot_collect_final_blocking_rels( struct stackshot_vmrl_state *state); __END_DECLS #endif /* XNU_KERNEL_PRIVATE */ #endif /* _VM_STACKSHOT_UTILITIES_H_ */ |