blob: a957f905bb9f6d109cdbaf2dd9436abdf8298a5c [file]
#include "linsched.h"
#include <assert.h>
/* for in_sched_functions() */
char __sched_text_start[1];
char __sched_text_end[1];
static struct rcu_head *rcu_head;
static struct rcu_head **rcu_curtail = &rcu_head;
/* 'rcu' */
void call_rcu_sched(struct rcu_head *head, void (*func)(struct rcu_head *rcu))
{
head->func = func;
head->next = NULL;
*rcu_curtail = head;
rcu_curtail = &head->next;
}
void linsched_rcu_invoke(void)
{
while(rcu_head) {
struct rcu_head *next = rcu_head->next;
rcu_head->func(rcu_head);
rcu_head = next;
}
}
/* kernel/workqueue.c */
void wq_worker_waking_up(struct task_struct *task, unsigned int cpu) {}
struct task_struct *wq_worker_sleeping(struct task_struct *task,
unsigned int cpu)
{
/* should be unused */
assert(0);
return NULL;
}
/* posix-timers.c */
int __group_send_sig_info(int sig, struct siginfo *info, struct task_struct *p)
{
/* should be unused */
assert(0);
return 0;
}
struct k_itimer;
int posix_timer_event(struct k_itimer *timr, int si_private)
{
/* should be unused */
assert(0);
return 0;
}
struct k_clock;
void posix_timers_register_clock(const clockid_t clock_id,
struct k_clock *new_clock)
{
/* should be unused */
assert(0);
}
/* kernel/smp.c */
void __smp_call_function_single(int cpu, struct call_single_data *data,
int wait)
{
int this_cpu = smp_processor_id();
unsigned long flags;
if (cpu != this_cpu)
linsched_change_cpu(cpu);
local_irq_save(flags);
data->func(data->info);
local_irq_restore(flags);
if (cpu != this_cpu)
linsched_change_cpu(this_cpu);
}
void wake_up_stop_task(int cpu, cpu_stop_fn_t fxn, void *data);
/* kernel/stop_machine.c */
void linsched_current_handler(void);
int stop_one_cpu(unsigned int cpu, cpu_stop_fn_t fxn, void *arg)
{
struct task_struct *stop = stop_tasks[cpu];
int this_cpu = smp_processor_id(), ret;
linsched_change_cpu(cpu);
wake_up_process(stop);
/* switch to stop */
schedule();
BUG_ON(current != stop);
ret = fxn(arg);
/* switch back */
stop->state = TASK_INTERRUPTIBLE;
schedule();
/* let whoever followed the stop task re-program (if needed) */
linsched_current_handler();
BUG_ON(current == stop);
linsched_change_cpu(this_cpu);
return ret;
}
void stop_one_cpu_nowait(unsigned int cpu, cpu_stop_fn_t fxn, void *arg,
struct cpu_stop_work *work_buf)
{
struct task_struct *stop = stop_tasks[cpu];
struct stop_task *stop_task = task_thread_info(stop)->td->data;
int this_cpu = smp_processor_id();
/*
* catch a data race on simultaneous calls to stop_one_cpu_nowait, if
* this ends up happening we'd need to support a proper queue here.
*/
BUG_ON(stop_task->fxn);
stop_task->fxn = fxn;
stop_task->arg = arg;
/*
* in the nowait case we actually go through a schedule to make sure
* that our cpu has a change to drop its rq->locks since they may be
* needed.
*/
linsched_change_cpu(cpu);
hrtimer_set_expires(&stop_task->timer, ns_to_ktime(1));
hrtimer_start_expires(&stop_task->timer, HRTIMER_MODE_REL);
linsched_change_cpu(this_cpu);
}
int __stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
{
/* technically we should bounce every cpu, but don't bother */
return stop_one_cpu(cpumask_first(cpus), fn, data);
}
int stop_machine(int (*fn)(void *), void *data, const struct cpumask *cpus)
{
int ret;
/* No CPUs can come up or down during this. */
get_online_cpus();
ret = __stop_machine(fn, data, cpus);
put_online_cpus();
return ret;
}
/* the below are unfortunately currently static so we re-define them */
__attribute__((weak)) struct task_group *cgroup_tg(struct cgroup *cgrp)
{
return container_of(cgroup_subsys_state(cgrp, cpu_cgroup_subsys_id),
struct task_group, css);
}
void __sched preempt_schedule(void)
{
};
void fire_sched_out_preempt_notifiers(struct task_struct *curr,
struct task_struct *next)
{
}
void fire_sched_in_preempt_notifiers(struct task_struct *curr)
{
}
int security_task_getscheduler(struct task_struct *p,
int policy, struct sched_param *lp)
{
return 0;
}
int security_task_setscheduler(struct task_struct *p,
int policy, struct sched_param *lp)
{
return 0;
}
int cap_task_setnice(struct task_struct *p, int nice)
{
return 1;
}
int cap_task_setscheduler(struct task_struct *p, int policy,
struct sched_param *lp)
{
return 1;
}