Exemple #1
0
static void migration_thread(void *__data)
{
	int cpu = (long) __data;
	edf_wm_task_t *et;
	struct timespec ts;

	set_current_state(TASK_INTERRUPTIBLE);
	while (!kthread_should_stop()) {
		spin_lock_irq(&kthread[cpu].lock);
		if (list_empty(&kthread[cpu].list)) {
			spin_unlock_irq(&kthread[cpu].lock);
			schedule();
			set_current_state(TASK_INTERRUPTIBLE);
			continue;
		}

		/* get a task in the list by fifo. */
		et = list_first_entry(&kthread[cpu].list, 
							  edf_wm_task_t,
							  migration_list);
		list_del_init(&et->migration_list);
		spin_unlock_irq(&kthread[cpu].lock);

		/* account runtime. */
		jiffies_to_timespec(et->runtime[cpu], &ts);
		et->rt->task->dl.sched_runtime = timespec_to_ns(&ts);

		/* trace precise deadlines. */
		et->rt->deadline_time += et->deadline;
		et->rt->task->dl.sched_deadline = et->sched_split_deadline;
		et->rt->task->dl.deadline = et->next_release;
		et->next_release += et->sched_split_deadline;

		/* now let's migrate the task! */
		et->rt->task->dl.flags |= DL_NEW;
		migrate_task(et->rt, cpu);
		wake_up_process(et->rt->task);

		/* when the budget is exhausted, the deadline should be added by
		   et->sched_deadline but not by et->sched_split_deadline. */
		et->rt->task->dl.sched_deadline = et->sched_deadline;

		/* account runtime. */
		jiffies_to_timespec(et->runtime[cpu], &ts);
		et->rt->task->dl.runtime = timespec_to_ns(&ts);

		/* activate the timer for the next migration of this task. */
		if (et->last_cpu != cpu) {
			et->rt->task->dl.flags &= ~SCHED_EXHAUSTIVE;
			start_window_timer(et);
		}
		else {
			et->rt->task->dl.flags |= SCHED_EXHAUSTIVE;
		}
	}
}
Exemple #2
0
static void job_complete(resch_task_t *rt)
{
	if (task_is_split(rt)) {
		edf_wm_task_t *et = &edf_wm_task[rt->rid];
		hrtimer_cancel(&et->migration_hrtimer);
		et->rt->task->dl.sched_deadline = et->sched_split_deadline;
		et->rt->task->dl.deadline = et->next_release;
		et->rt->task->dl.runtime = et->sched_split_deadline;
		if (smp_processor_id() != et->first_cpu) {
			migrate_task(rt, et->first_cpu);
		}
	}
}
Exemple #3
0
/**
 * assign the given task to a particular CPU.
 * if no CPUs can accept the task, it is just assigned the lowest priority.
 * note that the task has not yet been inserted into the global list.
 */
static void task_run(resch_task_t *rt)
{
	int cpu_dst;

	/* aperiodic tasks are just skipped. */
	if (!rt->period) {
		return;
	}

	/* first clear the EDF-WM properties. */
	clear_split_task(rt);

	/* this is going to be a big lock! */
	global_list_down();

	/* try partitioning. */
	if ((cpu_dst = partition(rt)) != RESCH_CPU_UNDEFINED) {
		/* schedulable. */
		goto out; 
	}

	/* try splitting. */
	cpu_dst = split(rt);

 out:
	rt->cpu_id = cpu_dst; /* this is safe. */
	global_list_up();

	/* if partitioning succeeded, migrate @p to the cpu. 
	   otherwise, do the default fair scheduling. */
	if (cpu_dst != RESCH_CPU_UNDEFINED) {
		if (task_is_split(rt)) {
			edf_wm_task_t *et = &edf_wm_task[rt->rid];
			unsigned long runtime_save = et->rt->runtime;
			et->sched_deadline = et->rt->task->dl.sched_deadline;
			et->rt->deadline = et->deadline;
			et->rt->runtime = jiffies_to_usecs(et->runtime[et->first_cpu]);
			/* change the deadline. */
			set_scheduler(et->rt, RESCH_SCHED_EDF, rt->prio);
			et->sched_split_deadline = et->rt->task->dl.sched_deadline;
			et->rt->runtime = runtime_save;

			printk(KERN_INFO "EDF-WM: task#%d is split across to CPU#%d-%d.\n", 
				   rt->rid, et->first_cpu, et->last_cpu);
		}
		else {
			if (rt->policy != RESCH_SCHED_EDF) {
				set_scheduler(rt, RESCH_SCHED_EDF, RESCH_PRIO_EDF);
			}
			printk(KERN_INFO "EDF-WM: task#%d is assigned to CPU#%d.\n", 
				   rt->rid, cpu_dst);
		}
		rt->migratory = false;
		migrate_task(rt, cpu_dst);
	}
	else {
		printk(KERN_INFO "EDF-WM: task#%d is not schedulable.\n", rt->rid);
		/* it is actually the designer's choice how the tasks not 
		   successfully partitioned are scheduled. */
		set_scheduler(rt, RESCH_SCHED_FAIR, 0);
	}
}
Exemple #4
0
int main(int argc, char *argv[])
{

    int test_num;
    int task_num;
    int len;
    int num_cpus;		/* Total time = TIME_INTERVAL *num_cpus in the machine */
    int migrate = 0;	/* For task migration */
    char mygroup[FILENAME_MAX], mytaskfile[FILENAME_MAX];
    char mysharesfile[FILENAME_MAX], ch;
    /* Following variables are to capture parameters from script */
    char *group_num_p, *mygroup_p, *script_pid_p, *num_cpus_p, *test_num_p,
         *task_num_p;
    pid_t pid;
    gid_t mygroup_num;	/* A number attached with a group */
    int fd;			/* A descriptor to open a fifo for synchronized start */
    int counter = 0;	/* To take n number of readings */
    double total_cpu_time,	/* Accumulated cpu time */
           delta_cpu_time,	/* Time the task could run on cpu(s) (in an interval) */
           prev_cpu_time = 0;
    double exp_cpu_time;	/* Expected time in % as obtained by shares calculation */

    struct rusage cpu_usage;
    time_t current_time, prev_time, delta_time;
    unsigned int fmyshares, num_tasks;	/* f-> from file. num_tasks is tasks in this group */
    struct sigaction newaction, oldaction;

    mygroup_num = -1;
    num_cpus = 0;
    task_num = 0;
    test_num = 0;

    /* Signal handling for alarm */
    sigemptyset(&newaction.sa_mask);
    newaction.sa_handler = signal_handler_alarm;
    newaction.sa_flags = 0;
    sigaction(SIGALRM, &newaction, &oldaction);

    /* Collect the parameters passed by the script */
    group_num_p = getenv("GROUP_NUM");
    mygroup_p = getenv("MYGROUP");
    script_pid_p = getenv("SCRIPT_PID");
    num_cpus_p = getenv("NUM_CPUS");
    test_num_p = getenv("TEST_NUM");
    task_num_p = getenv("TASK_NUM");
    /* Check if all of them are valid */
    if ((test_num_p != NULL)
            && (((test_num = atoi(test_num_p)) == 4)
                || ((test_num = atoi(test_num_p)) == 5))) {
        if ((group_num_p != NULL) && (mygroup_p != NULL)
                && (script_pid_p != NULL) && (num_cpus_p != NULL)
                && (task_num_p != NULL)) {
            mygroup_num = atoi(group_num_p);
            scriptpid = atoi(script_pid_p);
            num_cpus = atoi(num_cpus_p);
            task_num = atoi(task_num_p);
            sprintf(mygroup, "%s", mygroup_p);
        } else {
            tst_brkm(TBROK, cleanup,
                     "Invalid other input parameters\n");
        }
    } else {
        tst_brkm(TBROK, cleanup, "Invalid test number passed\n");
    }

    sprintf(mytaskfile, "%s", mygroup);
    sprintf(mysharesfile, "%s", mygroup);
    strcat(mytaskfile, "/tasks");
    strcat(mysharesfile, "/cpu.shares");
    pid = getpid();
    write_to_file(mytaskfile, "a", pid);	/* Assign the task to it's group */

    fd = open("./myfifo", 0);
    if (fd == -1) {
        tst_brkm(TBROK, cleanup,
                 "Could not open fifo for synchronization");
    }

    read(fd, &ch, 1);	/* To block all tasks here and fire them up at the same time */

    /*
     * We now calculate the expected % cpu time of this task by getting
     * it's group's shares, the total shares of all the groups and the
     * number of tasks in this group.
     */
    FLAG = 0;
    total_shares = 0;
    shares_pointer = &total_shares;
    len = strlen(path);
    if (!strncpy(fullpath, path, len))
        tst_brkm(TBROK, cleanup, "Could not copy directory path %s ",
                 path);

    if (scan_shares_files(shares_pointer) != 0)
        tst_brkm(TBROK, cleanup,
                 "From function scan_shares_files in %s ", fullpath);

    /* return val: -1 in case of function error, else 2 is min share value */
    if ((fmyshares = read_shares_file(mysharesfile)) < 2)
        tst_brkm(TBROK, cleanup, "in reading shares files  %s ",
                 mysharesfile);

    if ((read_file(mytaskfile, GET_TASKS, &num_tasks)) < 0)
        tst_brkm(TBROK, cleanup, "in reading tasks files  %s ",
                 mytaskfile);

    exp_cpu_time = (double)(fmyshares * 100) / (total_shares * num_tasks);

    prev_time = time(NULL);	/* Note down the time */

    while (1) {
        /* Need to run some cpu intensive task, which also frequently checks the timer value */
        double f = 274.345, mytime;	/*just a float number to take sqrt */
        alarm(TIME_INTERVAL);
        timer_expired = 0;
        while (!timer_expired)	/* Let the task run on cpu for TIME_INTERVAL */
            f = sqrt(f * f);	/* Time of this operation should not be high otherwise we can
						 * exceed the TIME_INTERVAL to measure cpu usage
						 */
        current_time = time(NULL);
        delta_time = current_time - prev_time;	/* Duration in case its not exact TIME_INTERVAL */

        getrusage(0, &cpu_usage);
        total_cpu_time = (cpu_usage.ru_utime.tv_sec + cpu_usage.ru_utime.tv_usec * 1e-6 +	/* user time */
                          cpu_usage.ru_stime.tv_sec + cpu_usage.ru_stime.tv_usec * 1e-6);	/* system time */
        delta_cpu_time = total_cpu_time - prev_cpu_time;

        prev_cpu_time = total_cpu_time;
        prev_time = current_time;

        /* calculate % cpu time each task gets */
        if (delta_time > TIME_INTERVAL)
            mytime =
                (delta_cpu_time * 100) / (delta_time * num_cpus);
        else
            mytime =
                (delta_cpu_time * 100) / (TIME_INTERVAL * num_cpus);

        fprintf(stdout, "Grp:-%3d task-%3d:CPU TIME{calc:-%6.2f(s)i.e. %6.2f(%%)exp:-%6.2f(%%)}\
with %u(shares) in %lu (s) INTERVAL\n", mygroup_num, task_num, delta_cpu_time,
                mytime, exp_cpu_time, fmyshares, delta_time);

        counter++;

        if (counter >= NUM_INTERVALS) {	/* Take n sets of readings for each shares value */
            switch (test_num) {
            case 4:	/* Test04 */
                exit(0);	/* This task is done with its job */
                break;
            case 5:	/* Test 05 */
                if (migrate == 0) {
                    counter = 0;
                    fprintf(stdout,
                            "FIRST RUN COMPLETED FOR TASK %d\n",
                            task_num);
                    migrate = 1;
                } else {
                    fprintf(stdout,
                            "SECOND RUN COMPLETED FOR TASK %d\n",
                            task_num);
                    exit(0);
                }
                break;
            default:
                tst_brkm(TBROK, cleanup,
                         "Invalid test number passed\n");
                break;

            }	/* end switch */
        }
        if ((migrate == 1) && (counter == 0)) {
            if (task_num == 1) {
                if (migrate_task() != 0)
                    tst_brkm(TFAIL, cleanup,
                             "Could not migrate task 1 ");
                else
                    fprintf(stdout,
                            "TASK 1 MIGRATED FROM GROUP 1 TO GROUP 2\n");
                strcpy(mytaskfile, "/dev/cpuctl/group_2/tasks");
            }
            /*
             * Read the shares files and again calculate the cpu fraction
             * In test 2(case 4) we need to read tasks file as we migrate task
             * Q?? How to ensure other tasks do not read before task 1 migration
             */
            if ((read_file(mytaskfile, GET_TASKS, &num_tasks)) < 0)
                tst_brkm(TBROK, cleanup,
                         "in reading tasks files  %s ",
                         mytaskfile);
            exp_cpu_time =
                (double)(fmyshares * 100) / (total_shares *
                                             num_tasks);
        }
    }			/* end while */
}				/* end main */