1 /*
2  * Copyright (c) 2024 Meta Platforms
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include "kernel_shell.h"
8 
9 #include <zephyr/kernel.h>
10 
cmd_kernel_thread_mask_clear(const struct shell * sh,size_t argc,char ** argv)11 static int cmd_kernel_thread_mask_clear(const struct shell *sh, size_t argc, char **argv)
12 {
13 	ARG_UNUSED(argc);
14 
15 	int rc, err = 0;
16 	struct k_thread *thread;
17 
18 	thread = UINT_TO_POINTER(shell_strtoull(argv[1], 16, &err));
19 	if (err != 0) {
20 		shell_error(sh, "Unable to parse thread ID %s (err %d)", argv[1], err);
21 		return err;
22 	}
23 
24 	if (!z_thread_is_valid(thread)) {
25 		shell_error(sh, "Invalid thread id %p", (void *)thread);
26 		return -EINVAL;
27 	}
28 
29 	rc = k_thread_cpu_mask_clear(thread);
30 	if (rc != 0) {
31 		shell_error(sh, "Failed - %d", rc);
32 	} else {
33 		shell_print(sh, "%p %s cpu_mask: 0x%x", (void *)thread, thread->name,
34 			    thread->base.cpu_mask);
35 	}
36 
37 	return rc;
38 }
39 
cmd_kernel_thread_mask_enable_all(const struct shell * sh,size_t argc,char ** argv)40 static int cmd_kernel_thread_mask_enable_all(const struct shell *sh, size_t argc, char **argv)
41 {
42 	ARG_UNUSED(argc);
43 
44 	int rc, err = 0;
45 	struct k_thread *thread;
46 
47 	thread = UINT_TO_POINTER(shell_strtoull(argv[1], 16, &err));
48 	if (err != 0) {
49 		shell_error(sh, "Unable to parse thread ID %s (err %d)", argv[1], err);
50 		return err;
51 	}
52 
53 	if (!z_thread_is_valid(thread)) {
54 		shell_error(sh, "Invalid thread id %p", (void *)thread);
55 		return -EINVAL;
56 	}
57 
58 	rc = k_thread_cpu_mask_enable_all(thread);
59 	if (rc != 0) {
60 		shell_error(sh, "Failed - %d", rc);
61 	} else {
62 		shell_print(sh, "%p %s cpu_mask: 0x%x", (void *)thread, thread->name,
63 			    thread->base.cpu_mask);
64 	}
65 
66 	return rc;
67 }
68 
cmd_kernel_thread_mask_enable(const struct shell * sh,size_t argc,char ** argv)69 static int cmd_kernel_thread_mask_enable(const struct shell *sh, size_t argc, char **argv)
70 {
71 	ARG_UNUSED(argc);
72 
73 	int rc, cpu, err = 0;
74 	struct k_thread *thread;
75 
76 	thread = UINT_TO_POINTER(shell_strtoull(argv[1], 16, &err));
77 	if (err != 0) {
78 		shell_error(sh, "Unable to parse thread ID %s (err %d)", argv[1], err);
79 		return err;
80 	}
81 
82 	if (!z_thread_is_valid(thread)) {
83 		shell_error(sh, "Invalid thread id %p", (void *)thread);
84 		return -EINVAL;
85 	}
86 
87 	cpu = (int)shell_strtol(argv[2], 10, &err);
88 	if (err != 0) {
89 		shell_error(sh, "Unable to parse CPU ID %s (err %d)", argv[2], err);
90 		return err;
91 	}
92 
93 	rc = k_thread_cpu_mask_enable(thread, cpu);
94 	if (rc != 0) {
95 		shell_error(sh, "Failed - %d", rc);
96 	} else {
97 		shell_print(sh, "%p %s cpu_mask: 0x%x", (void *)thread, thread->name,
98 			    thread->base.cpu_mask);
99 	}
100 
101 	return rc;
102 }
103 
cmd_kernel_thread_mask_disable(const struct shell * sh,size_t argc,char ** argv)104 static int cmd_kernel_thread_mask_disable(const struct shell *sh, size_t argc, char **argv)
105 {
106 	ARG_UNUSED(argc);
107 
108 	int rc, cpu, err = 0;
109 	struct k_thread *thread;
110 
111 	thread = UINT_TO_POINTER(shell_strtoull(argv[1], 16, &err));
112 	if (err != 0) {
113 		shell_error(sh, "Unable to parse thread ID %s (err %d)", argv[1], err);
114 		return err;
115 	}
116 
117 	if (!z_thread_is_valid(thread)) {
118 		shell_error(sh, "Invalid thread id %p", (void *)thread);
119 		return -EINVAL;
120 	}
121 
122 	cpu = (int)shell_strtol(argv[2], 10, &err);
123 	if (err != 0) {
124 		shell_error(sh, "Unable to parse CPU ID %s (err %d)", argv[2], err);
125 		return err;
126 	}
127 
128 	rc = k_thread_cpu_mask_disable(thread, cpu);
129 	if (rc != 0) {
130 		shell_error(sh, "Failed - %d", rc);
131 	} else {
132 		shell_print(sh, "%p %s cpu_mask: 0x%x", (void *)thread, thread->name,
133 			    thread->base.cpu_mask);
134 	}
135 
136 	return rc;
137 }
138 
139 SHELL_STATIC_SUBCMD_SET_CREATE(sub_kernel_thread_mask,
140 	SHELL_CMD_ARG(clear, NULL,
141 		      "Sets all CPU enable masks to zero.\n"
142 		      "Usage: kernel thread mask clear <thread ID>",
143 		      cmd_kernel_thread_mask_clear, 2, 0),
144 	SHELL_CMD_ARG(enable_all, NULL,
145 		      "Sets all CPU enable masks to one.\n"
146 		      "Usage: kernel thread mask enable_all <thread ID>",
147 		      cmd_kernel_thread_mask_enable_all, 2, 0),
148 	SHELL_CMD_ARG(enable, NULL,
149 		      "Enable thread to run on specified CPU.\n"
150 		      "Usage: kernel thread mask enable <thread ID> <CPU ID>",
151 		      cmd_kernel_thread_mask_enable, 3, 0),
152 	SHELL_CMD_ARG(disable, NULL,
153 		      "Prevent thread to run on specified CPU.\n"
154 		      "Usage: kernel thread mask disable <thread ID> <CPU ID>",
155 		      cmd_kernel_thread_mask_disable, 3, 0),
156 	SHELL_SUBCMD_SET_END /* Array terminated. */
157 );
158 
159 KERNEL_THREAD_CMD_ARG_ADD(mask, &sub_kernel_thread_mask, "Configure thread CPU mask affinity.",
160 			  NULL, 2, 0);
161