blob: 89da71c086e0ab40a6873ed2c3db6b4f80f8e4e4 [file]
/* LinSched -- The Linux Scheduler Simulator
* Copyright (C) 2008 John M. Calandrino
* E-mail: jmc@cs.unc.edu
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program (see COPYING); if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#ifndef LINSCHED_H
#define LINSCHED_H
#include "linux_sched_headers.h"
/* Linsched definitions and declarations. */
#define LINSCHED_RAND_SEED 123456
#define LINSCHED_MAX_TASKS 10000
#define LINSCHED_MAX_GROUPS 100
#define LINSCHED_DEFAULT_NR_CPUS 4
/* have we started the simulation */
extern bool simulation_started;
extern struct cgroup *root_cgroup;
extern struct task_struct *__linsched_tasks[LINSCHED_MAX_TASKS];
extern struct task_struct *stop_tasks[NR_CPUS];
struct linsched_cgroup {
struct cgroup cg;
void *temp;
};
extern struct linsched_cgroup __linsched_cgroups[LINSCHED_MAX_GROUPS];
extern u64 current_time;
struct task_data {
void *data;
void (*init_task) (struct task_struct *, void *data);
void (*handle_task) (struct task_struct *, void *data);
};
struct stop_task {
cpu_stop_fn_t fxn;
void *arg;
struct task_struct *p;
struct hrtimer timer;
};
struct sleep_run_data {
struct hrtimer timer;
struct task_struct *p;
u64 last_start;
};
struct sleep_run_task {
struct sleep_run_data sr_data;
unsigned int busy; /* ms to run */
unsigned int sleep; /* ms to sleep */
};
/* A generic data placeholder for tasks modelled using random dists.
*/
struct rnd_dist_task {
struct sleep_run_data sr_data;
unsigned int busy;
unsigned int sleep;
struct rand_dist *sleep_rdist, *busy_rdist;
};
struct perf_task {
struct sleep_run_data sr_data;
unsigned int busy; /* ms to run */
unsigned int sleep; /* ms to sleep */
char *filename; /* pid.rlog file */
void *fp; /* fp to pid.rlog file */
};
enum linsched_perf_event_type {
RUN,
SLEEP,
IOWAIT,
};
struct linsched_perf_event {
enum linsched_perf_event_type type;
unsigned long duration;
};
/* Used to specify the topology of the system. Not specifying a
* topology gives a flat topology of LINSCHED_DEFAULT_NR_CPUS CPUs,
* each with one core and no SMT */
struct linsched_topology {
/* map from logical cpu to containing NUMA node */
int node_map[NR_CPUS];
/* map to containing physical CPU package */
int coregroup_map[NR_CPUS];
/* map from SMT logical cpu to containing core */
int core_map[NR_CPUS];
/* map from [node][node] to distance between them */
int node_distances[MAX_NUMNODES][MAX_NUMNODES];
int nr_cpus;
};
enum topologies {
UNIPROCESSOR,
DUAL_CPU,
DUAL_CPU_MC,
QUAD_CPU,
QUAD_CPU_MC,
QUAD_CPU_DUAL_SOCKET,
QUAD_CPU_QUAD_SOCKET,
HEX_CPU_DUAL_SOCKET_SMT,
MAX_TOPOLOGIES
};
#define TOPO_UNIPROCESSOR \
{ \
.nr_cpus = 1, \
.core_map = { \
[0] = 0, \
}, \
.coregroup_map = { \
[0] = 0, \
}, \
.node_map = { \
[0] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_DUAL_CPU \
{ \
.nr_cpus = 2, \
.core_map = { \
[0] = 0, \
[1] = 1, \
}, \
.coregroup_map = { \
[0] = 0, \
[1] = 1, \
}, \
.node_map = { \
[0 ... 1] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_DUAL_CPU_MC \
{ \
.nr_cpus = 2, \
.core_map = { \
[0] = 0, \
[1] = 1, \
}, \
.coregroup_map = { \
[0 ... 1] = 0, \
}, \
.node_map = { \
[0 ... 1] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_QUAD_CPU \
{ \
.nr_cpus = 4, \
.core_map = { \
0, 1, 2, 3, \
}, \
.coregroup_map = { \
0, 1, 2, 3, \
}, \
.node_map = { \
[0 ... 3] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_QUAD_CPU_MC \
{ \
.nr_cpus = 4, \
.core_map = { \
0, 1, 2, 3, \
}, \
.coregroup_map = { \
[0 ... 1] = 0, \
[2 ... 3] = 1, \
}, \
.node_map = { \
[0 ... 3] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_QUAD_CPU_DUAL_SOCKET \
{ \
.nr_cpus = 8, \
.core_map = { \
0, 1, 2, 3, \
4, 5, 6, 7, \
}, \
.coregroup_map = { \
[0] = 0, \
[1] = 1, \
[2] = 2, \
[3] = 3, \
[4] = 0, \
[5] = 1, \
[6] = 2, \
[7] = 3, \
}, \
.node_map = { \
[0 ... 7] = 0, \
}, \
.node_distances = { \
{ 10 }, \
}, \
}
#define TOPO_QUAD_CPU_QUAD_SOCKET \
{ \
.nr_cpus = 16, \
.core_map = { \
0, 1, 2, 3, \
4, 5, 6, 7, \
8, 9, 10, 11, \
12, 13, 14, 15, \
}, \
.coregroup_map = { \
[0 ... 3] = 0, \
[4 ... 7] = 1, \
[8 ... 11] = 2, \
[12 ... 15] = 3, \
}, \
.node_map = { \
[0 ... 3] = 0, \
[4 ... 7] = 1, \
[8 ... 11] = 2, \
[12 ... 15] = 3, \
}, \
.node_distances = { \
{ 10, 20, 20, 30 }, \
{ 20, 20, 10, 20 }, \
{ 20, 10, 20, 20 }, \
{ 30, 20, 20, 10 }, \
}, \
}
#define TOPO_HEX_CPU_DUAL_SOCKET_SMT \
{ \
.nr_cpus = 24, \
.core_map = { \
[0] = 0, \
[1] = 1, \
[2] = 2, \
[3] = 3, \
[4] = 4, \
[5] = 5, \
[6] = 6, \
[7] = 7, \
[8] = 8, \
[9] = 9, \
[10] = 10, \
[11] = 11, \
[12] = 0, \
[13] = 1, \
[14] = 2, \
[15] = 3, \
[16] = 4, \
[17] = 5, \
[18] = 6, \
[19] = 7, \
[20] = 8, \
[21] = 9, \
[22] = 10, \
[23] = 11, \
}, \
.coregroup_map = { \
[0 ... 5] = 0, \
[6 ... 11] = 1, \
[12 ... 17] = 0, \
[18 ... 23] = 1, \
}, \
.node_map = { \
[0 ... 5] = 0, \
[6 ... 11] = 1, \
[12 ... 17] = 0, \
[18 ... 23] = 1, \
}, \
.node_distances = { \
{ 10, 20 }, \
{ 20, 10 }, \
}, \
}
struct linsched_global_options {
int print_nohz;
int print_tasks;
int print_cgroups;
int print_avg_imb;
int print_sched_stats;
int dump_imbalance;
int dump_full_balance;
};
extern struct linsched_global_options linsched_global_options;
/* Declarations of system initialization (or "boot") function. */
asmlinkage void __init start_kernel(void);
/* Scheduler "system calls" that are used during task creation. */
asmlinkage long sys_sched_setscheduler(pid_t pid, int policy,
struct sched_param __user *param);
asmlinkage long sys_nice(int increment);
/* sched.c functions */
struct task_group *cgroup_tg(struct cgroup *cgrp);
struct cpuacct *cgroup_ca(struct cgroup *cgrp);
struct cpuacct *task_ca(struct task_struct *tsk);
struct task_group *task_group(struct task_struct *p);
/* cgroup functions */
const char *cgroup_name(struct cgroup *cgrp);
struct cgroup *linsched_create_cgroup(struct cgroup *parent, char *path);
struct task_group *cgroup_tg(struct cgroup *cgrp); /* from sched.c */
struct cpuacct *cgroup_ca(struct cgroup *cgrp); /* from sched.c */
struct cpuacct *task_ca(struct task_struct *tsk); /* from sched.c */
static inline struct linsched_cgroup *linsched_cgroup(struct cgroup *cg) {
return container_of(cg, struct linsched_cgroup, cg);
}
static inline struct linsched_cgroup *linsched_tg(struct task_group *tg) {
return container_of(tg->css.cgroup, struct linsched_cgroup, cg);
}
/* linsched functions */
struct task_struct *linsched_get_task(int task_id);
struct task_data *linsched_create_sleep_run(int sleep, int busy);
struct task_struct *linsched_create_batch_task(struct task_data *, int niceval);
struct task_struct *linsched_create_RTfifo_task(struct task_data *, int prio);
struct task_struct *linsched_create_RTrr_task(struct task_data *, int prio);
struct task_struct *linsched_create_normal_task(struct task_data *td, int niceval);
struct task_struct *linsched_raw_copy_process(void);
int linsched_show_schedstat(void);
void linsched_change_cpu(int cpu);
void linsched_trigger_cpu(int cpu);
void linsched_check_resched(void);
void linsched_init_cpus(struct linsched_topology *topo);
void linsched_init_hrtimer(void);
void linsched_init(struct linsched_topology *topo);
void linsched_default_callback(void);
void linsched_announce_callback(void);
void linsched_exit_callback(void);
void linsched_disable_migrations(void);
void linsched_enable_migrations(void);
int linsched_force_migration(struct task_struct *task, int dest_cpu, int migr);
int linsched_create_task_group(int parent);
int linsched_add_task_to_group(struct task_struct *p, struct cgroup *cgrp);
void linsched_set_task_group_shares(int groupid, unsigned long shares);
void linsched_yield(void);
void linsched_random_init(int seed);
unsigned long linsched_random(void);
void linsched_run_sim(int sim_ticks);
void linsched_sched_debug_show(void);
void linsched_print_task_stats(void);
void linsched_print_group_stats(void);
void linsched_print_cpuacct_stats(int cpuacct_group_id);
void linsched_runtime_timer(struct task_struct *t, u64 runtime, void (*fn)(struct task_data *));
void linsched_idled_set(int cpu, long idle_time, long busy_time);
struct task_data *linsched_create_rnd_dist_sleep_run(struct rand_dist *sleep_rdist,
struct rand_dist *busy_rdist);
u64 getticks(void);
int linsched_create_perf_tasks(char *dirpath);
void linsched_set_printk_level(int level);
void linsched_rcu_invoke(void);
void linsched_online_cpu(int cpu);
void linsched_offline_cpu(int cpu);
#endif /* LINSCHED_H */