aboutsummaryrefslogblamecommitdiffstats
path: root/bin/rt_mode_poll.c
blob: d05521c79eeaef05190160b216f1558db8055c3c (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15














                     
                             


                           
                                        


                      















                                                                                                            
                                  









                                    
                            





                               

                                                                            




                                 




                                           



                                             




                                     
                            

                        
                                      
        
                       













                                                          
                         
                                                 
                              

                                                 













                                                                                   
                              

                                            

                                           
 


                                  











                                                                
        




                                                                                      


                                                           










                                                                          









                                                                  


















                                                             
                                        




                                                            




                                                    




                                                     
                                   







                                                          
                                         





                                                                 

                 
#include <sys/time.h>
#include <sys/mman.h>

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>
#include <string.h>
#include <assert.h>
#include <limits.h>


#include "litmus.h"
#include "common.h"

#define __NR_request_mode 408
#define __NR_enact_mode 409

int main_job(void){
	return syscall(__NR_enact_mode);
}

static char* progname;

static void usage(char *error) {
	fprintf(stderr, "Error: %s\n", error);
	fprintf(stderr,
		"Usage:\n"
		"	rt_spin [COMMON-OPTS] WCET PERIOD DURATION\n"
		"	rt_spin [COMMON-OPTS] -f FILE [-o COLUMN] WCET PERIOD\n"
		"	rt_spin -l\n"
		"\n"
		"COMMON-OPTS = [-w] [-s SCALE]\n"
		"              [-p PARTITION/CLUSTER [-z CLUSTER SIZE]] [-c CLASS] [-m CRITICALITY LEVEL]\n"
		"\n"
		"WCET and PERIOD are microseconds, DURATION is seconds.\n");
	exit(EXIT_FAILURE);
}

static int job(double program_end)
{
	if (wctime() > program_end)
		return 0;
	else {
		main_job();
		sleep_next_period();
		return 1;
	}
}

#define OPTSTR "p:wvel:b:k:"
int main(int argc, char** argv)
{
	int ret;
	lt_t wcet;
	lt_t period;
	lt_t budget;
	double wcet_ms, period_ms, budget_ms;
	unsigned int priority = 0; //guarantee highest priority to this task
	int migrate = 0;
	int cluster = 0;
	int opt;
	int wait = 0;
	int want_enforcement = 0;
	task_class_t class = RT_CLASS_HARD;
	struct rt_task param;
	struct mc2_task mc2_param;
	struct reservation_config config;
	int res_type = PERIODIC_POLLING;
	uint32_t mode_mask = (1 << 0);
	int i;
	double duration = 0, start = 0;
	struct control_page* ctl_page = NULL;

	progname = argv[0];

	/* default for reservation */
	config.id = 0;
	config.priority = 1;
	config.cpu = -1;
	
	mc2_param.crit = CRIT_LEVEL_A;
	
	budget_ms = 10;

	while ((opt = getopt(argc, argv, OPTSTR)) != -1) {
		switch (opt) {
		case 'w':
			wait = 1;
			break;
		case 'p':
			cluster = atoi(optarg);
			migrate = 1;
			config.cpu = cluster;
			break;
		case 'e':
			want_enforcement = 1;
			break;
		case 'b':
			budget_ms = atof(optarg);
			break;
		case 'k':
			mode_mask = atoi(optarg);
			break;
		case ':':
			usage("Argument missing.");
			break;
		case '?':
		default:
			usage("Bad argument.");
			break;
		}
	}

	if (mc2_param.crit > CRIT_LEVEL_A && config.priority != LITMUS_NO_PRIORITY)
		usage("Bad criticailty level or priority");

	if (argc - optind < 2)
		usage("Arguments missing.");

	wcet_ms   = atof(argv[optind + 0]);
	period_ms = atof(argv[optind + 1]);

	wcet   = ms2ns(wcet_ms);
	period = ms2ns(period_ms);
	budget = ms2ns(budget_ms);
	
	if (wcet <= 0)
		usage("The worst-case execution time must be a "
				"positive number.");
	if (period <= 0)
		usage("The period must be a positive number.");
	if (wcet > period) {
		usage("The worst-case execution time must not "
				"exceed the period.");
	}

	duration  = atof(argv[optind + 2]);
	
	if (migrate) {
		ret = be_migrate_to_domain(cluster);
		if (ret < 0)
			bail_out("could not migrate to target partition or cluster.");
	}
	else{
		bail_out("rt_mode_poll must be migrated.");
	}

	/* reservation config */
	config.id = gettid();
	
	config.polling_params.budget = budget;
	config.polling_params.period = period;
	config.polling_params.offset = 0;
	config.polling_params.relative_deadline = 0;
	if (config.polling_params.budget > config.polling_params.period) {
		usage("The budget must not exceed the period.");
	}

	/* create reservation's */
	for( i = 0; i < 32; i++){
		if ( !( (1 << i) & mode_mask ) )
			continue;
		config.mode = i;
		ret = reservation_create(res_type, &config);
		if (ret < 0) {
			bail_out("failed to create reservation.");
		}
	}
	
	init_rt_task_param(&param);
	param.exec_cost = wcet;
	param.period = period;
	param.priority = priority;
	param.cls = class;
	param.release_policy = TASK_PERIODIC;
	param.budget_policy = (want_enforcement) ?
			PRECISE_ENFORCEMENT : NO_ENFORCEMENT;
	if (migrate) {
		param.cpu = gettid();
	}
	ret = set_rt_task_param(gettid(), &param);
	
	if (ret < 0)
		bail_out("could not setup rt task params");
	
	mc2_param.res_id = gettid();
	mc2_param.mode_mask = mode_mask;
	ret = set_mc2_task_param(gettid(), &mc2_param);
	if (ret < 0)
		bail_out("could not setup mc2 task params");

	init_litmus();
	ctl_page = get_ctrl_page();
	if (!ctl_page)
		bail_out("could not get ctrl_page");
	ctl_page->mode_poll_task = 1;
	
	start = wctime();
	ret = task_mode(LITMUS_RT_TASK);
	if (ret != 0)
		bail_out("could not become RT task");

	set_page_color(config.cpu);

	if (wait) {
		ret = wait_for_ts_release();
		if (ret != 0)
			bail_out("wait_for_ts_release()");
		start = wctime();
	}

	while (job(start + duration)) {};

	ret = task_mode(BACKGROUND_TASK);
	if (ret != 0)
		bail_out("could not become regular task (huh?)");

	reservation_destroy(gettid(), config.cpu);
	return 0;
}