| /* 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(); | 
 | } |