+/*
+ * With the introduction of auto-join work intervals, it is possible
+ * to change the work interval (and related thread group) of a thread in a
+ * variety of contexts (thread termination, context switch, thread mode
+ * change etc.). In order to clearly specify the policy expectation and
+ * the locking behavior, all calls to thread_set_work_interval() pass
+ * in a set of flags.
+ */
+
+__options_decl(thread_work_interval_options_t, uint32_t, {
+ /* Change the work interval using the explicit join rules */
+ THREAD_WI_EXPLICIT_JOIN_POLICY = 0x1,
+ /* Change the work interval using the auto-join rules */
+ THREAD_WI_AUTO_JOIN_POLICY = 0x2,
+ /* Caller already holds the thread lock */
+ THREAD_WI_THREAD_LOCK_HELD = 0x4,
+ /* Caller does not hold the thread lock */
+ THREAD_WI_THREAD_LOCK_NEEDED = 0x8,
+ /* Change the work interval from the context switch path (thread may not be running or on a runq) */
+ THREAD_WI_THREAD_CTX_SWITCH = 0x10,
+});
+
+static kern_return_t thread_set_work_interval(thread_t, struct work_interval *, thread_work_interval_options_t);
+
+#if CONFIG_SCHED_AUTO_JOIN
+/* MPSC queue used to defer deallocate work intervals */
+static struct mpsc_daemon_queue work_interval_deallocate_queue;
+
+static void work_interval_deferred_release(struct work_interval *);
+
+/*
+ * Work Interval Auto-Join Status
+ *
+ * work_interval_auto_join_status_t represents the state of auto-join for a given work interval.
+ * It packs the following information:
+ * - A bit representing if a "finish" is deferred on the work interval
+ * - Count of number of threads auto-joined to the work interval
+ */
+#define WORK_INTERVAL_STATUS_DEFERRED_FINISH_MASK ((uint32_t)(1 << 31))
+#define WORK_INTERVAL_STATUS_AUTO_JOIN_COUNT_MASK ((uint32_t)(WORK_INTERVAL_STATUS_DEFERRED_FINISH_MASK - 1))
+#define WORK_INTERVAL_STATUS_AUTO_JOIN_COUNT_MAX WORK_INTERVAL_STATUS_AUTO_JOIN_COUNT_MASK
+typedef uint32_t work_interval_auto_join_status_t;
+
+static inline bool __unused
+work_interval_status_deferred_finish(work_interval_auto_join_status_t status)
+{
+ return (status & WORK_INTERVAL_STATUS_DEFERRED_FINISH_MASK) ? true : false;
+}
+
+static inline uint32_t __unused
+work_interval_status_auto_join_count(work_interval_auto_join_status_t status)
+{
+ return (uint32_t)(status & WORK_INTERVAL_STATUS_AUTO_JOIN_COUNT_MASK);
+}
+
+/*
+ * struct work_interval_deferred_finish_state
+ *
+ * Contains the parameters of the finish operation which is being deferred.
+ */
+struct work_interval_deferred_finish_state {
+ uint64_t instance_id;
+ uint64_t start;
+ uint64_t deadline;
+ uint64_t complexity;
+};
+
+struct work_interval_auto_join_info {
+ struct work_interval_deferred_finish_state deferred_finish_state;
+ work_interval_auto_join_status_t _Atomic status;
+};
+#endif /* CONFIG_SCHED_AUTO_JOIN */
+