xref: /xnu-8020.121.3/osfmk/ipc/ipc_importance.h (revision fdd8201d7b966f0c3ea610489d29bd841d358941)
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 <mach/mach_types.h>
32 #include <mach/mach_voucher_types.h>
33 #include <mach/boolean.h>
34 #include <ipc/ipc_types.h>
35 #include <ipc/ipc_voucher.h>
36 
37 /*
38  * IPC Importance - All definitions are MACH_KERNEL_PRIVATE
39  */
40 #ifdef MACH_KERNEL_PRIVATE
41 
42 #include <kern/locks.h>
43 #include <kern/simple_lock.h>
44 
45 /*
46  * IPC Importance Value Element
47  *
48  * This element represents a single task's (base) importance,
49  * or in the case of inherited importance, the inheritance
50  * linkage from the source to the destination task.  In the
51  * inheritance case, this source can be a base importance or
52  * another inherited importace.
53  *
54  * Whenever the task importance is adjusted, it walks the
55  * list of IPC-related items it influences (ports and downstream
56  * tasks doing work on its behalf) and makes adjustments to
57  * their importance attributes accordingly.
58  *
59  */
60 
61 struct ipc_importance_elem {
62 	uint32_t                                iie_bits;       /* type and refs */
63 	mach_voucher_attr_value_reference_t     iie_made;       /* references given to vouchers */
64 	queue_head_t                            iie_kmsgs;      /* list of kmsgs inheriting from this */
65 	uint32_t                                iie_externcnt;  /* number of externalized boosts */
66 	uint32_t                                iie_externdrop; /* number of those dropped already */
67 #define IIE_REF_DEBUG 0
68 #if IIE_REF_DEBUG
69 	uint32_t iie_refs_added;                        /* all refs added via all means */
70 	uint32_t iie_refs_dropped;                      /* all refs dropped via all means */
71 	uint32_t iie_kmsg_refs_added;                   /* all refs added by kmsgs taking a ref */
72 	uint32_t iie_kmsg_refs_inherited;               /* kmsg refs consumed by a new inherit */
73 	uint32_t iie_kmsg_refs_coalesced;               /* kmsg refs coalesced into an existing inherit */
74 	uint32_t iie_kmsg_refs_dropped;                 /* kmsg refs dropped by not accepting msg importance */
75 	uint32_t iie_task_refs_added;                   /* refs added by a task reference call */
76 	uint32_t iie_task_refs_added_inherit_from;      /* task references added by inherit from */
77 	uint32_t iie_task_refs_added_transition;        /* task references added by imp transition code */
78 	uint32_t iie_task_refs_self_added;              /* task refs added by self-boost */
79 	uint32_t iie_task_refs_inherited;               /* task refs consumed by a new inherit */
80 	uint32_t iie_task_refs_coalesced;               /* task refs coalesced into an existing inherit */
81 	uint32_t iie_task_refs_dropped;                 /* all refs dropped via all task means */
82 #endif
83 };
84 
85 #define IIE_TYPE_MASK           0x80000000      /* Just the high bit for now */
86 #define IIE_TYPE_TASK           0x00000000      /* Element is a task element */
87 #define IIE_TYPE_INHERIT        0x80000000      /* Element inherits from a previous element */
88 #define IIE_TYPE(e)             ((e)->iie_bits & IIE_TYPE_MASK)
89 
90 #define IIE_REFS_MASK           0x7FFFFFFF      /* Mask to extract references */
91 #define IIE_REFS_MAX            0x7FFFFFFF
92 #define IIE_REFS(e)             ((e)->iie_bits & IIE_REFS_MASK)
93 
94 #define IIE_EXTERN(e)           ((e)->iie_externcnt - (e)->iie_externdrop)
95 
96 #if !IIE_REF_DEBUG
97 #define ipc_importance_reference_internal(elem)         \
98 	(os_atomic_inc(&(elem)->iie_bits, relaxed) & IIE_REFS_MASK)
99 
100 #define ipc_importance_release_internal(elem)           \
101 	(os_atomic_dec(&(elem)->iie_bits, relaxed) & IIE_REFS_MASK)
102 #endif
103 
104 struct ipc_importance_task {
105 	struct ipc_importance_elem iit_elem;    /* common element parts */
106 	task_t                  iit_task;       /* task associated with */
107 	queue_head_t            iit_inherits;   /* list of inherit elems hung off this */
108 	queue_t                 iit_updateq;    /* queue chained on for task policy updates */
109 	queue_chain_t           iit_updates;    /* link on update chain */
110 	queue_chain_t           iit_props;      /* link on propagation chain */
111 	uint64_t                iit_updatetime; /* timestamp of our last policy update request */
112 	uint64_t                iit_transitions;/* total number of boost transitions (lifetime) */
113 	uint32_t                iit_assertcnt;  /* net number of boost assertions (internal, external and legacy) */
114 	uint32_t                iit_legacy_externcnt;  /* Legacy external boost count */
115 	uint32_t                iit_legacy_externdrop; /* Legacy external boost drop count */
116 	uint32_t                iit_receiver:1, /* the task can receive importance boost */
117 	    iit_denap:1,                        /* the task can be awaked from App Nap */
118 	    iit_donor:1,                        /* the task always sends boosts regardless of boost status */
119 	    iit_live_donor:1,                          /* the task temporarily sends boosts regardless of boost status */
120 	    iit_updatepolicy:1,                        /* enqueue for policy update at the end of propagation */
121 	    iit_reserved:3,                            /* reserved for future use */
122 	    iit_filelocks:24;                          /* number of file lock boosts */
123 #if DEVELOPMENT || DEBUG
124 	char                    iit_procname[20];      /* name of proc */
125 	uint32_t                iit_bsd_pid;           /* pid of proc creating this iit */
126 	queue_chain_t           iit_allocation;        /* link on global iit allocation chain */
127 #endif
128 };
129 #define iit_bits                iit_elem.iie_bits
130 #define iit_made                iit_elem.iie_made
131 #define iit_kmsgs               iit_elem.iie_kmsgs
132 #define iit_externcnt           iit_elem.iie_externcnt
133 #define iit_externdrop          iit_elem.iie_externdrop
134 
135 #define IIT_REFS_MAX            IIE_REFS_MAX
136 #define IIT_REFS(t)             IIE_REFS(&(t)->iit_elem)
137 #define IIT_EXTERN(t)           IIE_EXTERN(&(t)->iit_elem)
138 #define IIT_LEGACY_EXTERN(t)    ((t)->iit_legacy_externcnt - (t)->iit_legacy_externdrop)
139 
140 #if !IIE_REF_DEBUG
141 #define ipc_importance_task_reference_internal(task_imp)        \
142 	(ipc_importance_reference_internal(&(task_imp)->iit_elem))
143 
144 #define ipc_importance_task_release_internal(task_imp)          \
145 	(assert(1 < IIT_REFS(task_imp)), ipc_importance_release_internal(&(task_imp)->iit_elem))
146 #endif
147 
148 typedef int iit_update_type_t;
149 #define IIT_UPDATE_HOLD                 ((iit_update_type_t)1)
150 #define IIT_UPDATE_DROP                 ((iit_update_type_t)2)
151 
152 struct ipc_importance_inherit {
153 	struct ipc_importance_elem      iii_elem;         /* common element partss */
154 	boolean_t                       iii_donating;     /* is this donating importance */
155 	uint32_t                        iii_depth;        /* nesting depth */
156 	ipc_importance_task_t           iii_to_task;      /* donating to */
157 	ipc_importance_elem_t           iii_from_elem;    /* other elem contributing */
158 	queue_chain_t                   iii_inheritance;  /* inherited from link */
159 };
160 #define iii_bits                        iii_elem.iie_bits
161 #define iii_made                        iii_elem.iie_made
162 #define iii_kmsgs                       iii_elem.iie_kmsgs
163 #define iii_externcnt                   iii_elem.iie_externcnt
164 #define iii_externdrop                  iii_elem.iie_externdrop
165 #define III_REFS_MAX                    IIE_REFS_MAX
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 /* initialize the ipc importance subsystem */
249 extern void ipc_importance_init(void);
250 
251 #if DEVELOPMENT || DEBUG
252 extern void task_importance_update_owner_info(task_t task);
253 #endif
254 
255 #if XNU_KERNEL_PRIVATE
256 #define TASK_IMP_LIST_DONATING_PIDS  0x1
257 extern int task_importance_list_pids(task_t task, int flags, char *pid_list, unsigned int max_count);
258 #endif
259 
260 __END_DECLS
261 
262 #endif /* MACH_KERNEL_PRIVATE */
263 
264 #endif  /* _IPC_IPC_IMPORTANCE_H_ */
265