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
25char *TCID = "smt_smp_affinity";
26int TST_TOTAL = 3;
27
28/************************************************************************************
29int set_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
30pid - pid of the process whose affinity is desired to be set.
31mask_ptr - pointer to the new cpu_affinity_mask.
32len - length in bytes of the bitmask pointed to by user_mask_ptr.
33
34int get_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
35pid - pid of the process whose affinity is being read.
36mask_ptr pointer to store the current affinity information.
37len - 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
49int HT_SetAffinity()
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
129unsigned 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
148int HT_GetAffinity()
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
180int HT_InheritAffinity()
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
214int main(int argc, char *argv[])
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