xref: /xnu-10002.81.5/osfmk/ipc/ipc_importance.h (revision 5e3eaea39dcf651e66cb99ba7d70e32cc4a99587)
1 /*
2  * Copyright (c) 2013 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 #ifndef _IPC_IPC_IMPORTANCE_H_
29 #define _IPC_IPC_IMPORTANCE_H_
30 
31 #include <os/refcnt.h>
32 #include <mach/mach_types.h>
33 #include <mach/mach_voucher_types.h>
34 #include <mach/boolean.h>
35 #include <ipc/ipc_types.h>
36 #include <ipc/ipc_voucher.h>
37 
38 /*
39  * IPC Importance - All definitions are MACH_KERNEL_PRIVATE
40  */
41 #ifdef MACH_KERNEL_PRIVATE
42 
43 #include <kern/locks.h>
44 #include <kern/simple_lock.h>
45 
46 /*
47  * IPC Importance Value Element
48  *
49  * This element represents a single task's (base) importance,
50  * or in the case of inherited importance, the inheritance
51  * linkage from the source to the destination task.  In the
52  * inheritance case, this source can be a base importance or
53  * another inherited importace.
54  *
55  * Whenever the task importance is adjusted, it walks the
56  * list of IPC-related items it influences (ports and downstream
57  * tasks doing work on its behalf) and makes adjustments to
58  * their importance attributes accordingly.
59  *
60  */
61 
62 struct ipc_importance_elem {
63 	os_ref_atomic_t                         iie_bits;       /* type and refs */
64 	mach_voucher_attr_value_reference_t     iie_made;       /* references given to vouchers */
65 	queue_head_t                            iie_kmsgs;      /* list of kmsgs inheriting from this */
66 	uint32_t                                iie_externcnt;  /* number of externalized boosts */
67 	uint32_t                                iie_externdrop; /* number of those dropped already */
68 #define IIE_REF_DEBUG 0
69 #if IIE_REF_DEBUG
70 	uint32_t iie_refs_added;                        /* all refs added via all means */
71 	uint32_t iie_refs_dropped;                      /* all refs dropped via all means */
72 	uint32_t iie_kmsg_refs_added;                   /* all refs added by kmsgs taking a ref */
73 	uint32_t iie_kmsg_refs_inherited;               /* kmsg refs consumed by a new inherit */
74 	uint32_t iie_kmsg_refs_coalesced;               /* kmsg refs coalesced into an existing inherit */
75 	uint32_t iie_kmsg_refs_dropped;                 /* kmsg refs dropped by not accepting msg importance */
76 	uint32_t iie_task_refs_added;                   /* refs added by a task reference call */
77 	uint32_t iie_task_refs_added_inherit_from;      /* task references added by inherit from */
78 	uint32_t iie_task_refs_added_transition;        /* task references added by imp transition code */
79 	uint32_t iie_task_refs_self_added;              /* task refs added by self-boost */
80 	uint32_t iie_task_refs_inherited;               /* task refs consumed by a new inherit */
81 	uint32_t iie_task_refs_coalesced;               /* task refs coalesced into an existing inherit */
82 	uint32_t iie_task_refs_dropped;                 /* all refs dropped via all task means */
83 #endif
84 };
85 
86 os_refgrp_decl(static, iie_refgrp, "IIERefGroup", NULL);
87 
88 #define IIE_TYPE_BITS           1               /* Just the low bit for now */
89 #define IIE_TYPE_MASK           ((1u << IIE_TYPE_BITS) - 1)
90 
91 #define IIE_TYPE_TASK           0x00000000      /* Element is a task element */
92 #define IIE_TYPE_INHERIT        0x00000001      /* Element inherits from a previous element */
93 #define IIE_TYPE(e)             (os_atomic_load(&(e)->iie_bits, relaxed) & IIE_TYPE_MASK)
94 #define IIE_REFS(e)             (os_ref_get_count_mask(&(e)->iie_bits, IIE_TYPE_BITS))
95 
96 #define IIE_EXTERN(e)           ((e)->iie_externcnt - (e)->iie_externdrop)
97 
98 #if !IIE_REF_DEBUG
99 #define ipc_importance_reference_internal(elem)         \
100 	os_ref_retain_mask(&(elem)->iie_bits, IIE_TYPE_BITS, &iie_refgrp)
101 
102 #define ipc_importance_release_internal(elem)           \
103 	os_ref_release_relaxed_mask(&(elem)->iie_bits, IIE_TYPE_BITS, &iie_refgrp)
104 #endif
105 
106 struct ipc_importance_task {
107 	struct ipc_importance_elem iit_elem;    /* common element parts */
108 	task_t                  iit_task;       /* task associated with */
109 	queue_head_t            iit_inherits;   /* list of inherit elems hung off this */
110 	queue_t                 iit_updateq;    /* queue chained on for task policy updates */
111 	queue_chain_t           iit_updates;    /* link on update chain */
112 	queue_chain_t           iit_props;      /* link on propagation chain */
113 	uint64_t                iit_updatetime; /* timestamp of our last policy update request */
114 	uint64_t                iit_transitions;/* total number of boost transitions (lifetime) */
115 	uint32_t                iit_assertcnt;  /* net number of boost assertions (internal, external and legacy) */
116 	uint32_t                iit_legacy_externcnt;  /* Legacy external boost count */
117 	uint32_t                iit_legacy_externdrop; /* Legacy external boost drop count */
118 	uint32_t                iit_receiver:1, /* the task can receive importance boost */
119 	    iit_denap:1,                        /* the task can be awaked from App Nap */
120 	    iit_donor:1,                        /* the task always sends boosts regardless of boost status */
121 	    iit_live_donor:1,                          /* the task temporarily sends boosts regardless of boost status */
122 	    iit_updatepolicy:1,                        /* enqueue for policy update at the end of propagation */
123 	    iit_reserved:3,                            /* reserved for future use */
124 	    iit_filelocks:24;                          /* number of file lock boosts */
125 #if DEVELOPMENT || DEBUG
126 	char                    iit_procname[20];      /* name of proc */
127 	uint32_t                iit_bsd_pid;           /* pid of proc creating this iit */
128 	queue_chain_t           iit_allocation;        /* link on global iit allocation chain */
129 #endif
130 };
131 #define iit_bits                iit_elem.iie_bits
132 #define iit_made                iit_elem.iie_made
133 #define iit_kmsgs               iit_elem.iie_kmsgs
134 #define iit_externcnt           iit_elem.iie_externcnt
135 #define iit_externdrop          iit_elem.iie_externdrop
136 
137 #define IIT_REFS(t)             IIE_REFS(&(t)->iit_elem)
138 #define IIT_EXTERN(t)           IIE_EXTERN(&(t)->iit_elem)
139 #define IIT_LEGACY_EXTERN(t)    ((t)->iit_legacy_externcnt - (t)->iit_legacy_externdrop)
140 
141 #if !IIE_REF_DEBUG
142 #define ipc_importance_task_reference_internal(task_imp)        \
143 	(ipc_importance_reference_internal(&(task_imp)->iit_elem))
144 
145 #define ipc_importance_task_release_internal(task_imp)          \
146 	(assert(1 < IIT_REFS(task_imp)), ipc_importance_release_internal(&(task_imp)->iit_elem))
147 #endif
148 
149 typedef int iit_update_type_t;
150 #define IIT_UPDATE_HOLD                 ((iit_update_type_t)1)
151 #define IIT_UPDATE_DROP                 ((iit_update_type_t)2)
152 
153 struct ipc_importance_inherit {
154 	struct ipc_importance_elem      iii_elem;         /* common element partss */
155 	boolean_t                       iii_donating;     /* is this donating importance */
156 	uint32_t                        iii_depth;        /* nesting depth */
157 	ipc_importance_task_t           iii_to_task;      /* donating to */
158 	ipc_importance_elem_t           iii_from_elem;    /* other elem contributing */
159 	queue_chain_t                   iii_inheritance;  /* inherited from link */
160 };
161 #define iii_bits                        iii_elem.iie_bits
162 #define iii_made                        iii_elem.iie_made
163 #define iii_kmsgs                       iii_elem.iie_kmsgs
164 #define iii_externcnt                   iii_elem.iie_externcnt
165 #define iii_externdrop                  iii_elem.iie_externdrop
166 #define III_REFS(i)                     IIE_REFS(&(i)->iii_elem)
167 #define III_EXTERN(i)                   IIE_EXTERN(&(i)->iii_elem)
168 
169 #define III_DEPTH_RESET                 0x80000000
170 #define III_DEPTH_MASK                  0x000000FF
171 #define III_DEPTH(i)                    ((i)->iii_depth & III_DEPTH_MASK)
172 #define III_DEPTH_MAX                   32      /* maximum inherit->inherit chain depth */
173 
174 #define ipc_importance_inherit_reference_internal(inherit)      \
175 	(ipc_importance_reference_internal(&(inherit)->iii_elem))
176 
177 __BEGIN_DECLS
178 
179 /* add a reference to an importance attribute */
180 extern void ipc_importance_reference(ipc_importance_elem_t elem);
181 
182 /* release an importance attribute reference */
183 extern void ipc_importance_release(ipc_importance_elem_t elem);
184 
185 /* retain a task importance attribute reference */
186 extern void ipc_importance_task_reference(ipc_importance_task_t task_elem);
187 
188 /* release a task importance attribute reference */
189 extern void ipc_importance_task_release(ipc_importance_task_t task_imp);
190 
191 /* reset the influence of the task on the importance */
192 extern void ipc_importance_reset(ipc_importance_task_t task_imp, boolean_t donor);
193 
194 extern ipc_importance_task_t ipc_importance_for_task(task_t task, boolean_t made);
195 extern void ipc_importance_disconnect_task(task_t task);
196 extern ipc_importance_inherit_t ipc_importance_exec_switch_task(task_t old_task, task_t new_task);
197 
198 extern boolean_t ipc_importance_task_is_donor(ipc_importance_task_t task_imp);
199 extern boolean_t ipc_importance_task_is_never_donor(ipc_importance_task_t task_imp);
200 extern boolean_t ipc_importance_task_is_marked_donor(ipc_importance_task_t task_imp);
201 extern boolean_t ipc_importance_task_is_marked_live_donor(ipc_importance_task_t task_imp);
202 
203 extern void ipc_importance_task_mark_donor(ipc_importance_task_t task_imp, boolean_t donating);
204 extern void ipc_importance_task_mark_live_donor(ipc_importance_task_t task_imp, boolean_t live_donating);
205 extern void ipc_importance_task_update_live_donor(ipc_importance_task_t task_imp);
206 
207 extern boolean_t ipc_importance_task_is_marked_receiver(ipc_importance_task_t task_imp);
208 extern void ipc_importance_task_mark_receiver(ipc_importance_task_t task_imp, boolean_t receiving);
209 
210 extern boolean_t ipc_importance_task_is_denap_receiver(ipc_importance_task_t task_imp);
211 extern boolean_t ipc_importance_task_is_marked_denap_receiver(ipc_importance_task_t task_imp);
212 extern void ipc_importance_task_mark_denap_receiver(ipc_importance_task_t task_imp, boolean_t receiving);
213 
214 extern boolean_t ipc_importance_task_is_any_receiver_type(ipc_importance_task_t task_imp);
215 
216 extern kern_return_t ipc_importance_task_hold_internal_assertion(ipc_importance_task_t task_imp, uint32_t count);
217 extern kern_return_t ipc_importance_task_drop_internal_assertion(ipc_importance_task_t task_imp, uint32_t count);
218 
219 extern kern_return_t ipc_importance_task_hold_file_lock_assertion(ipc_importance_task_t task_imp, uint32_t count);
220 extern kern_return_t ipc_importance_task_drop_file_lock_assertion(ipc_importance_task_t task_imp, uint32_t count);
221 
222 extern kern_return_t ipc_importance_task_hold_legacy_external_assertion(ipc_importance_task_t task_imp, uint32_t count);
223 extern kern_return_t ipc_importance_task_drop_legacy_external_assertion(ipc_importance_task_t task_imp, uint32_t count);
224 
225 extern boolean_t ipc_importance_check_circularity(ipc_port_t port, ipc_port_t dest);
226 
227 /* prepare importance attributes for sending */
228 extern boolean_t ipc_importance_send(
229 	ipc_kmsg_t              kmsg,
230 	mach_msg_option_t       option);
231 
232 /* receive importance attributes from message */
233 extern void ipc_importance_receive(
234 	ipc_kmsg_t              kmsg,
235 	mach_msg_option_t       option);
236 
237 /* undo receive of importance attributes from message */
238 extern void ipc_importance_unreceive(
239 	ipc_kmsg_t              kmsg,
240 	mach_msg_option_t       option);
241 
242 /* clean importance attributes out of destroyed message */
243 extern void ipc_importance_clean(ipc_kmsg_t kmsg);
244 
245 /* assert a message is clean w.r.t. importance attributes */
246 extern void ipc_importance_assert_clean(ipc_kmsg_t kmsg);
247 
248 #if DEVELOPMENT || DEBUG
249 extern void task_importance_update_owner_info(task_t task);
250 #endif
251 
252 #if XNU_KERNEL_PRIVATE
253 #define TASK_IMP_LIST_DONATING_PIDS  0x1
254 extern int task_importance_list_pids(task_t task, int flags, char *pid_list, unsigned int max_count);
255 #endif
256 
257 __END_DECLS
258 
259 #endif /* MACH_KERNEL_PRIVATE */
260 
261 #endif  /* _IPC_IPC_IMPORTANCE_H_ */
262