xref: /xnu-10002.61.3/tests/vm/diag_threshold_test_logging.c (revision 0f4c859e951fba394238ab619495c4e1d54d0f34)
1 /**
2  *  diag_threshold_test_logging.c
3  *  diag_mem_threshold_logging_test
4  *
5  * Test that logs while sending signals between threads. That will
6  * validate that test logging functionality will not have a reentrancy
7  * issue.
8  *
9  * Copyright (c) 2023 Apple Inc. All rights reserved.
10  */
11 
12 
13 
14 #include <stdio.h>
15 #include "diag_threshold_test.h"
16 #include <sys/kern_memorystatus.h>
17 #include <pthread.h>
18 #include <signal.h>
19 #include <stdatomic.h>
20 #include <TargetConditionals.h>
21 
22 
23 pthread_t thread_logger, thread_kicker;
24 static void *logger_thread(void *);
25 static void signal_handler(__unused int signo, __unused  siginfo_t *info, __unused void *extra);
26 static struct sigaction    original_action;                                           /**   Original signal handler for the process */
27 static void set_sig_handler(void);
28 static void *kicker_thread(__unused void *param);
29 
30 static const double TESTING_TIME = 5.;
31 T_GLOBAL_META(
32 	T_META_ENABLED(TARGET_OS_IPHONE),
33 	T_META_NAMESPACE("xnu.vm.100432442"),
34 	T_META_RADAR_COMPONENT_NAME("xnu"),
35 	T_META_OWNER("jsolsona"),
36 	T_META_RADAR_COMPONENT_VERSION("VM")
37 	);
38 
39 
40 
41 T_DECL(diag_mem_threshold_logging_test,
42     "Logging test, log while handling posix signals")
43 {
44 	//diag_mem_threshold_set_setup(&diag_mem_threshold_logging_test);
45 	int  iret1, iret2;
46 	iret1 = pthread_create( &thread_logger, NULL, logger_thread, (void*) NULL);
47 	T_QUIET; T_ASSERT_POSIX_ZERO(iret1, "Creation of the logging thread");
48 	iret2 = pthread_create( &thread_kicker, NULL, kicker_thread, (void*) NULL);
49 	T_QUIET; T_ASSERT_POSIX_ZERO(iret2, "Creation of the kick thread");
50 	pthread_join(thread_logger, NULL);
51 	pthread_join(thread_kicker, NULL);
52 }
53 
54 /**
55  *  Simple logger thread, sets a signal handler and logs for 10s
56  */
57 static void *
logger_thread(__unused void * param)58 logger_thread(__unused void *param)
59 {
60 	set_sig_handler();
61 	time_t t = time(NULL);
62 	while (difftime(time(NULL), t) < TESTING_TIME) {
63 		diag_mem_threshold_log_test("I am logging from a thread %f  seconds ", difftime(time(NULL), t));
64 	}
65 	return NULL;
66 }
67 
68 
69 /**
70  *  Simple kicker thread, just send signals to the logger thread
71  */
72 static void *
kicker_thread(__unused void * param)73 kicker_thread(__unused void *param)
74 {
75 	time_t t = time(NULL);
76 	while (difftime(time(NULL), t) < TESTING_TIME) {
77 		pthread_kill(thread_logger, SIGUSR1);
78 	}
79 	return NULL;
80 }
81 
82 /**
83  * Standard function to set a singal handler routine. Sets the handler for SIGUSR1 to the
84  * termination_handler routine, and indeed terminates current thread.
85  */
86 static void
set_sig_handler(void)87 set_sig_handler(void)
88 {
89 	struct sigaction action;
90 
91 	action.sa_flags = SA_SIGINFO;
92 	action.sa_sigaction = signal_handler;
93 
94 	T_QUIET; T_ASSERT_MACH_SUCCESS(sigaction(SIGUSR1, &action, &original_action), "Verification of adjustment of signal handler");
95 }
96 
97 /**
98  * Handler of the SIGUSR1 signal, just terminates the current thread.
99  */
100 static void
signal_handler(__unused int signo,__unused siginfo_t * info,__unused void * extra)101 signal_handler(__unused int signo, __unused  siginfo_t *info, __unused void *extra)
102 {
103 	static atomic_int recursion_level = 0;
104 	atomic_fetch_add_explicit(&recursion_level, 1, memory_order_relaxed);
105 	if (recursion_level == 1) {
106 		diag_mem_threshold_log_test("Logging from a signal handler");
107 	}
108 	atomic_fetch_sub_explicit(&recursion_level, 1, memory_order_relaxed);
109 }
110