ovni/test/rt/nanos6/spawn-task-external.c

112 lines
2.3 KiB
C

/* Copyright (c) 2021-2023 Barcelona Supercomputing Center (BSC)
* SPDX-License-Identifier: GPL-3.0-or-later */
/* Spawn a task from an external thread that calls some nanos6
* functions. The external thread must be paused when the task pauses
* the execution. This emulates the same behavior as TAMPI when using a
* polling task. */
#define _GNU_SOURCE
#include <nanos6.h>
#include <nanos6/library-mode.h>
#include <time.h>
#include <pthread.h>
#include "common.h"
#include "compat.h"
#include "ovni.h"
static double
get_time_ms(void)
{
struct timespec ts;
clock_gettime(CLOCK_MONOTONIC, &ts);
return (double) ts.tv_sec + (double) ts.tv_nsec * 1.0e-9;
}
static void
dummy_work(double ms)
{
double end = get_time_ms() + ms * 1e-3;
while (get_time_ms() < end);
}
static void
polling_func(void *arg)
{
double ms = *((double *) arg);
double end = get_time_ms() + ms * 1e-3;
while (get_time_ms() < end) {
dummy_work(1.0); /* 1 ms */
nanos6_wait_for(1000UL); /* 1 ms */
}
}
static inline void
instr_thread_start(int32_t cpu, int32_t creator_tid, uint64_t tag)
{
ovni_thread_init(get_tid());
struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, "OHx");
ovni_ev_set_clock(&ev, ovni_clock_now());
ovni_payload_add(&ev, (uint8_t *) &cpu, sizeof(cpu));
ovni_payload_add(&ev, (uint8_t *) &creator_tid, sizeof(creator_tid));
ovni_payload_add(&ev, (uint8_t *) &tag, sizeof(tag));
ovni_ev_emit(&ev);
/* Flush the events to disk before killing the thread */
ovni_flush();
}
static inline void
instr_thread_end(void)
{
struct ovni_ev ev = {0};
ovni_ev_set_mcv(&ev, "OHe");
ovni_ev_set_clock(&ev, ovni_clock_now());
ovni_ev_emit(&ev);
/* Flush the events to disk before killing the thread */
ovni_flush();
}
/* Call the nanos6_spawn_function from an external thread */
static void *
spawn(void *arg)
{
/* Inform ovni of this external thread */
instr_thread_start(-1, -1, 0);
double ms = *((double *) arg);
nanos6_spawn_function(polling_func, &ms, NULL, NULL, "polling_task");
/* Then inform that the thread finishes */
instr_thread_end();
return NULL;
}
int
main(void)
{
pthread_t th;
double T = 100.0;
if (pthread_create(&th, NULL, spawn, &T) != 0)
die("pthread_create failed:");
if (pthread_join(th, NULL) != 0)
die("pthread_join failed:");
#pragma oss task label("dummy_task")
dummy_work(T);
#pragma oss taskwait
return 0;
}