1 | /* |
2 | * Copyright (c) 2019 Apple Inc. All rights reserved. |
3 | * |
4 | * @APPLE_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. Please obtain a copy of the License at |
10 | * http://www.opensource.apple.com/apsl/ and read it before using this |
11 | * file. |
12 | * |
13 | * The Original Code and all software distributed under the License are |
14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER |
15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, |
17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. |
18 | * Please see the License for the specific language governing rights and |
19 | * limitations under the License. |
20 | * |
21 | * @APPLE_LICENSE_HEADER_END@ |
22 | */ |
23 | |
24 | /* |
25 | * Purgeable spelling rules |
26 | * It is believed that the correct spelling is |
27 | * { 'p', 'u', 'r', 'g', 'e', 'a', 'b', 'l', 'e' }. |
28 | * However, there is one published API that likes to spell it without the |
29 | * first 'e', vm_purgable_control(). Since we can't change that API, |
30 | * here are the rules. |
31 | * All qualifiers defined in vm_purgable.h are spelled without the e. |
32 | * All other qualifiers are spelled with the e. |
33 | * Right now, there are remains of the wrong spelling throughout the code, |
34 | * vm_object_t.purgable for example. We expect to change these on occasion. |
35 | */ |
36 | |
37 | #ifndef __VM_PURGEABLE_INTERNAL__ |
38 | #define __VM_PURGEABLE_INTERNAL__ |
39 | |
40 | #include <kern/queue.h> |
41 | |
42 | enum purgeable_q_type { |
43 | PURGEABLE_Q_TYPE_OBSOLETE, |
44 | PURGEABLE_Q_TYPE_FIFO, |
45 | PURGEABLE_Q_TYPE_LIFO, |
46 | PURGEABLE_Q_TYPE_MAX |
47 | }; |
48 | |
49 | typedef uint32_t token_idx_t; |
50 | typedef uint32_t token_cnt_t; |
51 | #define TOKEN_COUNT_MAX UINT32_MAX |
52 | |
53 | #define NUM_VOLATILE_GROUPS 8 |
54 | struct purgeable_q { |
55 | token_idx_t token_q_head; /* first token */ |
56 | token_idx_t token_q_tail; /* last token */ |
57 | token_idx_t token_q_unripe; /* first token which is not ripe */ |
58 | int32_t new_pages; |
59 | queue_head_t objq[NUM_VOLATILE_GROUPS]; |
60 | enum purgeable_q_type type; |
61 | #if MACH_ASSERT |
62 | int debug_count_tokens; |
63 | int debug_count_objects; |
64 | #endif |
65 | }; |
66 | |
67 | typedef struct purgeable_q * purgeable_q_t; |
68 | |
69 | extern struct purgeable_q purgeable_queues[PURGEABLE_Q_TYPE_MAX]; |
70 | extern queue_head_t purgeable_nonvolatile_queue; |
71 | extern int purgeable_nonvolatile_count; |
72 | extern int32_t token_new_pagecount; |
73 | #define TOKEN_NEW_PAGECOUNT_MAX INT32_MAX |
74 | extern int available_for_purge; |
75 | |
76 | |
77 | /* |
78 | * Locking: |
79 | * the token counters are protected by the vm_page_queue_lock, since they're |
80 | * mostly used in that context and we don't want to do a lot of extra locking |
81 | * the purgeable page queues are protected by a separate lock since they're |
82 | * mostly used on a user context and we don't want any contention with the |
83 | * pageout daemon. |
84 | */ |
85 | decl_lck_mtx_data(extern, vm_purgeable_queue_lock); |
86 | |
87 | /* add a new token to queue. called by vm_object_purgeable_control */ |
88 | /* enter with page queue locked */ |
89 | kern_return_t vm_purgeable_token_add(purgeable_q_t queue); |
90 | |
91 | /* enter with page queue locked */ |
92 | void vm_purgeable_token_delete_first(purgeable_q_t queue); |
93 | void vm_purgeable_token_delete_last(purgeable_q_t queue); |
94 | |
95 | /* |
96 | * decrement token counters. |
97 | * enter with page queue locked |
98 | */ |
99 | void vm_purgeable_q_advance_all(void); |
100 | |
101 | /* the object purger. purges the next eligible object from memory. */ |
102 | /* returns TRUE if an object was purged, otherwise FALSE. */ |
103 | boolean_t vm_purgeable_object_purge_one(int force_purge_below_group, int flags); |
104 | |
105 | /* purge all volatile objects now */ |
106 | void vm_purgeable_object_purge_all(void); |
107 | |
108 | /* insert purgeable object into queue */ |
109 | void vm_purgeable_object_add(vm_object_t object, purgeable_q_t queue, int group); |
110 | |
111 | /* look for object. If found, remove from purgeable queue. */ |
112 | purgeable_q_t vm_purgeable_object_remove(vm_object_t object); |
113 | |
114 | /* statistics for purgable objects in all queues */ |
115 | void vm_purgeable_stats(vm_purgeable_info_t info, task_t target_task); |
116 | |
117 | #if DEVELOPMENT || DEBUG |
118 | /* statistics for purgeable object usage in all queues for a task */ |
119 | kern_return_t vm_purgeable_account(task_t task, pvm_account_info_t acnt_info); |
120 | #endif /* DEVELOPMENT || DEBUG */ |
121 | |
122 | uint64_t vm_purgeable_purge_task_owned(task_t task); |
123 | void vm_purgeable_nonvolatile_enqueue(vm_object_t object, task_t task); |
124 | void vm_purgeable_nonvolatile_dequeue(vm_object_t object); |
125 | void vm_purgeable_accounting(vm_object_t object, |
126 | vm_purgable_t old_state); |
127 | void vm_object_owner_compressed_update(vm_object_t object, |
128 | int delta); |
129 | |
130 | #define PURGEABLE_LOOP_MAX 64 |
131 | |
132 | #define TOKEN_ADD 0x40 /* 0x100 */ |
133 | #define TOKEN_DELETE 0x41 /* 0x104 */ |
134 | #define TOKEN_RIPEN 0x42 /* 0x108 */ |
135 | #define OBJECT_ADD 0x48 /* 0x120 */ |
136 | #define OBJECT_REMOVE 0x49 /* 0x124 */ |
137 | #define OBJECT_PURGE 0x4a /* 0x128 */ |
138 | #define OBJECT_PURGE_ALL 0x4b /* 0x12c */ |
139 | #define OBJECT_PURGE_ONE 0x4c /* 0x12d */ |
140 | #define OBJECT_PURGE_LOOP 0x4e /* 0x12e */ |
141 | |
142 | #endif /* __VM_PURGEABLE_INTERNAL__ */ |
143 | |