blob: 229280c0d864947f1a67f04da309ce494d54b10c [file] [log] [blame]
/* Copyright (c) 2009, 2012, 2015 The Regents of the University of California
* Barret Rhoden <brho@cs.berkeley.edu>
* Valmon Leymarie <leymariv@berkeley.edu>
* Kevin Klues <klueska@cs.berkeley.edu>
* See LICENSE for details.
*/
#include <env.h>
#include <schedule.h>
/* Provision a core to proc p. This code assumes that the scheduler that uses
* it holds a lock for the duration of the call. */
void __provision_core(struct proc *p, uint32_t pcoreid)
{
struct sched_pcore *spc = pcoreid2spc(pcoreid);
struct sched_pcore_tailq *prov_list;
/* If the core is already prov to someone else, take it away. (last
* write wins, some other layer or new func can handle permissions). */
if (spc->prov_proc) {
/* the list the spc is on depends on whether it is alloced to
* the prov_proc or not */
prov_list = spc->alloc_proc == spc->prov_proc ?
&spc->prov_proc->ksched_data.crd.prov_alloc_me :
&spc->prov_proc->ksched_data.crd.prov_not_alloc_me;
TAILQ_REMOVE(prov_list, spc, prov_next);
}
/* Now prov it to p. Again, the list it goes on depends on whether it
* is alloced to p or not. Callers can also send in 0 to de-provision.
* */
if (p) {
if (spc->alloc_proc == p) {
TAILQ_INSERT_TAIL(&p->ksched_data.crd.prov_alloc_me, spc,
prov_next);
} else {
/* this is be the victim list, which can be sorted so
* that we pick the right victim (sort by alloc_proc
* reverse priority, etc). */
TAILQ_INSERT_TAIL(&p->ksched_data.crd.prov_not_alloc_me,
spc, prov_next);
}
}
spc->prov_proc = p;
}
/* Unprovisions any pcores for the given list */
static void __unprov_pcore_list(struct sched_pcore_tailq *list_head)
{
struct sched_pcore *spc_i;
/* We can leave them connected within the tailq, since the scps don't
* have a default list (if they aren't on a proc's list, then we don't
* care about them), and since the INSERTs don't care what list you were
* on before (chummy with the implementation). Pretty sure this is
* right. If there's suspected list corruption, be safer here. */
TAILQ_FOREACH(spc_i, list_head, prov_next)
spc_i->prov_proc = 0;
TAILQ_INIT(list_head);
}
/* Unprovision all cores from proc p. This code assumes that the scheduler
* that uses * it holds a lock for the duration of the call. */
void __unprovision_all_cores(struct proc *p)
{
__unprov_pcore_list(&p->ksched_data.crd.prov_alloc_me);
__unprov_pcore_list(&p->ksched_data.crd.prov_not_alloc_me);
}
/* Print a list of the cores currently provisioned to p. */
void print_proc_coreprov(struct proc *p)
{
struct sched_pcore *spc_i;
if (!p)
return;
print_lock();
printk("Prov cores alloced to proc %d (%p)\n----------\n", p->pid, p);
TAILQ_FOREACH(spc_i, &p->ksched_data.crd.prov_alloc_me, prov_next)
printk("Pcore %d\n", spc2pcoreid(spc_i));
printk("Prov cores not alloced to proc %d (%p)\n----------\n", p->pid,
p);
TAILQ_FOREACH(spc_i, &p->ksched_data.crd.prov_not_alloc_me, prov_next)
printk("Pcore %d (alloced to %d (%p))\n", spc2pcoreid(spc_i),
spc_i->alloc_proc ? spc_i->alloc_proc->pid : 0,
spc_i->alloc_proc);
print_unlock();
}
/* Print the processes attached to each provisioned core. */
void print_coreprov_map(void)
{
struct sched_pcore *spc_i;
/* Doing this without a scheduler lock, which is dangerous, but won't
* deadlock */
print_lock();
printk("Which cores are provisioned to which procs:\n--------------\n");
for (int i = 0; i < num_cores; i++) {
spc_i = pcoreid2spc(i);
printk("Core %02d, prov: %d(%p) alloc: %d(%p)\n", i,
spc_i->prov_proc ? spc_i->prov_proc->pid : 0,
spc_i->prov_proc,
spc_i->alloc_proc ? spc_i->alloc_proc->pid : 0,
spc_i->alloc_proc);
}
print_unlock();
}