1 /* 2 * EPISODE 12B 3 * How to recognise different types of trees from quite a long way away. 4 * NO. 1 5 * THE LARCH 6 */ 7 #include "u.h" 8 #include "../port/lib.h" 9 #include "mem.h" 10 #include "dat.h" 11 #include "fns.h" 12 #include "../port/error.h" 13 14 #ifndef incref 15 int incref(Ref * r)16incref(Ref *r) 17 { 18 int x; 19 20 lock(r); 21 x = ++r->ref; 22 unlock(r); 23 return x; 24 } 25 #endif /* incref */ 26 27 #ifndef decref 28 int decref(Ref * r)29decref(Ref *r) 30 { 31 int x; 32 33 lock(r); 34 x = --r->ref; 35 unlock(r); 36 if(x < 0) 37 panic("decref pc=%#p", getcallerpc(&r)); 38 39 return x; 40 } 41 #endif /* decref */ 42 43 void procrestore(Proc * p)44procrestore(Proc *p) 45 { 46 uvlong t; 47 48 if(p->kp) 49 return; 50 cycles(&t); 51 p->pcycles -= t; 52 53 fpuprocrestore(p); 54 } 55 56 /* 57 * Save the mach dependent part of the process state. 58 */ 59 void procsave(Proc * p)60procsave(Proc *p) 61 { 62 uvlong t; 63 64 cycles(&t); 65 p->pcycles += t; 66 67 fpuprocsave(p); 68 69 /* 70 */ 71 mmuflushtlb(m->pml4->pa); 72 } 73 74 static void linkproc(void)75linkproc(void) 76 { 77 spllo(); 78 up->kpfun(up->kparg); 79 pexit("kproc dying", 0); 80 } 81 82 void kprocchild(Proc * p,void (* func)(void *),void * arg)83kprocchild(Proc* p, void (*func)(void*), void* arg) 84 { 85 /* 86 * gotolabel() needs a word on the stack in 87 * which to place the return PC used to jump 88 * to linkproc(). 89 */ 90 p->sched.pc = PTR2UINT(linkproc); 91 p->sched.sp = PTR2UINT(p->kstack+KSTACK-BY2SE); 92 p->sched.sp = STACKALIGN(p->sched.sp); 93 94 p->kpfun = func; 95 p->kparg = arg; 96 } 97 98 static int idle_spin; 99 100 /* 101 * put the processor in the halt state if we've no processes to run. 102 * an interrupt will get us going again. 103 */ 104 void idlehands(void)105idlehands(void) 106 { 107 /* 108 * we used to halt only on single-core setups. halting in an smp system 109 * can result in a startup latency for processes that become ready. 110 * if idle_spin is zero, we care more about saving energy 111 * than reducing this latency. 112 * 113 * the performance loss with idle_spin == 0 seems to be slight 114 * and it reduces lock contention (thus system time and real time) 115 * on many-core systems with large values of NPROC. 116 */ 117 if(sys->nonline == 1 || idle_spin == 0) 118 halt(); 119 } 120