/* 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 #include #include #include #include #include #include #include #include #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; }