Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions Makefile.am
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
AM_MAKEFLAGS=CC="$(CC)"
if SET_DLSCHED
SUBDIRS = libdl src
SUBDIRS = libdl src rtapp_function
else
SUBDIRS = src
SUBDIRS = src rtapp_function
endif

1 change: 1 addition & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ AC_HEADER_STDC
AC_CHECK_LIB([pthread], [pthread_create])
AC_CHECK_LIB([m], [round])
AC_CHECK_LIB([rt], [clock_gettime])
AC_CHECK_LIB([dl], [dlopen])
AC_CHECK_LIB([json-c], [json_object_from_file], [], [AC_MSG_ERROR([json-c libraries required])])
AC_CHECK_FUNCS(sched_setattr, [], [])

Expand Down
41 changes: 41 additions & 0 deletions doc/examples/tutorial/example9.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
{
"tasks" : {
"thread0" : {
"loop" : 3,
"phases" : {
"phase0" : {
"external_workload0" : {
"library_name" : "test_workload/test.so",
"main_method" : "test1"
},
"external_workload1" : {
"library_name" : "test_workload/test.so",
"main_method" : "test1"
}
},
"phase1" : {
"external_workload" : {
"library_name" : "test_workload/test.so",
"main_method" : "test2"
}
}
}
}
},
"global" : {
"calibration" : "CPU0",
"default_policy" : "SCHED_OTHER",
"pi_enabled" : false,
"lock_pages" : false,
"logdir" : "./",
"log_basename" : "rt-app9",
"ftrace" : false,
"gnuplot" : false
}
}






9 changes: 9 additions & 0 deletions doc/tutorial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -533,6 +533,15 @@ taskB ...-------------------|resume taskA|run 10 |--------------------
* yield: String. Calls pthread_yield(), freeing the CPU for other tasks. This has a
special meaning for SCHED_DEADLINE tasks. String can be empty.

* external_workload: {"library_name" : "base_dir/lib.so", "main_method" : "method_name" }
Executes a function declared in a shared library. The shared libraries are stored at
rtapp_function/<workload base directory>/ .
For each c file present in the workload base directory a shared library is compiled. The
external_workload is defined, in the rt-app taskset definition, by two fields:
1) library_name - The shared library where the function is to be loaded from. This
name is relative to the rtapp_function directory;
2) main_method - The name of the function to be called.

**** Trace and Log ****

Some traces and log hooks have been added to ease the debug and monitor various
Expand Down
14 changes: 14 additions & 0 deletions rtapp_function/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
SOURCE = $(wildcard */*.c)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, I'm wondering if pulling "random" code into rt-app sources is really a good idea.
I guess we are basically subscribing to maintaining all the snippets we import.. :-(
Alternatives?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agree, this should be mostly a mechanism to allow for random code to be used as rt-app phases. Only very select and generic code snippets should be committed to rt-app. The current workload which is part of the PR has the purpose of showcasing that the mechanism works for complex workloads, it should not be part of the PR when it hypothetically gets merged.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm OK. I wonder what's the best way to make life easy for potential users of this new feature, though. I guess having a very simple example in the repo would certainly help. And I also guess adding substantial documentation to tutorial.txt should help as well.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

created a simple workload which just prints an integer. The workload has two methods that behave differently with respect to the integer increment.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added documentation to doc/tutorial.txt detailing the external_workload event.

LIBRARIES = $(SOURCE:.c=.so)

.PHONY: all clean

all: $(LIBRARIES)

clean:
echo "cleaning libraries"
rm -f */*.so

%.so : %.c
@echo "*** building external workload $(<:.c=)"
$(CC) $^ -rdynamic -shared -fPIC -o $@
18 changes: 18 additions & 0 deletions rtapp_function/test_workload/test.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#include <stdio.h>

volatile int testVar = 0;

int test1() {

testVar++;
printf("first test %d\n", testVar);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Mmm, this breaks rt-app log_* output format. :-/
Wonder if we can make that available to external workloads and actually enforce that is used?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are the external workloads generally expected to call printf or do any logging for that matter? Is this really required?


return 0;
}

int test2() {

printf("second test %d\n", testVar);

return 0;
}
11 changes: 11 additions & 0 deletions src/rt-app.c
Original file line number Diff line number Diff line change
Expand Up @@ -413,6 +413,17 @@ static int run_event(event_data_t *event, int dry_run,
pthread_yield();
}
break;
case rtapp_external_workload:
{
struct timespec t_start, t_end;
log_debug("external workload execution %s:%s ", rdata->res.external_workload.library_name, rdata->res.external_workload.symbol_name);
clock_gettime(CLOCK_MONOTONIC, &t_start);
rdata->res.external_workload.workload(ldata);
clock_gettime(CLOCK_MONOTONIC, &t_end);
t_end = timespec_sub(&t_end, &t_start);
ldata->duration += timespec_to_usec(&t_end);
}
break;
default:
break;
}
Expand Down
47 changes: 47 additions & 0 deletions src/rt-app_args.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <string.h>
#include <sys/stat.h>
#include <getopt.h>
#include <limits.h>
#include <errno.h>

#include "rt-app_utils.h"
#include "rt-app_parse_config.h"

char help_usage[] = \
Expand Down Expand Up @@ -60,11 +63,55 @@ struct option long_args[] = {
{0, 0, 0, 0}
};

static char* main_install_path = NULL;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No need to initialize this to NULL.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removed initialisation.


char const* get_shared_library_base_path()
{
return main_install_path;
}

void
parse_command_line(int argc, char **argv, rtapp_options_t *opts)
{
struct stat config_file_stat;
int c;
int full_path_len;
int main_install_path_len;

const char shared_lib_dir_name[] = "/../rtapp_function/";

/* get the rt-app base directory full name */
char* full_path = malloc(PATH_MAX);
int index;
int return_snprintf = 0;

/* get the program invocation string and extract the base directory content */
if (!realpath(argv[0], full_path)) {
log_error("failed to get rt-app base path: %s", strerror(errno));
exit(EXIT_FAILURE);
}

for(index=strlen(full_path)-1; index>0; index--) {
if(full_path[index]=='/') {
full_path[index]='\0';
break;
}
}

full_path_len = strlen(full_path);

main_install_path_len = full_path_len + sizeof(shared_lib_dir_name) + 1;
main_install_path = malloc(main_install_path_len);
if (!main_install_path) {
log_error("failed to allocate %d bytes: %s", main_install_path_len, strerror(errno));
exit(EXIT_FAILURE);
}

return_snprintf = snprintf(main_install_path, main_install_path_len,"%s%s", full_path, shared_lib_dir_name);
if(return_snprintf >= main_install_path_len || return_snprintf < 0) {
log_error("failed to compose install path\n");
exit(EXIT_FAILURE);
}

while (1) {
c = getopt_long(argc, argv, "hv", long_args, 0);
Expand Down
1 change: 1 addition & 0 deletions src/rt-app_args.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,4 +30,5 @@ usage (const char* msg, int ex_code);
void
parse_command_line(int argc, char **argv, rtapp_options_t *opts);

char const* get_shared_library_base_path();
#endif // _RTAPP_ARGS_H_
84 changes: 84 additions & 0 deletions src/rt-app_parse_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,10 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <string.h>
#include <fcntl.h>
#include <json-c/json.h>
#include <dlfcn.h>

#include "rt-app_utils.h"
#include "rt-app_args.h"
#include "rt-app_parse_config.h"

#define PFX "[json] "
Expand Down Expand Up @@ -363,6 +365,57 @@ static char* create_unique_name(char *tmp, int size, const char* ref, long tag)
return tmp;
}

void initialise_external_library(rtapp_resource_t *rdata)
{
void *library_handle;
void *symbol;
char const* shared_library_dir_name = NULL;
char *full_library_name = NULL;

char *library_name = rdata->res.external_workload.library_name;
int base_path_len = 0;
int lib_name_len = 0;
int full_library_name_length = 0;
int return_snprintf;

shared_library_dir_name = get_shared_library_base_path();
if (!shared_library_dir_name) {
log_error("failed to obtain shared library directory\n");

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exit(EXIT_FAILURE)?
Also please don't mix declarations and code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

exit(EXIT_FAILURE);
}

base_path_len = strlen(shared_library_dir_name);
lib_name_len = strlen(library_name);
full_library_name_length = base_path_len + lib_name_len +1;

full_library_name = malloc(full_library_name_length);
if (!full_library_name) {
log_error("failed to allocate memory for library name\n");
exit(EXIT_FAILURE);
}

return_snprintf = snprintf(full_library_name, full_library_name_length, "%s%s", shared_library_dir_name, library_name);
if(return_snprintf >= full_library_name_length || return_snprintf < 0) {
log_error("failed to compose the full library name\n");
exit(EXIT_FAILURE);
}

library_handle = dlopen(full_library_name, RTLD_NOW | RTLD_LOCAL);
if(library_handle == NULL) {
log_info(PIN2 "failed to open shared library: %s\n", dlerror());
exit(EXIT_FAILURE);
}
free(full_library_name);

symbol = dlsym(library_handle, rdata->res.external_workload.symbol_name);
if(!symbol) {
log_info(PIN2 "failed to open obtain symbol: %s\n", dlerror());
exit(EXIT_FAILURE);
}

rdata->res.external_workload.workload = symbol;
}

static void
parse_thread_event_data(char *name, struct json_object *obj,
event_data_t *data, rtapp_options_t *opts, long tag)
Expand Down Expand Up @@ -517,6 +570,36 @@ parse_thread_event_data(char *name, struct json_object *obj,
return;
}

if (!strncmp(name, "external_workload", strlen("external_workload"))) {

data->type = rtapp_external_workload;

ref = json_object_get_string(obj);

i = add_resource_data(name, rtapp_external_workload, opts);

data->res = i;
rdata = &(opts->resources[data->res]);

/*
* Get the name of the shared library as well as
* the optional method name
*/
rdata->res.external_workload.library_name = get_string_value_from(obj, "library_name", FALSE, "");

tmp = get_string_value_from(obj, "main_method", TRUE, "workload");
rdata->res.external_workload.symbol_name = tmp;

log_info(PIN2 "type %d target %s [%d] lib name %s, workload %s\n",
data->type, rdata->name, rdata->index, rdata->res.external_workload.library_name,
rdata->res.external_workload.symbol_name);

/* Load the symbol in the dynamic library */
initialise_external_library(rdata);

return;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nitpick!
Add a space below.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.


if (!strncmp(name, "timer", strlen("timer"))) {

tmp = get_string_value_from(obj, "ref", TRUE, "unknown");
Expand Down Expand Up @@ -631,6 +714,7 @@ static char *events[] = {
"iorun",
"yield",
"barrier",
"external_workload",
NULL
};

Expand Down
10 changes: 9 additions & 1 deletion src/rt-app_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,8 @@ typedef enum resource_t
rtapp_iorun,
rtapp_runtime,
rtapp_yield,
rtapp_barrier
rtapp_barrier,
rtapp_external_workload,
} resource_t;

struct _rtapp_mutex {
Expand Down Expand Up @@ -118,6 +119,12 @@ struct _rtapp_iodev {
int fd;
};

struct _rtapp_external_workload {
char *library_name;
char *symbol_name;
int (*workload)();
};

/* Shared resources */
typedef struct _rtapp_resource_t {
union {
Expand All @@ -128,6 +135,7 @@ typedef struct _rtapp_resource_t {
struct _rtapp_iomem_buf buf;
struct _rtapp_iodev dev;
struct _rtapp_barrier_like barrier;
struct _rtapp_external_workload external_workload;
} res;
int index;
resource_t type;
Expand Down