xref: /xnu-11215/tools/tests/affinity/tags.c (revision a5e72196)
1 #include <AvailabilityMacros.h>
2 #include <mach/thread_policy.h>
3 #include <mach/mach.h>
4 #include <mach/mach_traps.h>
5 #include <mach/mach_error.h>
6 #include <mach/mach_time.h>
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 #include <unistd.h>
11 #include <err.h>
12 
13 int             verbosity = 1;
14 
15 #define DBG(x...) do {                          \
16 	if (verbosity > 1) {                    \
17 	        printf(x);                      \
18 	}                                       \
19 } while (0)
20 
21 #define mutter(x...) do {                       \
22 	if (verbosity > 0) {                    \
23 	        printf(x);                      \
24 	}                                       \
25 } while (0)
26 
27 #define s_if_plural(x)  (((x) > 1) ? "s" : "")
28 
29 static void
usage()30 usage()
31 {
32 	fprintf(stderr,
33 	    "usage: tags [-i]   interactive/input\n"
34 	    "            [-v V] verbosity level 0..2 (1)\n"
35 	    "            [-h]   help info\n"
36 	    "            pid    process id of target task\n"
37 	    );
38 	exit(1);
39 }
40 
41 void
thread_tag_set(thread_t thread,int tag)42 thread_tag_set(thread_t thread, int tag)
43 {
44 	kern_return_t                   ret;
45 	thread_affinity_policy_data_t   policy;
46 
47 	policy.affinity_tag = tag;
48 	ret = thread_policy_set(
49 		thread, THREAD_AFFINITY_POLICY,
50 		(thread_policy_t) &policy,
51 		THREAD_AFFINITY_POLICY_COUNT);
52 	if (ret != KERN_SUCCESS) {
53 		printf("thread_policy_set(1) returned %d\n", ret);
54 		exit(1);
55 	}
56 }
57 
58 int
thread_tag_get(thread_t thread)59 thread_tag_get(thread_t thread)
60 {
61 	kern_return_t                   ret;
62 	boolean_t                       get_default = FALSE;
63 	thread_affinity_policy_data_t   policy;
64 	mach_msg_type_number_t          count = THREAD_AFFINITY_POLICY_COUNT;
65 
66 	ret = thread_policy_get(
67 		thread, THREAD_AFFINITY_POLICY,
68 		(thread_policy_t) &policy, &count, &get_default);
69 	if (ret != KERN_SUCCESS) {
70 		printf("thread_policy_set(1) returned %d\n", ret);
71 		exit(1);
72 	}
73 
74 	return policy.affinity_tag;
75 }
76 
77 char                    input[81];
78 int
main(int argc,char * argv[])79 main(int argc, char *argv[])
80 {
81 	kern_return_t           ret;
82 	mach_port_name_t        port;
83 	int                     pid;
84 	int                     c;
85 	thread_act_t            *thread_array;
86 	mach_msg_type_number_t  num_threads;
87 	int                     i;
88 	boolean_t               interactive = FALSE;
89 	int                     tag;
90 
91 	if (geteuid() != 0) {
92 		printf("Must be run as root\n");
93 		exit(1);
94 	}
95 
96 	/* Do switch parsing: */
97 	while ((c = getopt(argc, argv, "hiv:")) != -1) {
98 		switch (c) {
99 		case 'i':
100 			interactive = TRUE;
101 			break;
102 		case 'v':
103 			verbosity = atoi(optarg);
104 			break;
105 		case 'h':
106 		case '?':
107 		default:
108 			usage();
109 		}
110 	}
111 	argc -= optind; argv += optind;
112 	if (argc > 0) {
113 		pid = atoi(*argv);
114 	}
115 
116 	ret = task_for_pid(mach_task_self(), pid, &port);
117 	if (ret != KERN_SUCCESS) {
118 		err(1, "task_for_pid(,%d,) returned %d", pid, ret);
119 	}
120 
121 	mutter("task %p\n", port);
122 	ret = task_threads(port, &thread_array, &num_threads);
123 	if (ret != KERN_SUCCESS) {
124 		err(1, "task_threads() returned %d", pid, ret);
125 	}
126 
127 	for (i = 0; i < num_threads; i++) {
128 		printf(" %d: thread 0x%08x tag %d\n",
129 		    i, thread_array[i], thread_tag_get(thread_array[i]));
130 	}
131 
132 	while (interactive) {
133 		printf("Enter new tag or <return> to skip or ^D to quit\n");
134 		for (i = 0; i < num_threads; i++) {
135 			tag =  thread_tag_get(thread_array[i]);
136 			printf(" %d: thread 0x%08x tag %d: ",
137 			    i, thread_array[i], tag);
138 			fflush(stdout);
139 			(void) fgets(input, 20, stdin);
140 			if (feof(stdin)) {
141 				printf("\n");
142 				interactive = FALSE;
143 				break;
144 			}
145 			if (strlen(input) > 1) {
146 				tag = atoi(input);
147 				thread_tag_set(thread_array[i], tag);
148 			}
149 		}
150 	}
151 
152 	return 0;
153 }
154