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 #include <vm/vm_purgeable_xnu.h>
42 
43 enum purgeable_q_type {
44 	PURGEABLE_Q_TYPE_OBSOLETE,
45 	PURGEABLE_Q_TYPE_FIFO,
46 	PURGEABLE_Q_TYPE_LIFO,
47 	PURGEABLE_Q_TYPE_MAX
48 };
49 
50 typedef uint32_t token_idx_t;
51 typedef uint32_t token_cnt_t;
52 #define TOKEN_COUNT_MAX UINT32_MAX
53 
54 #define NUM_VOLATILE_GROUPS 8
55 struct purgeable_q {
56 	token_idx_t token_q_head;    /* first token */
57 	token_idx_t token_q_tail;    /* last token  */
58 	token_idx_t token_q_unripe;  /* first token which is not ripe */
59 	int32_t new_pages;
60 	queue_head_t objq[NUM_VOLATILE_GROUPS];
61 	enum purgeable_q_type type;
62 #if MACH_ASSERT
63 	int debug_count_tokens;
64 	int debug_count_objects;
65 #endif
66 };
67 
68 typedef struct purgeable_q * purgeable_q_t;
69 
70 extern struct purgeable_q purgeable_queues[PURGEABLE_Q_TYPE_MAX];
71 extern queue_head_t purgeable_nonvolatile_queue;
72 extern int purgeable_nonvolatile_count;
73 extern int32_t token_new_pagecount;
74 #define TOKEN_NEW_PAGECOUNT_MAX INT32_MAX
75 extern int available_for_purge;
76 
77 
78 /*
79  * Locking:
80  * the token counters are protected by the vm_page_queue_lock, since they're
81  * mostly used in that context and we don't want to do a lot of extra locking
82  * the purgeable page queues are protected by a separate lock since they're
83  * mostly used on a user context and we don't want any contention with the
84  * pageout daemon.
85  */
86 decl_lck_mtx_data(extern, vm_purgeable_queue_lock);
87 
88 /* add a new token to queue. called by vm_object_purgeable_control */
89 /* enter with page queue locked */
90 kern_return_t vm_purgeable_token_add(purgeable_q_t queue);
91 
92 /* enter with page queue locked */
93 void vm_purgeable_token_delete_first(purgeable_q_t queue);
94 void vm_purgeable_token_delete_last(purgeable_q_t queue);
95 
96 /*
97  * decrement token counters.
98  * enter with page queue locked
99  */
100 void vm_purgeable_q_advance_all(void);
101 
102 /* purge all volatile objects now */
103 void vm_purgeable_object_purge_all(void);
104 
105 /* insert purgeable object into queue */
106 void vm_purgeable_object_add(vm_object_t object, purgeable_q_t queue, int group);
107 
108 /* look for object. If found, remove from purgeable queue. */
109 purgeable_q_t vm_purgeable_object_remove(vm_object_t object);
110 
111 void vm_purgeable_nonvolatile_enqueue(vm_object_t object, task_t task);
112 void vm_purgeable_nonvolatile_dequeue(vm_object_t object);
113 void vm_purgeable_accounting(vm_object_t        object,
114     vm_purgable_t      old_state);
115 void vm_object_owner_compressed_update(vm_object_t      object,
116     int              delta);
117 
118 #define PURGEABLE_LOOP_MAX 64
119 
120 #endif /* __VM_PURGEABLE_INTERNAL__ */
121