1/* 2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 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. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 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. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28 29#ifndef _DTRACE_PTSS_H_ 30#define _DTRACE_PTSS_H_ 31 32#ifdef __cplusplus 33extern "C" { 34#endif 35 36/* 37 * The pid provider needs a small per thread scratch space, 38 * in the address space of the user task. This code is used to 39 * manage that space. 40 * 41 * High level design: 42 * 43 * To avoid serialization, this is a (mostly) lockless allocator. If 44 * a new page has to be allocated, the process's sprlock will be acquired. 45 * 46 * NOTE: The dtrace copyin/copyout code is still the shared code that 47 * can handle unmapped pages, so the scratch space isn't wired for now. 48 * * Each page in user space is wired. It cannot be paged out, because 49 * * dtrace's copyin/copyout is only guaranteed to handle pages already 50 * * in memory. 51 * 52 * Each page in user space is represented by a dt_ptss_page. Page entries 53 * are chained. Once allocated, a page is not freed until dtrace "cleans up" 54 * that process. 55 * 56 * Clean up works like this: 57 * 58 * At process exit, free all kernel allocated memory, but ignore user pages. 59 * At process exec, free all kernel allocated memory, but ignore user pages. 60 * At process fork, free user pages copied from parent, and do not allocate kernel memory. 61 * 62 * This is making the assumption that it is faster to let the bulk vm_map 63 * operations in exec/exit do their work, instead of explicit page free(s) 64 * via mach_vm_deallocate. 65 * 66 * As each page is allocated, its entries are chained and added to the 67 * free_list. To claim an entry, cas it off the list. When a thread exits, 68 * cas its entry onto the list. We could potentially optimize this by 69 * keeping a head/tail, and cas'ing the frees to the tail instead of the 70 * head. Without evidence to support such a need, it seems better to keep 71 * things simple for now. 72 */ 73 74 75 76#define DTRACE_PTSS_SCRATCH_SPACE_PER_THREAD (64) 77 78#define DTRACE_PTSS_ENTRIES_PER_PAGE (PAGE_SIZE / DTRACE_PTSS_SCRATCH_SPACE_PER_THREAD) 79 80struct dtrace_ptss_page_entry { 81 struct dtrace_ptss_page_entry* next; 82 user_addr_t addr; 83}; 84 85struct dtrace_ptss_page { 86 struct dtrace_ptss_page* next; 87 struct dtrace_ptss_page_entry entries[PAGE_MAX_SIZE / DTRACE_PTSS_SCRATCH_SPACE_PER_THREAD]; 88}; 89 90struct dtrace_ptss_page_entry* dtrace_ptss_claim_entry(struct proc* p); /* sprlock not held */ 91struct dtrace_ptss_page_entry* dtrace_ptss_claim_entry_locked(struct proc* p); /* sprlock held */ 92void dtrace_ptss_release_entry(struct proc* p, struct dtrace_ptss_page_entry* e); 93 94struct dtrace_ptss_page* dtrace_ptss_allocate_page(struct proc* p); 95void dtrace_ptss_free_page(struct proc* p, struct dtrace_ptss_page* ptss_page); 96 97void dtrace_ptss_enable(struct proc* p); 98void dtrace_ptss_exec_exit(struct proc* p); 99void dtrace_ptss_fork(struct proc* parent, struct proc* child); 100 101#ifdef __cplusplus 102} 103#endif 104 105#endif /* _DTRACE_PTSS_H_ */ 106 107