uti: futex call function in mcctrl

Previously, futex code of McKerenl was called by mccontrol,
but there ware some problems with this method.
(Mainly, location of McKernel image on memory)

Call futex code in mcctrl instead of the one in McKernel image,
giving the following benefits:
1. Not relying on shared kernel virtual address space with Linux any more
2. The cpu id store / retrieve is not needed and resulting in the code

Change-Id: Ic40929b64a655b270c435859fa287fedb713ee5c
refe: #1428
This commit is contained in:
Ken Sato
2020-09-18 14:42:26 +09:00
committed by Masamichi Takagi
parent 35296c8210
commit a9973e913d
62 changed files with 4320 additions and 1116 deletions

View File

@@ -4,60 +4,57 @@
#include <string.h>
#include <pthread.h>
#include <errno.h>
#include <sys/mman.h>
#include <unistd.h>
#include <sys/syscall.h>
#include <linux/futex.h>
#include <sys/mman.h>
#include <signal.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdint.h>
#include <uti.h>
#include "util.h"
#define WAITER_CPU 0
#define WAKER_CPU 1
int sem;
pthread_mutex_t mutex;
pthread_cond_t cond;
pthread_barrier_t bar;
int flag;
pthread_t thr;
long t_futex_wait, t_fwq;
long t_cond_wait, t_fwq;
long nloop;
long blocktime = 10L * 1000 * 1000;
int linux_run;
void *util_fn(void *arg)
{
int i;
int ret;
long start, end;
int testid = 32101;
long start, end;
print_cpu_last_executed_on("Utility thread");
ret = syscall(732);
OKNGNOJUMP(ret == -1, "Utility thread is running on Linux\n");
pthread_barrier_wait(&bar);
for (i = 0; i < nloop; i++) {
start = rdtsc_light();
fwq(blocktime);
end = rdtsc_light();
t_fwq += end - start;
if ((ret = syscall(__NR_futex, &sem, FUTEX_WAKE, 1, NULL, NULL, 0)) == -1) {
printf("Error: futex wake: %s\n", strerror(errno));
}
//pthread_barrier_wait(&bar);
if (!linux_run) {
ret = syscall(732);
OKNGNOJUMP(ret == -1, "Utility thread is running on Linux\n");
}
pthread_barrier_wait(&bar);
for (i = 0; i < nloop; i++) {
start = rdtsc_light();
pthread_mutex_lock(&mutex); /* no futex */
while(!flag) {
pthread_cond_wait(&cond, &mutex); /* 1st futex */
}
flag = 0;
pthread_mutex_unlock(&mutex); /* 2nd futex */
end = rdtsc_light();
t_cond_wait += end - start;
}
ret = 0;
fn_fail:
return NULL;
}
@@ -71,21 +68,24 @@ int main(int argc, char **argv)
{
int i;
int ret;
long start, end;
long start, end;
cpu_set_t cpuset;
pthread_attr_t attr;
pthread_barrierattr_t bar_attr;
struct sched_param param = { .sched_priority = 99 };
int opt;
while ((opt = getopt_long(argc, argv, "+b:", options, NULL)) != -1) {
while ((opt = getopt_long(argc, argv, "+b:l", options, NULL)) != -1) {
switch (opt) {
case 'b':
blocktime = atoi(optarg);
break;
default: /* '?' */
printf("unknown option %c\n", optopt);
exit(1);
case 'b':
blocktime = atoi(optarg);
break;
case 'l':
linux_run = 1;
break;
default: /* '?' */
printf("unknown option %c\n", optopt);
exit(1);
}
}
nloop = (10 * 1000000000UL) / blocktime;
@@ -102,88 +102,66 @@ int main(int argc, char **argv)
fwq_init();
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
pthread_barrierattr_init(&bar_attr);
pthread_barrier_init(&bar, &bar_attr, 2);
if (!linux_run) {
ret = syscall(732);
OKNGNOJUMP(ret != -1, "Master thread is running on McKernel\n");
ret = syscall(731, 1, NULL);
OKNGNOJUMP(ret != -1, "util_indicate_clone\n");
}
if ((ret = pthread_attr_init(&attr))) {
printf("Error: pthread_attr_init: %s\n", strerror(errno));
printf("%s: Error: pthread_attr_init failed (%d)\n", __FUNCTION__, ret);
goto fn_fail;
}
#if 0
uti_attr_t uti_attr;
ret = uti_attr_init(&uti_attr);
if (ret) {
printf("%s: Error: uti_attr_init failed (%d)\n", __FUNCTION__, ret);
exit(1);
}
/* Give a hint that it's beneficial to prioritize it in scheduling. */
ret = UTI_ATTR_HIGH_PRIORITY(&uti_attr);
if (ret) {
printf("%s: Error: UTI_ATTR_HIGH_PRIORITY failed (%d)\n", __FUNCTION__, ret);
exit(1);
}
if ((ret = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED))) {
printf("%s: Error: pthread_attr_setdetachstate failed (%d)\n", __FUNCTION__, ret);
exit(1);
}
if ((ret = uti_pthread_create(&thr, &attr, progress_function, NULL, &uti_attr))) {
printf("%s: Error: uti_pthread_create: %s\n", __FUNCTION__, strerror(errno));
exit(1);
}
if ((ret = uti_attr_destroy(&uti_attr))) {
printf("%s: Error: uti_attr_destroy failed (%d)\n", __FUNCTION__, ret);
exit(1);
}
#else
CPU_ZERO(&cpuset);
CPU_SET(WAKER_CPU, &cpuset);
if ((ret = pthread_attr_setaffinity_np(&attr, sizeof(cpu_set_t), &cpuset))) {
printf("Error: pthread_attr_setaffinity_np: %s\n", strerror(errno));
printf("%s: Error: pthread_attr_setaffinity_np failed (%d)\n", __FUNCTION__, ret);
goto fn_fail;
}
ret = syscall(732);
OKNGNOJUMP(ret != -1, "Master thread is running on McKernel\n");
ret = syscall(731, 1, NULL);
OKNGNOJUMP(ret != -1, "util_indicate_clone\n");
if ((ret = pthread_create(&thr, &attr, util_fn, NULL))) {
printf("Error: pthread_create: %s\n", strerror(errno));
fprintf(stderr, "Error: pthread_create failed (%d)\n", ret);
goto fn_fail;
}
#endif
if ((ret = sched_setscheduler(0, SCHED_FIFO, &param))) {
printf("Error: sched_setscheduler: %s\n", strerror(errno));
ret = -errno;
goto fn_fail;
fprintf(stderr, "Warning: sched_setscheduler: %s\n",
strerror(errno));
}
syscall(701, 1 | 2);
if (!linux_run) {
syscall(701, 1 | 2);
}
pthread_barrier_wait(&bar);
start = rdtsc_light();
for (i = 0; i < nloop; i++) {
if ((ret = syscall(__NR_futex, &sem, FUTEX_WAIT, 0, NULL, NULL, 0))) {
printf("Error: futex wait failed (%s)\n", strerror(errno));
}
start = rdtsc_light();
//pthread_barrier_wait(&bar); /* 2nd futex */
fwq(blocktime);
end = rdtsc_light();
t_fwq += end - start;
pthread_mutex_lock(&mutex);
flag = 1;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
if (!linux_run) {
syscall(701, 4 | 8);
}
end = rdtsc_light();
t_futex_wait += end - start;
syscall(701, 4 | 8);
pthread_join(thr, NULL);
printf("[INFO] waiter: %ld cycles, waker: %ld cycles, (waiter - waker) / nloop: %ld cycles\n", t_fwq, t_futex_wait, (t_futex_wait - t_fwq) / nloop);
printf("[INFO] waker: %ld cycles, waiter: %ld cycles, (waiter - waker) / nloop: %ld cycles\n", t_fwq, t_cond_wait, (t_cond_wait - t_fwq) / nloop);
ret = 0;
fn_fail: