]> git.saurik.com Git - apple/xnu.git/blob - tests/vm_memory_tests_src/main.c
xnu-7195.50.7.100.1.tar.gz
[apple/xnu.git] / tests / vm_memory_tests_src / main.c
1 #include "mach_vm_tests.h"
2
3 T_GLOBAL_META(T_META_NAMESPACE("xnu.vm"));
4
5 extern char **environ;
6
7 static void
8 spawn_process(char *action, char *serviceName, char *extraArg,
9 mach_port_t *server_Port, pid_t *serverPid, boolean_t use4k);
10
11 static void mach_client(void);
12
13 mach_port_t serverPort;
14 static pid_t serverPid;
15
16 boolean_t debug = TRUE;
17
18 void
19 spawn_process(char *action, char *serviceName, char *extraArg,
20 mach_port_t *server_Port, pid_t *server_Pid, boolean_t use4k)
21 {
22 char buffer[PATH_MAX];
23 char *argv[10] = {0};
24 int arg_index = 0;
25 pid_t pid = -1;
26 int r = proc_pidpath(getpid(), buffer, sizeof(buffer));
27 T_ASSERT_NE(r, -1, "proc_pidpath");
28 r = (int)strlcat(buffer, "_server", sizeof(buffer));
29 T_ASSERT_LT(r, (int)sizeof(buffer), "strlcat");
30
31 if (use4k) {
32 int supported = 0;
33 size_t supported_size = sizeof(supported);
34
35 r = sysctlbyname("debug.vm_mixed_pagesize_supported", &supported, &supported_size, NULL, 0);
36 if (r == 0 && supported) {
37 T_LOG("Using %s to spawn process with 4k", VM_SPAWN_TOOL);
38 argv[arg_index++] = VM_SPAWN_TOOL;
39 } else {
40 /*
41 * We didnt find debug.vm.mixed_page.supported OR its set to 0.
42 * Skip the test.
43 */
44 T_SKIP("Hardware doesn't support 4K pages, skipping test...");
45 exit(0);
46 }
47 }
48 argv[arg_index++] = (char *)&buffer[0];
49 argv[arg_index++] = (char *)action;
50 argv[arg_index++] = (char *)serviceName;
51 argv[arg_index++] = (char *)extraArg;
52 argv[arg_index++] = NULL;
53
54 printf("posix_spawn with argv: ");
55 for (r = 0; r <= arg_index; r++) {
56 printf("%s ", argv[r]);
57 }
58 printf("\n");
59
60 T_LOG("Spawning %s process(%s) with service name %s at %s\n", action, buffer, serviceName, buffer);
61
62
63 posix_spawn_file_actions_t actions;
64 posix_spawn_file_actions_init(&actions);
65
66 T_ASSERT_POSIX_ZERO(posix_spawn(&pid, buffer, &actions, NULL, argv, environ), "spawn %s", serviceName);
67 posix_spawn_file_actions_destroy(&actions);
68
69 kern_return_t ret;
70 mach_port_t servicePort;
71 int attempts = 0;
72 const int kMaxAttempts = 10;
73 do {
74 sleep(1);
75 ret = bootstrap_look_up(bootstrap_port, serviceName, &servicePort);
76 attempts++;
77 } while (ret == BOOTSTRAP_UNKNOWN_SERVICE && attempts < kMaxAttempts);
78
79 if (ret != KERN_SUCCESS) {
80 printf("ERROR: Failed bootstrap lookup for process with mach service name '%s': (%d) %s\n", serviceName, ret, mach_error_string(ret));
81 if (pid > 0) {
82 kill(pid, SIGKILL);
83 }
84 T_FAIL("Failed bootstrap lookup for process with mach service");
85 }
86
87 *server_Port = servicePort;
88 *server_Pid = pid;
89 T_LOG("Server pid=%d port 0x%x", pid, servicePort);
90 }
91
92
93
94
95 void
96 mach_client()
97 {
98 mach_port_t replyPort;
99 T_ASSERT_POSIX_ZERO(mach_port_allocate(mach_task_self(), MACH_PORT_RIGHT_RECEIVE, &replyPort), "create recieve port");
100 T_ASSERT_POSIX_ZERO(mach_port_insert_right(mach_task_self(), replyPort, replyPort, MACH_MSG_TYPE_MAKE_SEND), "insert send port");
101
102 ipc_message_t message;
103 bzero(&message, sizeof(message));
104 message.header.msgh_id = 1;
105
106 message.header.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, MACH_MSG_TYPE_COPY_SEND);
107 message.header.msgh_remote_port = serverPort;
108 message.header.msgh_local_port = replyPort;
109 message.header.msgh_size = sizeof(message);
110
111 /* reply creation is not necessary in this case.
112 * mach_msg_size_t replySize = sizeof(ipc_message_t) + sizeof(mach_msg_trailer_t) + 64;
113 * ipc_message_t *reply = calloc(1, replySize);
114 */
115 T_LOG("sending message to %d of size %u", message.header.msgh_remote_port, message.header.msgh_size);
116 kern_return_t ret = mach_msg(&message.header, MACH_SEND_MSG, message.header.msgh_size, 0, MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
117 T_ASSERT_MACH_SUCCESS(ret, "mach_msg to serverProcess");
118 mach_vm_client(replyPort);
119 T_LOG("Sending SIGKILL to server(%d)", serverPid);
120 kill(serverPid, SIGKILL);
121 }
122
123 T_DECL(memory_share_tests,
124 "test vm memory sharing between client and server process with different process PAGE_SIZE",
125 T_META_ASROOT(true))
126 {
127 boolean_t use4k = FALSE;
128 char serviceName[64];
129
130 struct sigaction action = {
131 .sa_handler = SIG_IGN,
132 .sa_flags = SA_NOCLDWAIT
133 };
134 sigaction(SIGCHLD, &action, NULL);
135
136 if (getenv("USE4K")) {
137 use4k = TRUE;
138 }
139
140 if (getenv("QUIET")) {
141 debug = FALSE;
142 }
143
144 T_LOG("running with use4k=%d debug=%d", use4k, (int)debug);
145
146 strcpy(serviceName, MACH_VM_TEST_SERVICE_NAME);
147
148 spawn_process("machserver", serviceName, NULL, &serverPort, &serverPid, use4k);
149 mach_client();
150 }
151
152 T_DECL_REF(memory_share_tests_4k, memory_share_tests, "vm memory sharing with 4k processes",
153 T_META_ENVVAR("USE4K=YES"),
154 T_META_ASROOT(true)
155 );