#include <unistd.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <signal.h> #include <fcntl.h> #include <sys/mman.h> #include <sys/types.h> #include <sched.h> /* for cpu sets */ #include "litmus.h" #include "internal.h" #define LP(name) {name ## _SEM, #name} static struct { int id; const char* name; } protocol[] = { LP(FMLP), LP(SRP), LP(MPCP), LP(MPCP_VS), {MPCP_VS_SEM, "MPCP-VS"}, LP(DPCP), LP(PCP), {FIFO_MUTEX, "FIFO"}, LP(IKGLP), LP(KFMLP), {IKGLP_SIMPLE_GPU_AFF_OBS, "IKGLP-GPU-SIMPLE"}, {IKGLP_GPU_AFF_OBS, "IKGLP-GPU"}, {KFMLP_SIMPLE_GPU_AFF_OBS, "KFMLP-GPU-SIMPLE"}, {KFMLP_GPU_AFF_OBS, "KFMLP-GPU"}, {PRIOQ_MUTEX, "PRIOQ"}, }; #define NUM_PROTOS (sizeof(protocol)/sizeof(protocol[0])) int lock_protocol_for_name(const char* name) { int i; for (i = 0; i < NUM_PROTOS; i++) if (strcmp(name, protocol[i].name) == 0) return protocol[i].id; return -1; } const char* name_for_lock_protocol(int id) { int i; for (i = 0; i < NUM_PROTOS; i++) if (protocol[i].id == id) return protocol[i].name; return "<UNKNOWN>"; } int litmus_open_lock( obj_type_t protocol, int lock_id, const char* namespace, void *config_param) { int fd, od; fd = open(namespace, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); if (fd < 0) return -1; od = od_openx(fd, protocol, lock_id, config_param); close(fd); return od; } void show_rt_param(struct rt_task* tp) { printf("rt params:\n\t" "exec_cost:\t%llu\n\tperiod:\t\t%llu\n\tcpu:\t%d\n", tp->exec_cost, tp->period, tp->cpu); } void init_rt_task_param(struct rt_task* tp) { /* Defaults: * - implicit deadline (t->relative_deadline == 0) * - phase = 0 * - class = RT_CLASS_SOFT * - budget policy = NO_ENFORCEMENT * - fixed priority = LITMUS_LOWEST_PRIORITY * - release policy = SPORADIC * - cpu assignment = 0 * * User must still set the following fields to non-zero values: * - tp->exec_cost * - tp->period * * User must set tp->cpu to the appropriate value for non-global * schedulers. For clusters, set tp->cpu to the first CPU in the * assigned cluster. */ memset(tp, 0, sizeof(*tp)); tp->cls = RT_CLASS_SOFT; tp->priority = LITMUS_LOWEST_PRIORITY; tp->budget_policy = NO_ENFORCEMENT; tp->release_policy = SPORADIC; } task_class_t str2class(const char* str) { if (!strcmp(str, "hrt")) return RT_CLASS_HARD; else if (!strcmp(str, "srt")) return RT_CLASS_SOFT; else if (!strcmp(str, "be")) return RT_CLASS_BEST_EFFORT; else return (task_class_t)(-1); } #define NS_PER_MS 1000000 int sporadic_global(lt_t e_ns, lt_t p_ns) { struct rt_task param; init_rt_task_param(¶m); param.exec_cost = e_ns; param.period = p_ns; return set_rt_task_param(gettid(), ¶m); } int sporadic_partitioned(lt_t e_ns, lt_t p_ns, int partition) { int ret; struct rt_task param; ret = be_migrate_to_partition(partition); check("be_migrate_to_partition()"); if (ret != 0) return ret; init_rt_task_param(¶m); param.exec_cost = e_ns; param.period = p_ns; param.cpu = partition_to_cpu(partition); return set_rt_task_param(gettid(), ¶m); } int sporadic_clustered(lt_t e_ns, lt_t p_ns, int cluster, int cluster_size) { int ret; struct rt_task param; ret = be_migrate_to_cluster(cluster, cluster_size); check("be_migrate_to_cluster()"); if (ret != 0) return ret; init_rt_task_param(¶m); param.exec_cost = e_ns; param.period = p_ns; param.cpu = cluster_to_first_cpu(cluster, cluster_size); return set_rt_task_param(gettid(), ¶m); } int init_kernel_iface(void); int init_litmus(void) { int ret, ret2; ret = mlockall(MCL_CURRENT | MCL_FUTURE); check("mlockall()"); ret2 = init_rt_thread(); return (ret == 0) && (ret2 == 0) ? 0 : -1; } int init_rt_thread(void) { int ret; ret = init_kernel_iface(); check("kernel <-> user space interface initialization"); return ret; } void exit_litmus(void) { /* nothing to do in current version */ } int open_kfmlp_gpu_sem(int fd, int name, unsigned int num_gpus, unsigned int gpu_offset, unsigned int rho, int affinity_aware) { int lock_od; int affinity_od; unsigned int num_replicas; struct gpu_affinity_observer_args aff_args; int aff_type; // number of GPU tokens num_replicas = num_gpus * rho; // create the GPU token lock lock_od = open_kfmlp_sem(fd, name, num_replicas); if(lock_od < 0) { perror("open_kfmlp_sem"); return -1; } // create the affinity method to use. // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS aff_args.obs.lock_od = lock_od; aff_args.replica_to_gpu_offset = gpu_offset; aff_args.rho = rho; aff_type = (affinity_aware) ? KFMLP_GPU_AFF_OBS : KFMLP_SIMPLE_GPU_AFF_OBS; affinity_od = od_openx(fd, aff_type, name+1, &aff_args); if(affinity_od < 0) { perror("open_kfmlp_aff"); return -1; } return lock_od; } //int open_ikglp_gpu_sem(int fd, int name, int num_gpus, int gpu_offset, int rho, int affinity_aware, int relax_max_fifo_len) //{ // int lock_od; // int affinity_od; // int num_replicas; // struct gpu_affinity_observer_args aff_args; // int aff_type; // // // number of GPU tokens // num_replicas = num_gpus * num_simult_users; // // // create the GPU token lock // lock_od = open_ikglp_sem(fd, name, (void*)&num_replicas); // if(lock_od < 0) { // perror("open_ikglp_sem"); // return -1; // } // // // create the affinity method to use. // // "no affinity" -> KFMLP_SIMPLE_GPU_AFF_OBS // aff_args.obs.lock_od = lock_od; // aff_args.replica_to_gpu_offset = gpu_offset; // aff_args.nr_simult_users = num_simult_users; // aff_args.relaxed_rules = (relax_max_fifo_len) ? 1 : 0; // // aff_type = (affinity_aware) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS; // affinity_od = od_openx(fd, aff_type, name+1, &aff_args); // if(affinity_od < 0) { // perror("open_ikglp_aff"); // return -1; // } // // return lock_od; //} int open_ikglp_sem(int fd, int name, unsigned int nr_replicas) { struct ikglp_args args = { .nr_replicas = nr_replicas, .max_in_fifos = IKGLP_M_IN_FIFOS, .max_fifo_len = IKGLP_OPTIMAL_FIFO_LEN}; return od_openx(fd, IKGLP_SEM, name, &args); } int open_gpusync_token_lock(int fd, int name, unsigned int num_gpus, unsigned int gpu_offset, unsigned int rho, unsigned int max_in_fifos, unsigned int max_fifo_len, int enable_affinity_heuristics) { int lock_od; int affinity_od; struct ikglp_args args = { .nr_replicas = num_gpus*rho, .max_in_fifos = max_in_fifos, .max_fifo_len = max_fifo_len, }; struct gpu_affinity_observer_args aff_args; int aff_type; if (!num_gpus || !rho) { perror("open_gpusync_sem"); return -1; } if ((max_in_fifos != IKGLP_UNLIMITED_IN_FIFOS) && (max_fifo_len != IKGLP_UNLIMITED_FIFO_LEN) && (max_in_fifos > args.nr_replicas * max_fifo_len)) { perror("open_gpusync_sem"); return(-1); } lock_od = od_openx(fd, IKGLP_SEM, name, &args); if(lock_od < 0) { perror("open_gpusync_sem"); return -1; } // create the affinity method to use. aff_args.obs.lock_od = lock_od; aff_args.replica_to_gpu_offset = gpu_offset; aff_args.rho = rho; aff_args.relaxed_rules = (max_fifo_len == IKGLP_UNLIMITED_FIFO_LEN) ? 1 : 0; aff_type = (enable_affinity_heuristics) ? IKGLP_GPU_AFF_OBS : IKGLP_SIMPLE_GPU_AFF_OBS; affinity_od = od_openx(fd, aff_type, name+1, &aff_args); if(affinity_od < 0) { perror("open_gpusync_affinity"); return -1; } return lock_od; }