Home | History | Annotate | Download | only in ht_affinity
      1 /***************************************************************************
      2                           HTaffinity.c  -  description
      3                              -------------------
      4     email                : sonic,zhang (at) 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 
     49 int 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 
    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 
    148 int 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 
    180 int 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
    214 int 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