1 /***************************************************************************
2                           HTaffinity.c  -  description
3                              -------------------
4     email                : sonic,zhang@intel.com
5  ***************************************************************************/
6 
7 /***************************************************************************
8  *                                                                         *
9  *   This program is free software; you can redistribute it and/or modify  *
10  *   it under the terms of the GNU General Public License as published by  *
11  *   the Free Software Foundation; either version 2 of the License, or     *
12  *   (at your option) any later version.                                   *
13  *                                                                         *
14  ***************************************************************************/
15 #include "ht_utils.h"
16 #include <sys/syscall.h>
17 #include <sys/types.h>
18 #include <unistd.h>
19 #include <sys/wait.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include "test.h"
24 
25 char *TCID = "smt_smp_affinity";
26 int TST_TOTAL = 3;
27 
28 /************************************************************************************
29 int set_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
30 pid - pid of the process whose affinity is desired to be set.
31 mask_ptr - pointer to the new cpu_affinity_mask.
32 len - length in bytes of the bitmask pointed to by user_mask_ptr.
33 
34 int get_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
35 pid - pid of the process whose affinity is being read.
36 mask_ptr pointer to store the current affinity information.
37 len - length in bytes of the bitmask pointed to by user_mask_ptr.
38 ************************************************************************************/
39 
40 //Any application program can invoke these system call using sched_setaffinity() and sched_getaffinity(),
41 //with the syntax mentioned in the previous section, after declaring the interface as:
42 
43 #define sched_setaffinity(pid, cpusetsize, mask) syscall(__NR_sched_setaffinity, pid, cpusetsize, mask)
44 #define sched_getaffinity(pid, cpusetsize, mask) syscall(__NR_sched_getaffinity, pid, cpusetsize, mask)
45 
46 #define AFFINITY_NAME "affinity"
47 #define PROCFS_PATH "/proc/"
48 
HT_SetAffinity(void)49 int HT_SetAffinity(void)
50 {
51 	unsigned int mask;
52 	pid_t pid;
53 	int result = 1;
54 	int cpu_count, i, j, k, cpuid;
55 
56 	pid = getpid();
57 
58 	tst_resm(TINFO, "Set affinity through system call");
59 
60 	cpu_count = get_cpu_count();
61 	if (cpu_count == 0) {
62 		return 0;
63 	} else if (cpu_count > 32)
64 		cpu_count = 32;
65 
66 	for (i = 0, mask = 0x1; i < cpu_count; i++, mask = mask << 1) {
67 		tst_resm(TINFO, "Set test process affinity.");
68 		printf("mask: %x\n", mask);
69 
70 		sched_setaffinity(pid, sizeof(unsigned long), &mask);
71 
72 		for (j = 0; j < 10; j++) {
73 			for (k = 0; k < 10; k++) {
74 				if (fork() == 0) {
75 					system("ps > /dev/null");
76 					exit(0);
77 				}
78 			}
79 
80 			sleep(1);
81 
82 			if (get_current_cpu(pid) != i)
83 				break;
84 		}
85 
86 		if (j < 10) {
87 			tst_resm(TINFO, "...Error");
88 			result = 0;
89 		} else
90 			tst_resm(TINFO, "...OK");
91 
92 	}
93 
94 	for (i = 0, mask = 0x3; i < cpu_count - 1; i++, mask = mask << 1) {
95 		tst_resm(TINFO, "Set test process affinity.");
96 		printf("mask: %x\n", mask);
97 
98 		sched_setaffinity(pid, sizeof(unsigned long), &mask);
99 
100 		for (j = 0; j < 10; j++) {
101 			for (k = 0; k < 10; k++) {
102 				if (fork() == 0) {
103 					system("ps > /dev/null");
104 					exit(0);
105 				}
106 			}
107 
108 			sleep(1);
109 
110 			cpuid = get_current_cpu(pid);
111 			if (cpuid != i && cpuid != i + 1)
112 				break;
113 		}
114 
115 		if (j < 10) {
116 			tst_resm(TINFO, "...Error");
117 			result = 0;
118 		} else
119 			tst_resm(TINFO, "...OK");
120 
121 	}
122 
123 	if (result)
124 		return 1;
125 	else
126 		return 0;
127 }
128 
get_porc_affinity(pid_t pid)129 unsigned long get_porc_affinity(pid_t pid)
130 {
131 	FILE *pfile;
132 
133 	sprintf(buf, "%s%d/%s%c", PROCFS_PATH, pid, AFFINITY_NAME, 0);
134 
135 	if ((pfile = fopen(buf, "r")) == NULL)
136 		return 0;
137 
138 	if (fgets(buf, 255, pfile) == NULL) {
139 		fclose(pfile);
140 		return 0;
141 	}
142 
143 	fclose(pfile);
144 
145 	return atol(buf);
146 }
147 
HT_GetAffinity(void)148 int HT_GetAffinity(void)
149 {
150 	unsigned int mask[2], mask1[2];
151 	pid_t pid;
152 
153 	mask[0] = 0x1;
154 	pid = getpid();
155 
156 	tst_resm(TINFO, "Get affinity through system call");
157 
158 	sched_setaffinity(pid, sizeof(mask), mask);
159 
160 	sleep(1);
161 
162 	sched_getaffinity(pid, sizeof(mask), mask1);
163 
164 	if (mask[0] == 0x1 && mask[0] == mask1[0]) {
165 		mask[0] = 0x2;
166 		sched_setaffinity(pid, sizeof(mask), mask);
167 
168 		sleep(1);
169 
170 		sched_getaffinity(pid, sizeof(mask), mask1);
171 
172 		if (mask[0] == 0x2 && mask[0] == mask1[0])
173 			return 1;
174 		else
175 			return 0;
176 	} else
177 		return 0;
178 }
179 
HT_InheritAffinity(void)180 int HT_InheritAffinity(void)
181 {
182 	unsigned int mask[2];
183 	pid_t pid;
184 	int status;
185 	mask[0] = 0x2;
186 	pid = getpid();
187 
188 	sched_setaffinity(pid, sizeof(mask), mask);
189 
190 	sleep(1);
191 	pid = fork();
192 	if (pid == 0) {
193 		sleep(1);
194 		sched_getaffinity(pid, sizeof(mask), mask);
195 		if (mask[0] == 0x2)
196 			exit(0);
197 
198 		else
199 			exit(1);
200 	} else if (pid < 0) {
201 		tst_resm(TINFO, "Inherit affinity:fork failed!");
202 		return 0;
203 	}
204 	waitpid(pid, &status, 0);
205 
206 	if (WEXITSTATUS(status) == 0) {
207 		tst_resm(TINFO, "Inherited affinity from parent process");
208 		return 1;
209 	} else
210 		return 0;
211 }
212 
213 // return 0 means Pass, return 1 means Fail
main(void)214 int main(void)
215 {
216 
217 #if (!defined __i386__ && !defined __x86_64__)
218 	tst_brkm(TCONF, NULL,
219 		 "This test suite can only execute on x86 architecture.");
220 #else
221 	if (!check_ht_capability()) {
222 
223 		if (HT_GetAffinity())
224 			tst_resm(TPASS, "System call getaffinity() is OK.");
225 		else
226 			tst_resm(TFAIL, "System call getaffinity() is error.");
227 
228 		printf("\n");
229 
230 		if (HT_InheritAffinity())
231 			tst_resm(TPASS, "Inheritance of affinity is OK.");
232 		else
233 			tst_resm(TFAIL, "Inheritance of affinity is error.");
234 
235 		printf("\n");
236 
237 		if (HT_SetAffinity())
238 			tst_resm(TPASS, "System call setaffinity() is OK.");
239 		else
240 			tst_resm(TFAIL, "System call setaffinity() is error.");
241 	} else {
242 		tst_brkm(TCONF, NULL, "HT is not enabled or not supported.");
243 	}
244 #endif
245 
246 	tst_exit();
247 }
248