Files
mckernel/test/sve/src/015.c
Shiratori, Takehiro 7da5fede8b Test "Scalable Vector Extension (SVE) support." on arm64
Change-Id: I3abaca932985a06b06887b962e769f2eac96c738
2019-02-27 06:26:00 +00:00

260 lines
5.2 KiB
C

/* 015.c COPYRIGHT FUJITSU LIMITED 2016-2019 */
/* Context switch in the same core check and SIGSTOP -> SIGCONT
* restart check.(need run on background '&')
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/mman.h>
#include <arm_neon.h>
#include <sys/types.h>
#include <unistd.h>
#include <sched.h>
#include <errno.h>
#include "common.h"
static sem_t *sync_sem1;
static sem_t *sync_sem2;
static int *parent_core;
static int *sync_flag;
#define CHILD_DONE 1
#define PARENT_DONE 2
static int *child_count;
static void child_func(unsigned int vq)
{
const unsigned int cmp_reg = vq * 2;
uint64_t a[cmp_reg], b[cmp_reg];
int i = 0;
pid_t pid = getpid();
printf("[child] pid = %d\n", pid);
for (i = 0; i < cmp_reg; i++) {
a[i] = pid + i;
}
asm volatile(
".cpu cortex-a53+fp+simd+sve\n\t"
"ldr z31, [%0]\n\t"
:
: "r"(a)
:
);
for (;;) {
asm volatile(
"add z31.d, z31.d,#1\n\t"
"str z31, [%0]\n\t"
:
: "r"(b)
:
);
for (i = 0; i < cmp_reg; i++) {
a[i] = a[i] + 1;
if (a[i] != b[i]) {
printf("[child] sve failed."
"a[%d]=%lu,b[%d]=%lu\n",
i, a[i], i, b[i]);
*child_count = -1;
return;
}
}
*sync_flag = CHILD_DONE;
while (*sync_flag != PARENT_DONE) {
cpu_pause();
}
(*child_count)++;
cpu_pause();
}
}
static void parent_func(void)
{
uint32x4_t vec_a, vec_b, vec_result;
uint32_t data1[4] __attribute__((aligned(128)));
uint32_t data2[4] __attribute__((aligned(128))) = {1, 2, 3, 4};
pid_t pid;
int i = 0;
pid = getpid();
printf("[parent] pid = %d\n", pid);
data1[0] = pid + 1;
data1[1] = pid + 2;
data1[2] = pid + 3;
data1[3] = pid + 4;
vec_a = vld1q_u32(data1);
vec_b = vld1q_u32(data2);
for (;;) {
*sync_flag = PARENT_DONE;
while (*sync_flag != CHILD_DONE) {
cpu_pause();
}
vec_result = vec_a - vec_b;
if ((vgetq_lane_u32(vec_result, 0) != pid)
|| (vgetq_lane_u32(vec_result, 1) != pid)
|| (vgetq_lane_u32(vec_result, 2) != pid)
|| (vgetq_lane_u32(vec_result, 3) != pid)) {
printf("error\n");
return;
}
printf("[parent] loop ok. (%d)\n", i);
if (*child_count != -1) {
printf("[child] loop ok. (%d)\n", *child_count);
}
else {
return;
}
i++;
cpu_pause();
}
}
TEST_FUNC(TEST_NUMBER, unused1, vq, unused3, unused4)
{
pid_t pid = 0;
print_test_overview(tp_num);
/* get shared memory */
sync_sem1 = (sem_t *)mmap(NULL, sizeof(sem_t),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
sync_sem2 = (sem_t *)mmap(NULL, sizeof(sem_t),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
parent_core = (int *)mmap(NULL, sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
sync_flag = (int *)mmap(NULL, sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
child_count = (int *)mmap(NULL, sizeof(int),
PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, 0);
*parent_core = 0;
*sync_flag = 0;
*child_count = 0;
/* semaphore init */
sem_init(sync_sem1, 1, 0);
sem_init(sync_sem2, 1, 0);
/* create child process */
pid = fork();
switch (pid) {
case -1:
/* fork() error. */
perror("fork()");
return -1;
case 0: {
/* child process */
/* before migrate, get cpunum */
int old_mycore = sched_getcpu();
int new_mycore = -1;
printf("[child] running core %d\n", old_mycore);
/* sync parent */
sem_post(sync_sem1);
/* sync parent */
sem_wait(sync_sem2);
/* after migrate, get cpunum */
new_mycore = sched_getcpu();
/* corenum check. */
if (*parent_core != old_mycore) {
printf("[child] before migrate prevcore "
"%d, nowcore %d\n", old_mycore, new_mycore);
if (old_mycore == new_mycore) {
printf("TP failed, "
"not migrate child process.\n");
exit(-1);
}
} else {
printf("[child] migrate not required.\n");
}
/* loop */
child_func(vq);
/* unmap */
munmap(sync_sem1, sizeof(sem_t));
munmap(sync_sem2, sizeof(sem_t));
munmap(parent_core, sizeof(int));
munmap(sync_flag, sizeof(int));
munmap(child_count, sizeof(int));
/* child exit */
exit(-1);
break;
}
default: {
/* parent process */
cpu_set_t cpuset;
int result = -1;
/* sync child */
sem_wait(sync_sem1);
/* parent corenum get */
*parent_core = sched_getcpu();
/* child process to migrate parent core */
printf("[parent] running core %d\n", *parent_core);
printf("[parent] child process migrate/bind "
"to core %d\n", *parent_core);
CPU_ZERO(&cpuset);
CPU_SET(*parent_core, &cpuset);
result = sched_setaffinity(pid, sizeof(cpuset), &cpuset);
if (result == -1) {
printf("errno = %d\n", errno);
break;
}
/* parent core bind */
printf("[parent] parent process bind "
"to core %d\n", *parent_core);
result = sched_setaffinity(0, sizeof(cpuset), &cpuset);
if (result == -1) {
printf("errno = %d\n", errno);
break;
}
/* sync child */
sem_post(sync_sem2);
/* loop */
parent_func();
/* unmap */
munmap(sync_sem1, sizeof(sem_t));
munmap(sync_sem2, sizeof(sem_t));
munmap(parent_core, sizeof(int));
munmap(sync_flag, sizeof(int));
munmap(child_count, sizeof(int));
break;
}
}
/* never return */
printf("RESULT: NG.\n");
return 0;
}