master
1/*
2 * Copyright (c) 2020 Apple Inc. All rights reserved.
3 *
4 * @APPLE_APACHE_LICENSE_HEADER_START@
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 *
18 * @APPLE_APACHE_LICENSE_HEADER_END@
19 */
20
21#ifndef __OS_WORKGROUP_OBJECT__
22#define __OS_WORKGROUP_OBJECT__
23
24#ifndef __OS_WORKGROUP_INDIRECT__
25#error "Please #include <os/workgroup.h> instead of this file directly."
26#include <os/workgroup_base.h> // For header doc
27#endif
28
29__BEGIN_DECLS
30
31OS_WORKGROUP_ASSUME_NONNULL_BEGIN
32OS_WORKGROUP_ASSUME_ABI_SINGLE_BEGIN
33
34/*!
35 * @typedef os_workgroup_t
36 *
37 * @abstract
38 * A reference counted os object representing a workload that needs to
39 * be distinctly recognized and tracked by the system. The workgroup
40 * tracks a collection of threads all working cooperatively. An os_workgroup
41 * object - when not an instance of a specific os_workgroup_t subclass -
42 * represents a generic workload and makes no assumptions about the kind of
43 * work done.
44 *
45 * @discussion
46 * Threads can explicitly join an os_workgroup_t to mark themselves as
47 * participants in the workload.
48 */
49OS_WORKGROUP_DECL(os_workgroup, WorkGroup);
50
51
52/* Attribute creation and specification */
53
54/*!
55 * @typedef os_workgroup_attr_t
56 *
57 * @abstract
58 * Pointer to an opaque structure for describing attributes that can be
59 * configured on a workgroup at creation.
60 */
61typedef struct os_workgroup_attr_opaque_s os_workgroup_attr_s;
62typedef struct os_workgroup_attr_opaque_s *os_workgroup_attr_t;
63
64/* os_workgroup_t attributes need to be initialized before use. This initializer
65 * allows you to create a workgroup with the system default attributes. */
66#define OS_WORKGROUP_ATTR_INITIALIZER_DEFAULT \
67 { .sig = _OS_WORKGROUP_ATTR_SIG_DEFAULT_INIT }
68
69
70
71/* The main use of the workgroup API is through instantiations of the concrete
72 * subclasses - please refer to os/workgroup_interval.h and
73 * os/workgroup_parallel.h for more information on creating workgroups.
74 *
75 * The functions below operate on all subclasses of os_workgroup_t.
76 */
77
78/*!
79 * @function os_workgroup_copy_port
80 *
81 * @abstract
82 * Returns a reference to a send right representing this workgroup that is to be
83 * sent to other processes. This port is to be passed to
84 * os_workgroup_create_with_port() to create a workgroup object.
85 *
86 * It is the client's responsibility to release the send right reference.
87 *
88 * If an error is encountered, errno is set and returned.
89 */
90API_AVAILABLE(macos(11.0))
91API_UNAVAILABLE(ios, tvos, watchos)
92OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
93int
94os_workgroup_copy_port(os_workgroup_t wg, mach_port_t *mach_port_out);
95
96/*!
97 * @function os_workgroup_create_with_port
98 *
99 * @abstract
100 * Create an os_workgroup_t object from a send right returned by a previous
101 * call to os_workgroup_copy_port, potentially in a different process.
102 *
103 * A newly created os_workgroup_t has no initial member threads - in particular
104 * the creating thread does not join the os_workgroup_t implicitly.
105 *
106 * @param name
107 * A client specified string for labelling the workgroup. This parameter is
108 * optional and can be NULL.
109 *
110 * @param mach_port
111 * The send right to create the workgroup from. No reference is consumed
112 * on the specified send right.
113 */
114API_AVAILABLE(macos(11.0))
115API_UNAVAILABLE(ios, tvos, watchos)
116OS_SWIFT_NAME(WorkGroup.init(__name:port:)) OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED
117os_workgroup_t _Nullable
118os_workgroup_create_with_port(const char *OS_WORKGROUP_UNSAFE_INDEXABLE _Nullable name, mach_port_t mach_port);
119
120/*!
121 * @function os_workgroup_create_with_workgroup
122 *
123 * @abstract
124 * Create a new os_workgroup object from an existing os_workgroup.
125 *
126 * The newly created os_workgroup has no initial member threads - in particular
127 * the creating threaad does not join the os_workgroup_t implicitly.
128 *
129 * @param name
130 * A client specified string for labelling the workgroup. This parameter is
131 * optional and can be NULL.
132 *
133 * @param wg
134 * The existing workgroup to create a new workgroup object from.
135 */
136API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
137OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_RETURNS_RETAINED
138os_workgroup_t _Nullable
139os_workgroup_create_with_workgroup(const char * OS_WORKGROUP_UNSAFE_INDEXABLE _Nullable name, os_workgroup_t wg);
140
141/*!
142 * @typedef os_workgroup_join_token, os_workgroup_join_token_t
143 *
144 * @abstract
145 * An opaque join token which the client needs to pass to os_workgroup_join
146 * and os_workgroup_leave
147 */
148OS_REFINED_FOR_SWIFT
149typedef struct os_workgroup_join_token_opaque_s os_workgroup_join_token_s;
150OS_REFINED_FOR_SWIFT
151typedef struct os_workgroup_join_token_opaque_s *os_workgroup_join_token_t;
152
153
154/*!
155 * @function os_workgroup_join
156 *
157 * @abstract
158 * Joins the current thread to the specified workgroup and populates the join
159 * token that has been passed in. This API is real-time safe.
160 *
161 * @param wg
162 * The workgroup that the current thread would like to join
163 *
164 * @param token_out
165 * Pointer to a client allocated struct which the function will populate
166 * with the join token. This token must be passed in by the thread when it calls
167 * os_workgroup_leave().
168 *
169 * Errors will be returned in the following cases:
170 *
171 * EALREADY The thread is already part of a workgroup that the specified
172 * workgroup does not nest with
173 * EINVAL The workgroup has been cancelled
174 */
175API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
176OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
177int
178os_workgroup_join(os_workgroup_t wg, os_workgroup_join_token_t token_out);
179
180/*!
181 * @function os_workgroup_leave
182 *
183 * @abstract
184 * This removes the current thread from a workgroup it has previously
185 * joined. Threads must leave all workgroups in the reverse order that they
186 * have joined them. Failing to do so before exiting will result in undefined
187 * behavior.
188 *
189 * If the join token is malformed, the process will be aborted.
190 *
191 * This API is real time safe.
192 *
193 * @param wg
194 * The workgroup that the current thread would like to leave.
195 *
196 * @param token
197 * This is the join token populated by the most recent call to
198 * os_workgroup_join().
199 */
200API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
201OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
202void
203os_workgroup_leave(os_workgroup_t wg, os_workgroup_join_token_t token);
204
205/* Working Arena index of a thread in a workgroup */
206typedef uint32_t os_workgroup_index;
207/* Destructor for Working Arena */
208typedef void (*os_workgroup_working_arena_destructor_t)(void * _Nullable);
209
210/*!
211 * @function os_workgroup_set_working_arena
212 *
213 * @abstract
214 * Associates a client defined working arena with the workgroup. The arena
215 * is local to the workgroup object in the process. This is intended for
216 * distributing a manually managed memory allocation between member threads
217 * of the workgroup.
218 *
219 * This function can be called multiple times and the client specified
220 * destructor will be called on the previously assigned arena, if any. This
221 * function can only be called when no threads have currently joined the
222 * workgroup and all workloops associated with the workgroup are idle.
223 *
224 * @param wg
225 * The workgroup to associate the working arena with
226 *
227 * @param arena
228 * The client managed arena to associate with the workgroup. This value can
229 * be NULL.
230 *
231 * @param max_workers
232 * The maximum number of threads that will ever query the workgroup for the
233 * arena and request an index into it. If the arena is not used to partition
234 * work amongst member threads, then this field can be 0.
235 *
236 * @param destructor
237 * A destructor to call on the previously assigned working arena, if any
238 */
239API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
240OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT OS_WORKGROUP_WARN_RESULT
241int
242os_workgroup_set_working_arena(os_workgroup_t wg, void * _Nullable arena,
243 uint32_t max_workers, os_workgroup_working_arena_destructor_t destructor);
244
245/*!
246 * @function os_workgroup_get_working_arena
247 *
248 * @abstract
249 * Returns the working arena associated with the workgroup and the current
250 * thread's index in the workgroup. This function can only be called by a member
251 * of the workgroup. Multiple calls to this API by a member thread will return
252 * the same arena and index until the thread leaves the workgroup.
253 *
254 * For workloops with an associated workgroup, every work item on the workloop
255 * will receive the same index in the arena.
256 *
257 * This method returns NULL if no arena is set on the workgroup. The index
258 * returned by this function is zero-based and is namespaced per workgroup
259 * object in the process. The indices provided are strictly monotonic and never
260 * reused until a future call to os_workgroup_set_working_arena.
261 *
262 * @param wg
263 * The workgroup to get the working arena from.
264 *
265 * @param index_out
266 * A pointer to a os_workgroup_index which will be populated by the caller's
267 * index in the workgroup.
268 */
269API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
270OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
271void * _Nullable
272os_workgroup_get_working_arena(os_workgroup_t wg,
273 os_workgroup_index * _Nullable index_out);
274
275/*!
276 * @function os_workgroup_cancel
277 *
278 * @abstract
279 * This API invalidates a workgroup and indicates to the system that the
280 * workload is no longer relevant to the caller.
281 *
282 * No new work should be initiated for a cancelled workgroup and
283 * work that is already underway should periodically check for
284 * cancellation with os_workgroup_testcancel and initiate cleanup if needed.
285 *
286 * Threads currently in the workgroup continue to be tracked together but no
287 * new threads may join this workgroup - the only possible operation allowed is
288 * to leave the workgroup. Other actions may have undefined behavior or
289 * otherwise fail.
290 *
291 * This API is idempotent. Cancellation is local to the workgroup object
292 * it is called on and does not affect other workgroups.
293 *
294 * @param wg
295 * The workgroup that that the thread would like to cancel
296 */
297API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
298OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
299void
300os_workgroup_cancel(os_workgroup_t wg);
301
302/*!
303 * @function os_workgroup_testcancel
304 *
305 * @abstract
306 * Returns true if the workgroup object has been cancelled. See also
307 * os_workgroup_cancel
308 */
309API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
310OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
311bool
312os_workgroup_testcancel(os_workgroup_t wg);
313
314/*!
315 * @typedef os_workgroup_max_parallel_threads_attr_t
316 *
317 * @abstract
318 * A pointer to a structure describing the set of properties of a workgroup to
319 * override with the explicitly specified values in the structure.
320 *
321 * See also os_workgroup_max_parallel_threads.
322 */
323OS_REFINED_FOR_SWIFT
324typedef struct os_workgroup_max_parallel_threads_attr_s os_workgroup_mpt_attr_s;
325OS_REFINED_FOR_SWIFT
326typedef struct os_workgroup_max_parallel_threads_attr_s *os_workgroup_mpt_attr_t;
327
328/*!
329 * @function os_workgroup_max_parallel_threads
330 *
331 * @abstract
332 * Returns the system's recommendation for maximum number of threads the client
333 * should make for a multi-threaded workload in a given workgroup.
334 *
335 * This API takes into consideration the current hardware the code is running on
336 * and the attributes of the workgroup. It does not take into consideration the
337 * current load of the system and therefore always provides the most optimal
338 * recommendation for the workload.
339 *
340 * @param wg
341 * The workgroup in which the multi-threaded workload will be performed in. The
342 * threads performing the multi-threaded workload are expected to join this
343 * workgroup.
344 *
345 * @param attr
346 * This value is currently unused and should be NULL.
347 */
348API_AVAILABLE(macos(11.0), ios(14.0), tvos(14.0), watchos(7.0))
349OS_REFINED_FOR_SWIFT OS_WORKGROUP_EXPORT
350int
351os_workgroup_max_parallel_threads(os_workgroup_t wg, os_workgroup_mpt_attr_t
352 _Nullable attr);
353
354OS_WORKGROUP_ASSUME_ABI_SINGLE_END
355OS_WORKGROUP_ASSUME_NONNULL_END
356
357__END_DECLS
358
359#endif /* __OS_WORKGROUP_OBJECT__ */