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
32 changes: 32 additions & 0 deletions doc/tutorial.txt
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,38 @@ inherit the affinity from the task level):
}
}

*** Core Scheduling

* core_scheduling_family: Integer. If two or more tasks have the same family, they will share their Core Scheduling Cookie.
* core_scheduling_families_count: Integer. Number of core scheduling families to be created.

"core_scheduling_family" can only be specified at task level.
"core_scheduling_families_count" is a global parameter.
In the example below it creates 2 threads with different core scheduling cookie.
"tasks" : {
"thread1" : {
"core_scheduling_family" : 1,
"phases" : {
"phase1" : {
"run" : 10,
"sleep" : 10
}
}
}
"thread2" : {
"core_scheduling_family" : 2,
"phases" : {
"phase1" : {
"run" : 10,
"sleep" : 10
}
}
}
},
"global":{
"core_scheduling_families_count": 2
}

*** Utilization Clamping

util_min: Integer. Can be specified at task level or phase level. Sets the min
Expand Down
75 changes: 72 additions & 3 deletions src/rt-app.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,24 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
#include <unistd.h>
#include <errno.h>

/* Core scheduling libraries */
#include <ctype.h>
#include <sys/prctl.h>
#include <linux/version.h>
#include <semaphore.h>
#include <sys/ptrace.h>
#include <linux/ptrace.h>

#if LINUX_VERSION_CODE <= KERNEL_VERSION(5,16,0)

typedef enum {PIDTYPE_PID,PIDTYPE_TGID,PIDTYPE_PGID,PIDTYPE_SID,PIDTYPE_MAX}pid_type;

#define PR_SCHED_CORE_SCOPE_THREAD 0
#define PR_SCHED_CORE_SCOPE_THREAD_GROUP 1
#define PR_SCHED_CORE_SCOPE_PROCESS_GROUP 2

#endif

#include "config.h"
#include "rt-app_utils.h"
#include "rt-app_args.h"
Expand All @@ -63,6 +81,9 @@ static pthread_barrier_t threads_barrier;
static pthread_mutex_t joining_mutex;
static pthread_mutex_t fork_mutex;

static pid_t *core_scheduling_first_threads;
static pthread_mutex_t core_scheduling_mutex;

static ftrace_data_t ft_data = {
.debugfs = "/sys/kernel/debug",
.marker_fd = -1,
Expand Down Expand Up @@ -736,6 +757,7 @@ static void __shutdown(bool force_terminate)
free(threads[i].data);
}

free(core_scheduling_first_threads);

log_ftrace(ft_data.marker_fd, FTRACE_MAIN,
"rtapp_main: event=end");
Expand All @@ -745,7 +767,6 @@ static void __shutdown(bool force_terminate)
}

remove_cgroups();

/*
* If we unlock the joining_mutex here we could risk a late SIGINT
* causing us to re-enter this loop. Since we are calling exit() to
Expand Down Expand Up @@ -1144,7 +1165,33 @@ void *thread_body(void *arg)
perror("pthread_setname_np thread name over 16 characters");
}

/* Get the 1st phase's data */
/* Set core scheduling family */
if (data->core_scheduling_family != 0) {
if (opts.core_scheduling_families_count >= data->core_scheduling_family) {
pthread_mutex_lock(&core_scheduling_mutex);
if (core_scheduling_first_threads[data->core_scheduling_family-1] != 0) {
if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_SHARE_FROM,
core_scheduling_first_threads[data->core_scheduling_family-1],
PR_SCHED_CORE_SCOPE_THREAD, 0)) {
perror("Error copying core scheduling cookie");
}
} else {
core_scheduling_first_threads[data->core_scheduling_family-1] = gettid();
if (prctl(PR_SCHED_CORE, PR_SCHED_CORE_CREATE,
gettid(), PR_SCHED_CORE_SCOPE_THREAD, 0)) {
perror("Error creating core scheduling cookie");
}
}
pthread_mutex_unlock(&core_scheduling_mutex);
}

u_long test;
prctl(PR_SCHED_CORE, PR_SCHED_CORE_GET, gettid(), PR_SCHED_CORE_SCOPE_THREAD, &test);
log_notice("[%d] Core scheduling cookie set to %lu, family %d",
data->ind, test, data->core_scheduling_family);
}

/* Get the 1st phase's data */
pdata = &data->phases[0];

/* Init timing buffer */
Expand Down Expand Up @@ -1507,7 +1554,7 @@ static void setup_main_gnuplot(void)

int main(int argc, char* argv[])
{
int i, res, nresources;
int i, k, res, nresources;
rtapp_resource_t *rdata;
static cpu_set_t orig_set;
struct stat sb;
Expand Down Expand Up @@ -1597,6 +1644,20 @@ int main(int argc, char* argv[])
/* Sync timer resources with start time */
clock_gettime(CLOCK_MONOTONIC, &t_start);

/* Setup core scheduling */
if (opts.core_scheduling_families_count == -1) {
for (k = 0; k < opts.num_tasks; k++) {
if (opts.threads_data[k].core_scheduling_family > opts.core_scheduling_families_count) {
opts.core_scheduling_families_count = opts.threads_data[k].core_scheduling_family;
}
}
}
core_scheduling_first_threads = malloc(sizeof (pid_t) * opts.core_scheduling_families_count);
for (i = 0; i < opts.core_scheduling_families_count; i++) {
core_scheduling_first_threads[i] = 0;
}
pthread_mutex_init(&core_scheduling_mutex, NULL);

/* Start the use case */
int ind = 0;
for (i = 0; i < opts.num_tasks; i++) {
Expand All @@ -1620,6 +1681,14 @@ int main(int argc, char* argv[])
goto exit_err;
}

if((tdata_orig->core_scheduling_family > 0 &&
tdata_orig->core_scheduling_family > opts.core_scheduling_families_count) ||
tdata_orig->core_scheduling_family < 0) {
log_error("Thread core_scheduling_family (%d) bigger then core_scheduling_families_count (%d)",
tdata_orig->core_scheduling_family, opts.core_scheduling_families_count);
goto exit_err;
}

for (j = 0; j < tdata_orig->num_instances; j++) {
int ret = create_thread(tdata_orig, ind++, 0, 0);
if (ret) {
Expand Down
7 changes: 6 additions & 1 deletion src/rt-app_parse_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -1083,7 +1083,10 @@ parse_task_data(char *name, struct json_object *obj, int index,
data->forked = 0;
data->num_instances = get_int_value_from(obj, "instance", TRUE, 1);

/* Get phases */
/* Get core scheduling cookie if set */
data->core_scheduling_family = get_int_value_from(obj, "core_scheduling_family", TRUE, 0);

/* Get phases */
phases_obj = get_in_object(obj, "phases", TRUE);
if (phases_obj) {
/* used in the foreach macro */
Expand Down Expand Up @@ -1211,6 +1214,8 @@ parse_global(struct json_object *global, rtapp_options_t *opts)
}

opts->duration = get_int_value_from(global, "duration", TRUE, -1);
opts->core_scheduling_families_count = get_int_value_from(global, "core_scheduling_families_count",
TRUE, -1);
opts->gnuplot = get_bool_value_from(global, "gnuplot", TRUE, 0);
policy = get_string_value_from(global, "default_policy",
TRUE, "SCHED_OTHER");
Expand Down
4 changes: 4 additions & 0 deletions src/rt-app_types.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,8 @@ typedef struct _thread_data_t {

rtapp_resources_t *local_resources;
rtapp_resources_t **global_resources;

int core_scheduling_family;
} thread_data_t;

typedef struct _pthread_data_t {
Expand Down Expand Up @@ -289,6 +291,8 @@ typedef struct _rtapp_options_t {
char *io_device;

int cumulative_slack;

int core_scheduling_families_count;
} rtapp_options_t;

typedef struct _timing_point_t {
Expand Down