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

















                                                                              
                   








                                
                       














                                                               


                   






























                                                                       
              

                                                


                   
                                        
                                             












                                                                                    
 








                                                             
         

                                                    

         


                                                             
                    




                                                    
















                                                           


                                   




























                                                                                   

                                             


















                                                                            









                                                              




                                            





                                                                















                                                                                      
                                                         

























                                                                                  
                                                      








                                    



                               



                                                                    
                                 
                                       
                                         


                                         
 
                 


                       
                              



                         
/* based_mt_task.c -- A basic multi-threaded real-time task skeleton. 
 *
 * This (by itself useless) task demos how to setup a multi-threaded LITMUS^RT
 * real-time task. Familiarity with the single threaded example (base_task.c)
 * is assumed.
 *
 * Currently, liblitmus still lacks automated support for real-time
 * tasks, but internaly it is thread-safe, and thus can be used together
 * with pthreads.
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
/* Include gettid() */
#include <sys/types.h>

/* Include threading support. */
#include <pthread.h>

/* Include the LITMUS^RT API.*/
#include "litmus.h"
#include "color_shm.h"
#include "asm/cycles.h"

#define PERIOD            100
#define RELATIVE_DEADLINE 100
#define EXEC_COST         10

/* Let's create 10 threads in the example, 
 * for a total utilization of 1.
 */
#define NUM_THREADS      2 

/* The information passed to each thread. Could be anything. */
struct thread_context {
	int id;
	int cpu;
	int job_no;
	char* shm1;
	char* shm2;
	char* shm3;
};

/* The real-time thread program. Doesn't have to be the same for
 * all threads. Here, we only have one that will invoke job().
 */
void* rt_thread(void *tcontext);

/* Declare the periodically invoked job. 
 * Returns 1 -> task should exit.
 *         0 -> task should continue.
 */
int job(struct thread_context *tcx);


/* Catch errors.
 */
#define CALL( exp ) do { \
		int ret; \
		ret = exp; \
		if (ret != 0) \
			fprintf(stderr, "%s failed: %m\n", #exp);\
		else \
			fprintf(stderr, "%s ok.\n", #exp); \
	} while (0)


/* Basic setup is the same as in the single-threaded example. However, 
 * we do some thread initiliazation first before invoking the job.
 */
int main(int argc, char** argv)
{
	int i;
	struct thread_context ctx[NUM_THREADS];
	pthread_t             task[NUM_THREADS];
	char *shm1;
	char *shm2;
	char *shm3;
	struct color_ioctl_cmd shm_info;
	struct color_ioctl_offset shm_offset;
	/* The task is in background mode upon startup. */		


	/*****
	 * 1) Command line paramter parsing would be done here.
	 */


       
	/*****
	 * 2) Work environment (e.g., global data structures, file data, etc.) would
	 *    be setup here.
	 */

	shm_info.color = 0x00000001;
	shm_info.bank = 0x00000020;
	shm_offset.offset = 0;
	shm_offset.lock = 1;
	
	shm1 = (char*)color_mmap(1024, shm_info, shm_offset);
	if (!shm1) {
		printf("color mmap failed.\n");
		exit(-1);
	}
	else {
		printf("Mapped vaddr = %p\n", shm1);
	}

	shm_info.color = 0x00000003;
	shm_offset.offset = 1024;
	shm2 = (char*)color_mmap(4096, shm_info, shm_offset);
	if (!shm2) {
                printf("color mmap failed.\n");
                exit(-1);
        }
        else {
                printf("Mapped vaddr = %p\n", shm2);
	}

	mlockall(MCL_CURRENT | MCL_FUTURE);
	/*****
	 * 3) Initialize LITMUS^RT.
	 *    Task parameters will be specified per thread.
	 */
	init_litmus();


	/***** 
	 * 4) Launch threads.
	 */
	for (i = 0; i < NUM_THREADS; i++) {
		ctx[i].id = i;
		ctx[i].cpu = 0;
		ctx[i].job_no = 0;
		ctx[i].shm1 = shm1;
		ctx[i].shm3 = shm2;
		ctx[i].shm2 = shm3;
		pthread_create(task + i, NULL, rt_thread, (void *) (ctx + i));
	}

	
	/*****
	 * 5) Wait for RT threads to terminate.
	 */
	for (i = 0; i < NUM_THREADS; i++)
		pthread_join(task[i], NULL);
	

	/***** 
	 * 6) Clean up, maybe print results and stats, and exit.
	 */
	return 0;
}



/* A real-time thread is very similar to the main function of a single-threaded
 * real-time app. Notice, that init_rt_thread() is called to initialized per-thread
 * data structures of the LITMUS^RT user space libary.
 */
void* rt_thread(void *tcontext)
{
	int do_exit;
	struct thread_context *ctx = (struct thread_context *) tcontext;
	struct rt_task param;
	int ret;
	struct mc2_task mc2_param;
	struct reservation_config res_config;

	/* Set up task parameters */
	init_rt_task_param(&param);
	param.exec_cost = ms2ns(EXEC_COST);
	param.period = ms2ns(PERIOD);
	param.relative_deadline = ms2ns(RELATIVE_DEADLINE*(ctx->id+1));

	/* What to do in the case of budget overruns? */
	param.budget_policy = NO_ENFORCEMENT;

	/* The task class parameter is ignored by most plugins. */
	param.cls = RT_CLASS_SOFT;

	/* The priority parameter is only used by fixed-priority plugins. */
	param.priority = LITMUS_LOWEST_PRIORITY;

	/* Make presence visible. */
	printf("RT Thread %d active.\n", ctx->id);

	/* reservation config */
	res_config.id = gettid();
	res_config.polling_params.budget = ms2ns(EXEC_COST+1);
	res_config.polling_params.period = param.period;
	res_config.polling_params.offset = 0;
	res_config.polling_params.relative_deadline = 0;
	res_config.priority = LITMUS_MAX_PRIORITY;
	res_config.cpu = ctx->cpu;
	mc2_param.crit = CRIT_LEVEL_A;
	mc2_param.res_id = gettid();
	/*****
	 * 1) Initialize real-time settings.
	 */
	CALL( init_rt_thread() );

	ret = reservation_create(PERIODIC_POLLING, &res_config);
	if (ret < 0) {
		printf("reservation failed.\n");
		return NULL;
	}
	
	/* To specify a partition, do
	 *
	 * param.cpu = CPU;
	 * be_migrate_to(CPU);
	 *
	 * where CPU ranges from 0 to "Number of CPUs" - 1 before calling
	 * set_rt_task_param().
	 */
	param.cpu = ctx->cpu;
	ret = be_migrate_to_cpu(ctx->cpu);
	if (ret < 0) {
		printf("RT Thread %d fails to migrate to CPU%d\n", ctx->id, ctx->cpu);
		return NULL;
	}
	CALL( set_rt_task_param(gettid(), &param) );

	CALL( set_mc2_task_param(gettid(), &mc2_param) );
	/*****
	 * 2) Transition to real-time mode.
	 */
	CALL( task_mode(LITMUS_RT_TASK) );

	/* The task is now executing as a real-time task if the call didn't fail. 
	 */



	/*****
	 * 3) Invoke real-time jobs.
	 */
	do {
		/* Wait until the next job is released. */
		sleep_next_period();
		/* Invoke job. */
		do_exit = job(ctx);		
	} while (!do_exit);


	
	/*****
	 * 4) Transition to background mode.
	 */
	CALL( task_mode(BACKGROUND_TASK) );
	reservation_destroy(gettid(), res_config.cpu);

	return NULL;
}



int job(struct thread_context *tcx) 
{
	int i;
	char* buf1 = tcx->shm1;
	char* buf2 = tcx->shm2;
	char* buf3 = tcx->shm3;
	char tmp = 0;
	/* Do real-time calculation. */
	printf("Task %d Job %d executinig\n", tcx->id, tcx->job_no);

	if (tcx->id == 0) {
		printf("READ\n");
		for (i=0; i<600; i++) {
			char t = buf1[i];
			printf("%x ", t);
		}
		printf("\n");

		;
	}
	//test_call(0);
	tcx->job_no++;
	if (tcx->job_no == 10)
		return 1;
	/* Don't exit. */
	return 0;
}