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 Colombierincref(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 Colombierdecref(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 Colombierprocrestore(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 Colombierprocsave(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 Colombierlinkproc(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 Colombierkprocchild(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 Colombieridlehands(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