···11+/*
22+ * Copyright (c) 2013-2016 Apple Inc. All rights reserved.
33+ *
44+ * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
55+ *
66+ * This file contains Original Code and/or Modifications of Original Code
77+ * as defined in and that are subject to the Apple Public Source License
88+ * Version 2.0 (the 'License'). You may not use this file except in
99+ * compliance with the License. The rights granted to you under the License
1010+ * may not be used to create, or enable the creation or redistribution of,
1111+ * unlawful or unlicensed copies of an Apple operating system, or to
1212+ * circumvent, violate, or enable the circumvention or violation of, any
1313+ * terms of an Apple operating system software license agreement.
1414+ *
1515+ * Please obtain a copy of the License at
1616+ * http://www.opensource.apple.com/apsl/ and read it before using this file.
1717+ *
1818+ * The Original Code and all software distributed under the License are
1919+ * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
2020+ * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
2121+ * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
2222+ * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
2323+ * Please see the License for the specific language governing rights and
2424+ * limitations under the License.
2525+ *
2626+ * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
2727+ */
2828+2929+#ifndef __OS_ACTIVITY_H__
3030+#define __OS_ACTIVITY_H__
3131+3232+#include <os/trace_base.h>
3333+3434+__BEGIN_DECLS
3535+3636+OS_ASSUME_NONNULL_BEGIN
3737+3838+#pragma mark - types and globals
3939+4040+#if OS_LOG_TARGET_HAS_10_12_FEATURES
4141+#define OS_ACTIVITY_OBJECT_API 1
4242+#else
4343+#if OS_ACTIVITY_OBJECT_API
4444+#error Please change your minimum OS requirements because OS_ACTIVITY_OBJECT_API is not available
4545+#endif // OS_ACTIVITY_OBJECT_API
4646+#define OS_ACTIVITY_OBJECT_API 0
4747+#endif
4848+4949+/*!
5050+ * @enum os_activity_flag_t
5151+ *
5252+ * @discussion
5353+ * Support flags for os_activity_create or os_activity_start.
5454+ *
5555+ * @constant OS_ACTIVITY_FLAG_DEFAULT
5656+ * Use the default flags.
5757+ *
5858+ * @constant OS_ACTIVITY_FLAG_DETACHED
5959+ * Detach the newly created activity from the provided activity (if any). If
6060+ * passed in conjunction with an exiting activity, the activity will only note
6161+ * what activity "created" the new one, but will make the new activity a top
6262+ * level activity. This allows users to see what activity triggered work
6363+ * without actually relating the activities.
6464+ *
6565+ * @constant OS_ACTIVITY_FLAG_IF_NONE_PRESENT
6666+ * Will only create a new activity if none present. If an activity ID is
6767+ * already present, a new object will be returned with the same activity ID
6868+ * underneath.
6969+ *
7070+ * Passing both OS_ACTIVITY_FLAG_DETACHED and OS_ACTIVITY_FLAG_IF_NONE_PRESENT
7171+ * is undefined.
7272+ */
7373+OS_ENUM(os_activity_flag, uint32_t,
7474+ OS_ACTIVITY_FLAG_DEFAULT = 0,
7575+ OS_ACTIVITY_FLAG_DETACHED = 0x1,
7676+ OS_ACTIVITY_FLAG_IF_NONE_PRESENT = 0x2
7777+);
7878+7979+#if OS_ACTIVITY_OBJECT_API
8080+8181+#define OS_ACTIVITY_NULL NULL
8282+8383+/*!
8484+ * @typedef os_activity_t
8585+ * An opaque activity object.
8686+ */
8787+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
8888+#if OS_OBJECT_USE_OBJC
8989+OS_OBJECT_DECL(os_activity);
9090+#else
9191+typedef struct os_activity_s *os_activity_t;
9292+#endif /* OS_OBJECT_USE_OBJC */
9393+9494+/*!
9595+ * @const OS_ACTIVITY_NONE
9696+ *
9797+ * @discussion
9898+ * Create activity with no current traits, this is the equivalent of a
9999+ * detached activity.
100100+ */
101101+#define OS_ACTIVITY_NONE OS_OBJECT_GLOBAL_OBJECT(os_activity_t, _os_activity_none)
102102+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
103103+OS_EXPORT
104104+const struct os_activity_s _os_activity_none;
105105+106106+/*!
107107+ * @const OS_ACTIVITY_CURRENT
108108+ *
109109+ * @discussion
110110+ * Create activity and links to the current activity if one is present.
111111+ * If no activity is present it is treated as if it is detached.
112112+ */
113113+#define OS_ACTIVITY_CURRENT OS_OBJECT_GLOBAL_OBJECT(os_activity_t, _os_activity_current)
114114+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
115115+OS_EXPORT
116116+const struct os_activity_s _os_activity_current;
117117+118118+#else // !OS_ACTIVITY_OBJECT_API
119119+120120+#define OS_ACTIVITY_NULL 0
121121+122122+/*!
123123+ * @typedef os_activity_t
124124+ * An opaque activity identifier.
125125+ */
126126+API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
127127+typedef uint64_t os_activity_t;
128128+129129+#endif // OS_ACTIVITY_OBJECT_API
130130+131131+/*!
132132+ * @typedef os_activity_id_t
133133+ * An value representing the activity ID assigned to an newly created activity.
134134+ */
135135+API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
136136+typedef uint64_t os_activity_id_t;
137137+138138+/*!
139139+ * @typedef os_activity_scope_state_t
140140+ * Structure that is populated by os_activity_scope_enter and restored using
141141+ * os_activity_scope_leave.
142142+ */
143143+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
144144+typedef struct os_activity_scope_state_s {
145145+ uint64_t opaque[2];
146146+} *os_activity_scope_state_t;
147147+148148+#pragma mark - Internal support functions
149149+150150+#if OS_ACTIVITY_OBJECT_API
151151+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
152152+OS_EXPORT OS_NOTHROW OS_WARN_RESULT_NEEDS_RELEASE OS_NOT_TAIL_CALLED
153153+OS_OBJECT_RETURNS_RETAINED
154154+os_activity_t
155155+_os_activity_create(void *dso, const char *description, os_activity_t activity,
156156+ os_activity_flag_t flags);
157157+#endif
158158+159159+/*!
160160+ * @function _os_activity_label_useraction
161161+ *
162162+ * @abstract
163163+ * Internal function for use by os_activity_label_useraction.
164164+ *
165165+ * @warning
166166+ * Do not use directly.
167167+ */
168168+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
169169+OS_EXPORT OS_NOTHROW OS_NOT_TAIL_CALLED
170170+void
171171+_os_activity_label_useraction(void *dso, const char *name);
172172+173173+/*!
174174+ * @function _os_activity_initiate
175175+ *
176176+ * @abstract
177177+ * Do not use directly because your description will not be preserved.
178178+ */
179179+API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
180180+OS_EXPORT OS_NOTHROW OS_NOT_TAIL_CALLED
181181+void
182182+_os_activity_initiate(void *dso, const char *description,
183183+ os_activity_flag_t flags, os_block_t activity_block OS_NOESCAPE);
184184+185185+/*!
186186+ * @function _os_activity_initiate_f
187187+ *
188188+ * @abstract
189189+ * Do not use directly because your description will not be preserved.
190190+ */
191191+API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0))
192192+OS_EXPORT OS_NOTHROW OS_NOT_TAIL_CALLED
193193+void
194194+_os_activity_initiate_f(void *dso, const char *description,
195195+ os_activity_flag_t flags, void *context, os_function_t function);
196196+197197+#pragma mark - activity related
198198+199199+/*!
200200+ * @function os_activity_initiate
201201+ *
202202+ * @abstract
203203+ * Synchronously initiates an activity using provided block.
204204+ *
205205+ * @discussion
206206+ * Synchronously initiates an activity using the provided block and creates
207207+ * a tracing buffer as appropriate. All new activities are created as a
208208+ * subactivity of an existing activity on the current thread.
209209+ *
210210+ * <code>
211211+ * os_activity_initiate("indexing database", OS_ACTIVITY_FLAG_DEFAULT, ^(void) {
212212+ * // either do work directly or issue work asynchronously
213213+ * });
214214+ * </code>
215215+ *
216216+ * @param description
217217+ * A constant string describing the activity, e.g., "performClick" or
218218+ * "menuSelection".
219219+ *
220220+ * @param flags
221221+ * Flags to be used when initiating the activity, typically
222222+ * OS_ACTIVITY_FLAG_DEFAULT.
223223+ *
224224+ * @param activity_block
225225+ * The block to execute a given activity
226226+ */
227227+#define os_activity_initiate(description, flags, activity_block) __extension__({ \
228228+ OS_LOG_STRING(ACT, __description, description); \
229229+ _os_activity_initiate(&__dso_handle, __description, flags, activity_block); \
230230+})
231231+232232+/*!
233233+ * @function os_activity_initiate_f
234234+ *
235235+ * @abstract
236236+ * Synchronously initiates an activity using the provided function.
237237+ *
238238+ * @discussion
239239+ * Synchronously initiates an activity using the provided function and creates
240240+ * a tracing buffer as appropriate. All new activities are created as a
241241+ * subactivity of an existing activity on the current thread.
242242+ *
243243+ * <code>
244244+ * os_activity_initiate_f("indexing database", OS_ACTIVITY_FLAG_DEFAULT, context, function);
245245+ * </code>
246246+ *
247247+ * @param description
248248+ * A constant string describing the activity, e.g., "performClick" or
249249+ * "menuSelection".
250250+ *
251251+ * @param flags
252252+ * Flags to be used when initiating the activity, typically
253253+ * OS_ACTIVITY_FLAG_DEFAULT.
254254+ *
255255+ * @param context
256256+ * An optional context that will be supplied to the activity function.
257257+ *
258258+ * @param activity_func
259259+ * The function to execute for the new activity.
260260+ */
261261+#define os_activity_initiate_f(description, flags, context, function) __extension__({ \
262262+ OS_LOG_STRING(ACT, __description, description); \
263263+ _os_activity_initiate_f(&__dso_handle, __description, flags, context, function); \
264264+})
265265+266266+#if OS_ACTIVITY_OBJECT_API
267267+/*!
268268+ * @function os_activity_create
269269+ *
270270+ * @abstract
271271+ * Creates an os_activity_t object which can be passed to os_activity_apply
272272+ * function.
273273+ *
274274+ * @param description
275275+ * Pass a description for the activity. The description must be a constant
276276+ * string within the calling executable or library.
277277+ *
278278+ * @param parent_activity
279279+ * Depending on flags will link the newly created activity to the value passed
280280+ * or note where the activity was created. Possible activities include:
281281+ * OS_ACTIVITY_NONE, OS_ACTIVITY_CURRENT or any existing os_activity_t object
282282+ * created using os_activity_create.
283283+ *
284284+ * @param flags
285285+ * A valid os_activity_flag_t which will determine behavior of the newly created
286286+ * activity.
287287+ *
288288+ * If the OS_ACTIVITY_FLAG_DETACHED flag is passed, the value passed to the
289289+ * parent_activity argument is ignored, and OS_ACTIVITY_NONE is used instead.
290290+ *
291291+ * If the OS_ACTIVITY_FLAG_IF_NONE_PRESENT flag is passed, then passing another
292292+ * value than OS_ACTIVITY_CURRENT to the parent_activity argument is undefined.
293293+ *
294294+ * @result
295295+ * Returns an os_activity_t object which can be used with os_activity_apply.
296296+ */
297297+#define os_activity_create(description, parent_activity, flags) __extension__({ \
298298+ OS_LOG_STRING(ACT, __description, description); \
299299+ _os_activity_create(&__dso_handle, __description, parent_activity, flags); \
300300+})
301301+302302+/*!
303303+ * @function os_activity_apply
304304+ *
305305+ * @abstract
306306+ * Execute a block using a given activity object.
307307+ *
308308+ * @param activity
309309+ * The given activity object created with os_activity_create() or
310310+ * OS_ACTIVITY_NONE.
311311+ *
312312+ * @param block
313313+ * Pass the block to be executed within the context of the given activity.
314314+ */
315315+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
316316+OS_EXPORT OS_NOTHROW
317317+void
318318+os_activity_apply(os_activity_t activity, os_block_t block OS_NOESCAPE);
319319+320320+/*!
321321+ * @function os_activity_apply_f
322322+ *
323323+ * @abstract
324324+ * Execute a given function with a provided activity.
325325+ *
326326+ * @param activity
327327+ * The given activity object created with os_activity_create() or
328328+ * OS_ACTIVITY_NONE.
329329+ *
330330+ * @param context
331331+ * Context to pass to the function which may be NULL.
332332+ *
333333+ * @param function
334334+ * Pass the function to be executed within the context of the given activity.
335335+ */
336336+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
337337+OS_EXPORT OS_NOTHROW
338338+void
339339+os_activity_apply_f(os_activity_t activity, void *context,
340340+ os_function_t function);
341341+342342+/*!
343343+ * @function os_activity_scope_enter
344344+ *
345345+ * @abstract
346346+ * Will change the current execution context to use the provided activity.
347347+ *
348348+ * @discussion
349349+ * Will change the current execution context to use the provided activity.
350350+ * An activity can be created and then applied to the current scope by doing:
351351+ *
352352+ * <code>
353353+ * struct os_activity_scope_state_s state;
354354+ * os_activity_t activity = os_activity_create("my new activity", 0);
355355+ * os_activity_scope_enter(activity, &state);
356356+ * ... do some work ...
357357+ * os_activity_scope_leave(&state);
358358+ * </code>
359359+ *
360360+ * To auto-cleanup state call:
361361+ *
362362+ * os_activity_scope(activity);
363363+ *
364364+ * @param activity
365365+ * Pass a valid activity created with os_activity_create or any global object.
366366+ *
367367+ * @param state
368368+ * A stack-based struct os_activity_scope_state_s to store the state.
369369+ */
370370+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
371371+OS_EXPORT OS_NOTHROW
372372+void
373373+os_activity_scope_enter(os_activity_t activity, os_activity_scope_state_t state);
374374+375375+/*!
376376+ * @function os_activity_scope_leave
377377+ *
378378+ * @abstract
379379+ * Will pop state up to the state provided.
380380+ *
381381+ * @discussion
382382+ * Will leave scope using the state provided. If state is not present an error
383383+ * will be generated.
384384+ *
385385+ * @param state
386386+ * Must be a valid value filled by os_activity_scope_enter call.
387387+ */
388388+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
389389+OS_EXPORT OS_NOTHROW
390390+void
391391+os_activity_scope_leave(os_activity_scope_state_t state);
392392+393393+#if defined(__GNUC__)
394394+#define _os_activity_scope(var, activity) \
395395+ struct os_activity_scope_state_s var __attribute__((__cleanup__(os_activity_scope_leave))); \
396396+ os_activity_scope_enter(activity, &var)
397397+#define os_activity_scope(activity) _os_activity_scope(OS_CONCAT(scope, __COUNTER__), activity)
398398+#endif
399399+400400+#endif // OS_ACTIVITY_OBJECT_API
401401+402402+/*!
403403+ * @function os_activity_get_active
404404+ *
405405+ * @abstract
406406+ * Returns the stack of nested activities associated with the current thread.
407407+ *
408408+ * @discussion
409409+ * Activities have a sense of nesting and therefore there could be more than
410410+ * one activity involved on the current thread. This should be used by
411411+ * diagnostic tools only for making additional decisions about a situation.
412412+ *
413413+ * @param entries
414414+ * Pass a buffer of sufficient size to hold the the number of os_activity_id_t
415415+ * being requested.
416416+ *
417417+ * @param count
418418+ * Pointer to the requested number of activity identifiers.
419419+ * On output will be filled with the number of activities that are available.
420420+ *
421421+ * @result
422422+ * Number of activity identifiers written to 'entries'
423423+ */
424424+API_DEPRECATED("No longer supported", macos(10.10, 10.12), ios(8.0, 10.0),
425425+ watchos(2.0, 3.0), tvos(9.0, 10.0))
426426+OS_EXPORT OS_NOTHROW
427427+unsigned int
428428+os_activity_get_active(os_activity_id_t *entries, unsigned int *count);
429429+430430+/*!
431431+ * @function os_activity_get_identifier
432432+ *
433433+ * @abstract
434434+ * Returns the current activity ID and will fill the parent_id if present.
435435+ *
436436+ * @discussion
437437+ * Returns the current activity ID and will fill the parent_id if present.
438438+ *
439439+ * @param parent_id
440440+ * If non-null will set the parent activity ID.
441441+ *
442442+ * @result
443443+ * The identifier for the provided activity.
444444+ */
445445+API_AVAILABLE(macos(10.12), ios(10.0), watchos(3.0), tvos(10.0))
446446+OS_EXPORT OS_NOTHROW OS_WARN_RESULT
447447+os_activity_id_t
448448+os_activity_get_identifier(os_activity_t activity,
449449+ os_activity_id_t *_Nullable parent_id);
450450+451451+/*!
452452+ * @function os_activity_label_useraction
453453+ *
454454+ * @abstract
455455+ * Label an activity that is auto-generated by AppKit/UIKit with a name that is
456456+ * useful for debugging macro-level user actions.
457457+ *
458458+ * @discussion
459459+ * Label an activity that is auto-generated by AppKit/UIKit with a name that is
460460+ * useful for debugging macro-level user actions. The API should be called
461461+ * early within the scope of the IBAction and before any sub-activities are
462462+ * created. The name provided will be shown in tools in additon to the
463463+ * underlying AppKit/UIKit provided name. This API can only be called once and
464464+ * only on the activity created by AppKit/UIKit. These actions help determine
465465+ * workflow of the user in order to reproduce problems that occur. For example,
466466+ * a control press and/or menu item selection can be labeled:
467467+ *
468468+ * <code>
469469+ * os_activity_label_useraction("New mail message");
470470+ * os_activity_label_useraction("Empty trash");
471471+ * </code>
472472+ *
473473+ * Where the underlying AppKit/UIKit name will be "gesture:" or "menuSelect:".
474474+ *
475475+ * @param name
476476+ * A constant string that describes the the action.
477477+ */
478478+#define os_activity_label_useraction(label) __extension__({ \
479479+ OS_LOG_STRING(ACT, __label, label); \
480480+ _os_activity_label_useraction(&__dso_handle, __label); \
481481+})
482482+483483+#pragma mark - deprecated function support
484484+485485+/*!
486486+ * @function _os_activity_start
487487+ *
488488+ * @abstract
489489+ * Internal function for activity start, do not use directly will not preserve
490490+ * description.
491491+ */
492492+API_DEPRECATED("use combination of os_activity_create and os_activity_apply/os_activity_scope",
493493+ macos(10.10, 10.12), ios(8.0, 10.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
494494+OS_EXPORT OS_NOTHROW OS_WARN_RESULT OS_NOT_TAIL_CALLED
495495+os_activity_t
496496+_os_activity_start(void *dso, const char *description, os_activity_flag_t flags);
497497+498498+/*!
499499+ * @function os_activity_start
500500+ *
501501+ * @warning
502502+ * Deprecated please use new os_activity_create and os_activity_apply.
503503+ */
504504+#define os_activity_start(description, flags) __extension__({ \
505505+ OS_LOG_STRING(ACT, __description, description); \
506506+ _os_activity_start(&__dso_handle, __description, flags); \
507507+})
508508+509509+/*!
510510+ * @function os_activity_end
511511+ *
512512+ * @warning
513513+ * Deprecated please use new os_activity_create and os_activity_apply.
514514+ */
515515+API_DEPRECATED("use combination of os_activity_create and os_activity_apply/os_activity_scope",
516516+ macos(10.10, 10.12), ios(8.0, 10.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
517517+OS_EXPORT OS_NOTHROW
518518+void
519519+os_activity_end(os_activity_t activity);
520520+521521+/*!
522522+ * @typedef os_breadcrumb_t
523523+ * An opaque value for the breadcrumb ID.
524524+ */
525525+API_DEPRECATED("No longer supported", macos(10.10, 10.12), ios(8.0, 10.0),
526526+ watchos(2.0, 3.0), tvos(9.0, 10.0))
527527+typedef uint32_t os_breadcrumb_t;
528528+529529+/*!
530530+ * @function _os_activity_set_breadcrumb
531531+ *
532532+ * @warning
533533+ * Deprecated, please use os_activity_label_useraction.
534534+ */
535535+API_DEPRECATED_WITH_REPLACEMENT("os_activity_label_useraction",
536536+ macos(10.10, 10.12), ios(8.0, 10.0), watchos(2.0, 3.0), tvos(9.0, 10.0))
537537+OS_EXPORT OS_NOTHROW OS_NOT_TAIL_CALLED
538538+void
539539+_os_activity_set_breadcrumb(void *dso, const char *name);
540540+541541+/*!
542542+ * @function os_activity_set_breadcrumb
543543+ *
544544+ * @warning
545545+ * Deprecated, please use os_activity_label_useraction.
546546+ */
547547+#define os_activity_set_breadcrumb(name) __extension__({ \
548548+ OS_LOG_STRING(ACT, __name, name); \
549549+ _os_activity_set_breadcrumb(&__dso_handle, __name); \
550550+})
551551+552552+OS_ASSUME_NONNULL_END
553553+554554+__END_DECLS
555555+556556+#endif // __OS_ACTIVITY_H__