xref: /xnu-12377.1.9/tests/unit/mocks/mock_thread.h (revision f6217f891ac0bb64f3d375211650a4c1ff8ca1ea)
1*f6217f89SApple OSS Distributions /*
2*f6217f89SApple OSS Distributions  * Copyright (c) 2025 Apple Inc. All rights reserved.
3*f6217f89SApple OSS Distributions  *
4*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*f6217f89SApple OSS Distributions  *
6*f6217f89SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*f6217f89SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*f6217f89SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*f6217f89SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*f6217f89SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*f6217f89SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*f6217f89SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*f6217f89SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*f6217f89SApple OSS Distributions  *
15*f6217f89SApple OSS Distributions  * Please obtain a copy of the License at
16*f6217f89SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*f6217f89SApple OSS Distributions  *
18*f6217f89SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*f6217f89SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*f6217f89SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*f6217f89SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*f6217f89SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*f6217f89SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*f6217f89SApple OSS Distributions  * limitations under the License.
25*f6217f89SApple OSS Distributions  *
26*f6217f89SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*f6217f89SApple OSS Distributions  */
28*f6217f89SApple OSS Distributions 
29*f6217f89SApple OSS Distributions #pragma once
30*f6217f89SApple OSS Distributions 
31*f6217f89SApple OSS Distributions #include "mock_dynamic.h"
32*f6217f89SApple OSS Distributions #include <arm/pmap_public.h>
33*f6217f89SApple OSS Distributions #include <vm/pmap.h>
34*f6217f89SApple OSS Distributions #include <kern/lock_mtx.h>
35*f6217f89SApple OSS Distributions #include <kern/task.h>
36*f6217f89SApple OSS Distributions 
37*f6217f89SApple OSS Distributions #include "fibers/fibers.h"
38*f6217f89SApple OSS Distributions 
39*f6217f89SApple OSS Distributions // Unit tests that wants to use fibers must call with macro in the global scope with val=1
40*f6217f89SApple OSS Distributions #define UT_USE_FIBERS(val) int ut_mocks_use_fibers = (val)
41*f6217f89SApple OSS Distributions // Unit tests using fibers that wants to enable the data race checker must call with macro in the global scope with val=1
42*f6217f89SApple OSS Distributions #define UT_FIBERS_USE_CHECKER(val) int ut_fibers_use_data_race_checker = (val)
43*f6217f89SApple OSS Distributions 
44*f6217f89SApple OSS Distributions extern int ut_mocks_use_fibers __attribute__((weak));
45*f6217f89SApple OSS Distributions extern int ut_fibers_use_data_race_checker __attribute__((weak));
46*f6217f89SApple OSS Distributions 
47*f6217f89SApple OSS Distributions // You can set the fibers configuration variables either assigning a value to them in the test function (see fibers_test.c)
48*f6217f89SApple OSS Distributions // or using these macros in the global scope
49*f6217f89SApple OSS Distributions #define UT_FIBERS_LOG_LEVEL(val)    \
50*f6217f89SApple OSS Distributions     __attribute__((constructor))    \
51*f6217f89SApple OSS Distributions     static void                     \
52*f6217f89SApple OSS Distributions     _ut_fibers_set_log_level(void)  \
53*f6217f89SApple OSS Distributions     {                               \
54*f6217f89SApple OSS Distributions 	fibers_log_level = (val);       \
55*f6217f89SApple OSS Distributions     }
56*f6217f89SApple OSS Distributions #define UT_FIBERS_DEBUG(val)        \
57*f6217f89SApple OSS Distributions     __attribute__((constructor))    \
58*f6217f89SApple OSS Distributions     static void                     \
59*f6217f89SApple OSS Distributions     _ut_fibers_set_log_debug(void)  \
60*f6217f89SApple OSS Distributions     {                               \
61*f6217f89SApple OSS Distributions 	fibers_debug = (val);           \
62*f6217f89SApple OSS Distributions     }
63*f6217f89SApple OSS Distributions #define UT_FIBERS_ABORT_ON_ERROR(val)    \
64*f6217f89SApple OSS Distributions     __attribute__((constructor))         \
65*f6217f89SApple OSS Distributions     static void                          \
66*f6217f89SApple OSS Distributions     _ut_fibers_set_abort_on_error(void)  \
67*f6217f89SApple OSS Distributions     {                                    \
68*f6217f89SApple OSS Distributions 	fibers_abort_on_error = (val);       \
69*f6217f89SApple OSS Distributions     }
70*f6217f89SApple OSS Distributions #define UT_FIBERS_MAY_YIELD_PROB(val)      \
71*f6217f89SApple OSS Distributions     __attribute__((constructor))           \
72*f6217f89SApple OSS Distributions     static void                            \
73*f6217f89SApple OSS Distributions     _ut_fibers_set_may_yield_prob(void)    \
74*f6217f89SApple OSS Distributions     {                                      \
75*f6217f89SApple OSS Distributions 	fibers_may_yield_probability = (val);  \
76*f6217f89SApple OSS Distributions     }
77*f6217f89SApple OSS Distributions 
78*f6217f89SApple OSS Distributions /*
79*f6217f89SApple OSS Distributions  * Writing tests using fibers:
80*f6217f89SApple OSS Distributions  *
81*f6217f89SApple OSS Distributions  * If UT_USE_FIBERS(1) is used, every test defined in the same test executable will use the threading mocks implemented using the fibers API.
82*f6217f89SApple OSS Distributions  * However, this is not sufficient to write a test with multiple "threads", the test itself is reposinsible of creating the fibers.
83*f6217f89SApple OSS Distributions  * For some working examples, see the fibers_test.c file.
84*f6217f89SApple OSS Distributions  *
85*f6217f89SApple OSS Distributions  * The tests file must include the needed headers from mocks/fibers/ depending on what needs to be used.
86*f6217f89SApple OSS Distributions  * Fibers API are very similar to pthread, and if FIBERS_PREEMPTION=1 is used at compile time it behaves in a similar way to real threads.
87*f6217f89SApple OSS Distributions  * The main different is that developers must be aware that blocking operations are blocking every fiber,
88*f6217f89SApple OSS Distributions  * for instance you should not call sleep() in your test and if some kernel function is calling a similar function you should mock it with
89*f6217f89SApple OSS Distributions  * a call to one or more fibers_yield() to trigger a context switch.
90*f6217f89SApple OSS Distributions  * The scheduler is deterministic, the interleaving can be changed either setting a different seed in the PRNG with random_set_seed()
91*f6217f89SApple OSS Distributions  * or with any change to the code itself, as possible context switch points are located inside the fibers API or, even more drastically,
92*f6217f89SApple OSS Distributions  * at every memory load/store when FIBERS_PREEMPTION=1.
93*f6217f89SApple OSS Distributions  *
94*f6217f89SApple OSS Distributions  * Target code in XNU (like sysctl tests) can trigger a fibers context switch using the following API (see mock_attached.c):
95*f6217f89SApple OSS Distributions  * void ut_fibers_ctxswitch(void); // Switch to a random fiber
96*f6217f89SApple OSS Distributions  * void ut_fibers_ctxswitch_to(int fiber_id); // Switch to a specific fiber by id
97*f6217f89SApple OSS Distributions  * int ut_fibers_current_id(void); // Get the current fiber id
98*f6217f89SApple OSS Distributions  */
99*f6217f89SApple OSS Distributions 
100*f6217f89SApple OSS Distributions extern void fake_init_lock(lck_mtx_t *mtx);
101*f6217f89SApple OSS Distributions extern void fake_init_task(task_t new_task);
102*f6217f89SApple OSS Distributions 
103*f6217f89SApple OSS Distributions T_MOCK_DYNAMIC_DECLARE(
104*f6217f89SApple OSS Distributions 	kern_return_t,
105*f6217f89SApple OSS Distributions 	thread_wakeup_prim, (
106*f6217f89SApple OSS Distributions 		event_t           event,
107*f6217f89SApple OSS Distributions 		boolean_t         one_thread,
108*f6217f89SApple OSS Distributions 		wait_result_t     result));
109*f6217f89SApple OSS Distributions 
110*f6217f89SApple OSS Distributions T_MOCK_DYNAMIC_DECLARE(
111*f6217f89SApple OSS Distributions 	wait_result_t,
112*f6217f89SApple OSS Distributions 	thread_block_reason, (
113*f6217f89SApple OSS Distributions 		thread_continue_t continuation,
114*f6217f89SApple OSS Distributions 		void              *parameter,
115*f6217f89SApple OSS Distributions 		ast_t             reason));
116