arch/arm/common/bL_switcher.c

Source file repositories/reference/linux-study-clean/arch/arm/common/bL_switcher.c

File Facts

System
Linux kernel
Corpus path
arch/arm/common/bL_switcher.c
Extension
.c
Size
20705 bytes
Lines
802
Domain
Architecture Layer
Bucket
arch/arm
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

struct bL_thread {
	spinlock_t lock;
	struct task_struct *task;
	wait_queue_head_t wq;
	int wanted_cluster;
	struct completion started;
	bL_switch_completion_handler completer;
	void *completer_cookie;
};

static struct bL_thread bL_threads[NR_CPUS];

static int bL_switcher_thread(void *arg)
{
	struct bL_thread *t = arg;
	int cluster;
	bL_switch_completion_handler completer;
	void *completer_cookie;

	sched_set_fifo_low(current);
	complete(&t->started);

	do {
		if (signal_pending(current))
			flush_signals(current);
		wait_event_interruptible(t->wq,
				t->wanted_cluster != -1 ||
				kthread_should_stop());

		spin_lock(&t->lock);
		cluster = t->wanted_cluster;
		completer = t->completer;
		completer_cookie = t->completer_cookie;
		t->wanted_cluster = -1;
		t->completer = NULL;
		spin_unlock(&t->lock);

		if (cluster != -1) {
			bL_switch_to(cluster);

			if (completer)
				completer(completer_cookie);
		}
	} while (!kthread_should_stop());

	return 0;
}

static struct task_struct *bL_switcher_thread_create(int cpu, void *arg)
{
	struct task_struct *task;

	task = kthread_run_on_cpu(bL_switcher_thread, arg,
				  cpu, "kswitcher_%d");
	if (IS_ERR(task))
		pr_err("%s failed for CPU %d\n", __func__, cpu);

	return task;
}

/*
 * bL_switch_request_cb - Switch to a specific cluster for the given CPU,
 *      with completion notification via a callback
 *
 * @cpu: the CPU to switch
 * @new_cluster_id: the ID of the cluster to switch to.
 * @completer: switch completion callback.  if non-NULL,
 *	@completer(@completer_cookie) will be called on completion of
 *	the switch, in non-atomic context.
 * @completer_cookie: opaque context argument for @completer.
 *
 * This function causes a cluster switch on the given CPU by waking up
 * the appropriate switcher thread.  This function may or may not return
 * before the switch has occurred.
 *
 * If a @completer callback function is supplied, it will be called when
 * the switch is complete.  This can be used to determine asynchronously
 * when the switch is complete, regardless of when bL_switch_request()
 * returns.  When @completer is supplied, no new switch request is permitted
 * for the affected CPU until after the switch is complete, and @completer
 * has returned.
 */
int bL_switch_request_cb(unsigned int cpu, unsigned int new_cluster_id,
			 bL_switch_completion_handler completer,
			 void *completer_cookie)
{
	struct bL_thread *t;

	if (cpu >= ARRAY_SIZE(bL_threads)) {
		pr_err("%s: cpu %d out of bounds\n", __func__, cpu);

Annotation

Implementation Notes