xref: /plan9-contrib/sys/src/9k/k10/arch.c (revision e364617b1a51ecd9aea3d1363ca48190e1d6c4a0)
19ef1f84bSDavid du Colombier /*
29ef1f84bSDavid du Colombier  * EPISODE 12B
39ef1f84bSDavid du Colombier  * How to recognise different types of trees from quite a long way away.
49ef1f84bSDavid du Colombier  * NO. 1
59ef1f84bSDavid du Colombier  * THE LARCH
69ef1f84bSDavid du Colombier  */
79ef1f84bSDavid du Colombier #include "u.h"
89ef1f84bSDavid du Colombier #include "../port/lib.h"
99ef1f84bSDavid du Colombier #include "mem.h"
109ef1f84bSDavid du Colombier #include "dat.h"
119ef1f84bSDavid du Colombier #include "fns.h"
129ef1f84bSDavid du Colombier #include "../port/error.h"
139ef1f84bSDavid du Colombier 
149ef1f84bSDavid du Colombier #ifndef incref
159ef1f84bSDavid du Colombier int
incref(Ref * r)169ef1f84bSDavid du Colombier incref(Ref *r)
179ef1f84bSDavid du Colombier {
189ef1f84bSDavid du Colombier 	int x;
199ef1f84bSDavid du Colombier 
209ef1f84bSDavid du Colombier 	lock(r);
219ef1f84bSDavid du Colombier 	x = ++r->ref;
229ef1f84bSDavid du Colombier 	unlock(r);
239ef1f84bSDavid du Colombier 	return x;
249ef1f84bSDavid du Colombier }
259ef1f84bSDavid du Colombier #endif /* incref */
269ef1f84bSDavid du Colombier 
279ef1f84bSDavid du Colombier #ifndef decref
289ef1f84bSDavid du Colombier int
decref(Ref * r)299ef1f84bSDavid du Colombier decref(Ref *r)
309ef1f84bSDavid du Colombier {
319ef1f84bSDavid du Colombier 	int x;
329ef1f84bSDavid du Colombier 
339ef1f84bSDavid du Colombier 	lock(r);
349ef1f84bSDavid du Colombier 	x = --r->ref;
359ef1f84bSDavid du Colombier 	unlock(r);
369ef1f84bSDavid du Colombier 	if(x < 0)
379ef1f84bSDavid du Colombier 		panic("decref pc=%#p", getcallerpc(&r));
389ef1f84bSDavid du Colombier 
399ef1f84bSDavid du Colombier 	return x;
409ef1f84bSDavid du Colombier }
419ef1f84bSDavid du Colombier #endif /* decref */
429ef1f84bSDavid du Colombier 
439ef1f84bSDavid du Colombier void
procrestore(Proc * p)449ef1f84bSDavid du Colombier procrestore(Proc *p)
459ef1f84bSDavid du Colombier {
469ef1f84bSDavid du Colombier 	uvlong t;
479ef1f84bSDavid du Colombier 
489ef1f84bSDavid du Colombier 	if(p->kp)
499ef1f84bSDavid du Colombier 		return;
509ef1f84bSDavid du Colombier 	cycles(&t);
519ef1f84bSDavid du Colombier 	p->pcycles -= t;
529ef1f84bSDavid du Colombier 
539ef1f84bSDavid du Colombier 	fpuprocrestore(p);
549ef1f84bSDavid du Colombier }
559ef1f84bSDavid du Colombier 
569ef1f84bSDavid du Colombier /*
579ef1f84bSDavid du Colombier  *  Save the mach dependent part of the process state.
589ef1f84bSDavid du Colombier  */
599ef1f84bSDavid du Colombier void
procsave(Proc * p)609ef1f84bSDavid du Colombier procsave(Proc *p)
619ef1f84bSDavid du Colombier {
629ef1f84bSDavid du Colombier 	uvlong t;
639ef1f84bSDavid du Colombier 
649ef1f84bSDavid du Colombier 	cycles(&t);
659ef1f84bSDavid du Colombier 	p->pcycles += t;
669ef1f84bSDavid du Colombier 
679ef1f84bSDavid du Colombier 	fpuprocsave(p);
689ef1f84bSDavid du Colombier 
699ef1f84bSDavid du Colombier 	/*
709ef1f84bSDavid du Colombier 	 */
719ef1f84bSDavid du Colombier 	mmuflushtlb(m->pml4->pa);
729ef1f84bSDavid du Colombier }
739ef1f84bSDavid du Colombier 
749ef1f84bSDavid du Colombier static void
linkproc(void)759ef1f84bSDavid du Colombier linkproc(void)
769ef1f84bSDavid du Colombier {
779ef1f84bSDavid du Colombier 	spllo();
789ef1f84bSDavid du Colombier 	up->kpfun(up->kparg);
799ef1f84bSDavid du Colombier 	pexit("kproc dying", 0);
809ef1f84bSDavid du Colombier }
819ef1f84bSDavid du Colombier 
829ef1f84bSDavid du Colombier void
kprocchild(Proc * p,void (* func)(void *),void * arg)839ef1f84bSDavid du Colombier kprocchild(Proc* p, void (*func)(void*), void* arg)
849ef1f84bSDavid du Colombier {
859ef1f84bSDavid du Colombier 	/*
869ef1f84bSDavid du Colombier 	 * gotolabel() needs a word on the stack in
879ef1f84bSDavid du Colombier 	 * which to place the return PC used to jump
889ef1f84bSDavid du Colombier 	 * to linkproc().
899ef1f84bSDavid du Colombier 	 */
909ef1f84bSDavid du Colombier 	p->sched.pc = PTR2UINT(linkproc);
919ef1f84bSDavid du Colombier 	p->sched.sp = PTR2UINT(p->kstack+KSTACK-BY2SE);
929ef1f84bSDavid du Colombier 	p->sched.sp = STACKALIGN(p->sched.sp);
939ef1f84bSDavid du Colombier 
949ef1f84bSDavid du Colombier 	p->kpfun = func;
959ef1f84bSDavid du Colombier 	p->kparg = arg;
969ef1f84bSDavid du Colombier }
979ef1f84bSDavid du Colombier 
98*e364617bSDavid du Colombier static int idle_spin;
99*e364617bSDavid du Colombier 
1009ef1f84bSDavid du Colombier /*
1019ef1f84bSDavid du Colombier  *  put the processor in the halt state if we've no processes to run.
1029ef1f84bSDavid du Colombier  *  an interrupt will get us going again.
1039ef1f84bSDavid du Colombier  */
1049ef1f84bSDavid du Colombier void
idlehands(void)1059ef1f84bSDavid du Colombier idlehands(void)
1069ef1f84bSDavid du Colombier {
107*e364617bSDavid du Colombier 	/*
108*e364617bSDavid du Colombier 	 * we used to halt only on single-core setups. halting in an smp system
109*e364617bSDavid du Colombier 	 * can result in a startup latency for processes that become ready.
110*e364617bSDavid du Colombier 	 * if idle_spin is zero, we care more about saving energy
111*e364617bSDavid du Colombier 	 * than reducing this latency.
112*e364617bSDavid du Colombier 	 *
113*e364617bSDavid du Colombier 	 * the performance loss with idle_spin == 0 seems to be slight
114*e364617bSDavid du Colombier 	 * and it reduces lock contention (thus system time and real time)
115*e364617bSDavid du Colombier 	 * on many-core systems with large values of NPROC.
116*e364617bSDavid du Colombier 	 */
117*e364617bSDavid du Colombier 	if(sys->nonline == 1 || idle_spin == 0)
1189ef1f84bSDavid du Colombier 		halt();
1199ef1f84bSDavid du Colombier }
120