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