/***************************************************************************
HTaffinity.c - description
-------------------
email : sonic,zhang@intel.com
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#include "ht_utils.h"
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "test.h"
char *TCID = "smt_smp_affinity";
int TST_TOTAL = 3;
/************************************************************************************
int set_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
pid - pid of the process whose affinity is desired to be set.
mask_ptr - pointer to the new cpu_affinity_mask.
len - length in bytes of the bitmask pointed to by user_mask_ptr.
int get_affinity(pid_t pid, unsigned int len, unsigned long *mask_ptr)
pid - pid of the process whose affinity is being read.
mask_ptr pointer to store the current affinity information.
len - length in bytes of the bitmask pointed to by user_mask_ptr.
************************************************************************************/
//Any application program can invoke these system call using sched_setaffinity() and sched_getaffinity(),
//with the syntax mentioned in the previous section, after declaring the interface as:
#define sched_setaffinity(pid, cpusetsize, mask) syscall(__NR_sched_setaffinity, pid, cpusetsize, mask)
#define sched_getaffinity(pid, cpusetsize, mask) syscall(__NR_sched_getaffinity, pid, cpusetsize, mask)
#define AFFINITY_NAME "affinity"
#define PROCFS_PATH "/proc/"
int HT_SetAffinity()
{
unsigned int mask;
pid_t pid;
int result = 1;
int cpu_count, i, j, k, cpuid;
pid = getpid();
tst_resm(TINFO, "Set affinity through system call");
cpu_count = get_cpu_count();
if (cpu_count == 0) {
return 0;
} else if (cpu_count > 32)
cpu_count = 32;
for (i = 0, mask = 0x1; i < cpu_count; i++, mask = mask << 1) {
tst_resm(TINFO, "Set test process affinity.");
printf("mask: %x\n", mask);
sched_setaffinity(pid, sizeof(unsigned long), &mask);
for (j = 0; j < 10; j++) {
for (k = 0; k < 10; k++) {
if (fork() == 0) {
system("ps > /dev/null");
exit(0);
}
}
sleep(1);
if (get_current_cpu(pid) != i)
break;
}
if (j < 10) {
tst_resm(TINFO, "...Error");
result = 0;
} else
tst_resm(TINFO, "...OK");
}
for (i = 0, mask = 0x3; i < cpu_count - 1; i++, mask = mask << 1) {
tst_resm(TINFO, "Set test process affinity.");
printf("mask: %x\n", mask);
sched_setaffinity(pid, sizeof(unsigned long), &mask);
for (j = 0; j < 10; j++) {
for (k = 0; k < 10; k++) {
if (fork() == 0) {
system("ps > /dev/null");
exit(0);
}
}
sleep(1);
cpuid = get_current_cpu(pid);
if (cpuid != i && cpuid != i + 1)
break;
}
if (j < 10) {
tst_resm(TINFO, "...Error");
result = 0;
} else
tst_resm(TINFO, "...OK");
}
if (result)
return 1;
else
return 0;
}
unsigned long get_porc_affinity(pid_t pid)
{
FILE *pfile;
sprintf(buf, "%s%d/%s%c", PROCFS_PATH, pid, AFFINITY_NAME, 0);
if ((pfile = fopen(buf, "r")) == NULL)
return 0;
if (fgets(buf, 255, pfile) == NULL) {
fclose(pfile);
return 0;
}
fclose(pfile);
return atol(buf);
}
int HT_GetAffinity()
{
unsigned int mask[2], mask1[2];
pid_t pid;
mask[0] = 0x1;
pid = getpid();
tst_resm(TINFO, "Get affinity through system call");
sched_setaffinity(pid, sizeof(mask), mask);
sleep(1);
sched_getaffinity(pid, sizeof(mask), mask1);
if (mask[0] == 0x1 && mask[0] == mask1[0]) {
mask[0] = 0x2;
sched_setaffinity(pid, sizeof(mask), mask);
sleep(1);
sched_getaffinity(pid, sizeof(mask), mask1);
if (mask[0] == 0x2 && mask[0] == mask1[0])
return 1;
else
return 0;
} else
return 0;
}
int HT_InheritAffinity()
{
unsigned int mask[2];
pid_t pid;
int status;
mask[0] = 0x2;
pid = getpid();
sched_setaffinity(pid, sizeof(mask), mask);
sleep(1);
pid = fork();
if (pid == 0) {
sleep(1);
sched_getaffinity(pid, sizeof(mask), mask);
if (mask[0] == 0x2)
exit(0);
else
exit(1);
} else if (pid < 0) {
tst_resm(TINFO, "Inherit affinity:fork failed!");
return 0;
}
waitpid(pid, &status, 0);
if (WEXITSTATUS(status) == 0) {
tst_resm(TINFO, "Inherited affinity from parent process");
return 1;
} else
return 0;
}
// return 0 means Pass, return 1 means Fail
int main(int argc, char *argv[])
{
#if (!defined __i386__ && !defined __x86_64__)
tst_brkm(TCONF, NULL,
"This test suite can only execute on x86 architecture.");
#else
if (!check_ht_capability()) {
if (HT_GetAffinity())
tst_resm(TPASS, "System call getaffinity() is OK.");
else
tst_resm(TFAIL, "System call getaffinity() is error.");
printf("\n");
if (HT_InheritAffinity())
tst_resm(TPASS, "Inheritance of affinity is OK.");
else
tst_resm(TFAIL, "Inheritance of affinity is error.");
printf("\n");
if (HT_SetAffinity())
tst_resm(TPASS, "System call setaffinity() is OK.");
else
tst_resm(TFAIL, "System call setaffinity() is error.");
} else {
tst_brkm(TCONF, NULL, "HT is not enabled or not supported.");
}
#endif
tst_exit();
}