long sys_cancel_reserve(pid_t pid) { struct cpumask set; struct pid *pid_struct; struct task_struct *task; struct task_struct *tmp; int i; int cpu_task_count[] = {0, 0, 0, 0}; printk(KERN_ALERT "[sys_cancel_reserve] PID %u\n", pid); // locate the task_struct for the task required if (pid == 0) { task = current; } else { rcu_read_lock(); pid_struct = find_get_pid(pid); if (!pid_struct) { rcu_read_unlock(); return -ENODEV; } task = pid_task(pid_struct, PIDTYPE_PID); if (!task) { rcu_read_unlock(); return -ENODEV; } rcu_read_unlock(); } // make sure the task has a reservation if (task->has_reservation == 0) { return -EINVAL; } if (task->has_reservation || task->energymon_node) { cancel_reserve_hook(task); // execute cancel reserve hook } // cancel timers if they are active if (hrtimer_active(&(task->T_timer))) { hrtimer_cancel(&(task->T_timer)); } if (hrtimer_active(&(task->C_timer))) { hrtimer_cancel(&(task->C_timer)); } // make runnable any task suspended by enforcement if (task->put_to_sleep) { task->put_to_sleep = 0; wake_up_process(task); } // mark as not having a reservation task->has_reservation = 0; // set process CPU to 0 because it is never offline cpumask_clear(&set); cpumask_set_cpu(0, &set); if (sched_setaffinity(task->pid, &set)) { printk(KERN_INFO "[sys_cancel_reserve] failed to set CPU affinity\n"); return -EINVAL; } // find what cpus have tasks with reservations rcu_read_lock(); for_each_process(tmp) { if (tmp->has_reservation) { cpu_task_count[task_cpu(tmp)] = 1; } } rcu_read_unlock(); // Bring offline all cpus with no tasks for (i = 0; i < NUM_CPUS; i ++) { if (cpu_task_count[i] == 0) { if (power_cpu(i, 0) != 0) { printk(KERN_INFO "[sys_cancel_reserve] failed to turn off cpu %d", i); return -EINVAL; } } else { if (power_cpu(i, 1) != 0) { printk(KERN_INFO "[sys_cancel_reserve] failed to turn on cpu %d", i); return -EINVAL; } } } // set the frequency based on sysclock algorithm sysclock_set(); return 0; }
/** * @brief 设置系统时间 * @param pclock 设置的时间值变量指针 * @return 成功时返回0, 否则返回非零值 */ int SysClockSet(const struct sysclock *pclock) { sysclock_set(pclock); return 0; }
long sys_set_reserve(pid_t pid, struct timespec __user *user_C, struct timespec __user *user_T, int cid) { struct cpumask set; struct timespec T, C, empty; struct pid *pid_struct; struct task_struct *task; struct task_struct *tmp; int i; int cpu_task_count[] = {0, 0, 0, 0}; set_normalized_timespec(&empty, 0, 0); // locate the task_struct for the task required if (pid == 0) { task = current; } else { rcu_read_lock(); pid_struct = find_get_pid(pid); if (!pid_struct) { rcu_read_unlock(); return -ENODEV; } task = pid_task(pid_struct, PIDTYPE_PID); if (!task) { rcu_read_unlock(); return -ENODEV; } rcu_read_unlock(); } // get timespec struct info if (copy_from_user(&C, user_C, sizeof(struct timespec))) { printk(KERN_ALERT "[sys_set_reserve] failed to copy C from user\n"); return -EFAULT; } if (copy_from_user(&T, user_T, sizeof(struct timespec))) { printk(KERN_ALERT "[sys_set_reserve] failed to copy T from user\n"); return -EFAULT; } // check for timespec validity if ((timespec_compare(&T, &C) < 0) || !timespec_valid(&T) || !timespec_valid(&C) || (cid >= NUM_CPUS)) { printk(KERN_ALERT "[sys_set_reserve] invalid T and C\n"); return -EINVAL; } // do a reservation admission check cid = admission_check(task, C, T, cid); if (cid < 0) { return -EBUSY; } if (set_reserve_hook(task) != 0) { return -EFAULT; } // cancel any old timers for an updated reservation if (hrtimer_active(&(task->C_timer))) { hrtimer_cancel(&(task->C_timer)); } if (hrtimer_active(&(task->T_timer))) { hrtimer_cancel(&(task->T_timer)); } // make runnable any task suspended by enforcement if (task->put_to_sleep) { task->put_to_sleep = 0; wake_up_process(task); } // copy into task struct ktime values task->real_C_time = ktime_set(0, 0); task->C_time = ktime_set(C.tv_sec, C.tv_nsec); task->T_time = ktime_set(T.tv_sec, T.tv_nsec); // find what cpus have tasks on them rcu_read_lock(); for_each_process(tmp) { if (tmp->has_reservation) { cpu_task_count[task_cpu(tmp)] = 1; } } rcu_read_unlock(); cpu_task_count[cid] = 1; task->reserve_cpu = cid; // Bring offline all cpus with no tasks for (i = 0; i < NUM_CPUS; i ++) { if (cpu_task_count[i] == 0) { if (power_cpu(i, 0) != 0) { printk(KERN_ALERT"[sys_set_reserve] failed to turn off cpu %d\n", i); goto fail; } printk(KERN_ALERT"[sys_set_reserve] turned OFF CPU %d\n", i); } else { if (power_cpu(i, 1) != 0) { printk(KERN_ALERT"[sys_set_reserve] failed to turn on cpu %d\n", i); goto fail; } printk(KERN_ALERT"[sys_set_reserve] turned ON CPU %d\n", i); } } // set process CPU cpumask_clear(&set); cpumask_set_cpu(cid, &set); if (sched_setaffinity(pid, &set)) { printk(KERN_ALERT"[sys_set_reserve] failed to set CPU affinity\n"); goto fail; } printk(KERN_ALERT "[sys_set_reserve] PID %d (C = %lld ms / T = %lld ms) CPU %u\n", pid, ktime_to_ms(task->C_time), ktime_to_ms(task->T_time), cid); // mark as having a reservation task->has_reservation = 1; // set the frequency based on sysclock algorithm sysclock_set(); return 0; fail: if (task->has_reservation || task->energymon_node) { cancel_reserve_hook(task); } return -EINVAL; }