arch.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. /*
  10. * EPISODE 12B
  11. * How to recognise different types of trees from quite a long way away.
  12. * NO. 1
  13. * THE LARCH
  14. */
  15. #include "u.h"
  16. #include "../port/lib.h"
  17. #include "mem.h"
  18. #include "dat.h"
  19. #include "fns.h"
  20. #include "../port/error.h"
  21. /* the rules are different for different compilers. We need to define up. */
  22. // Initialize it to force it into data.
  23. // That way, if we set them in assembly, they won't get zero'd by the bss init in main
  24. // N.B. There was an interesting hack in plan 9 c. You could grab up to two registers for your
  25. // program. In the case of Plan 9, m was r15, and up was r14. Very slick, and if there is a way to do
  26. // this in gcc or clang I don't know it. This also nicely handled per cpu info; R15/14 were always right for
  27. // your core and context.
  28. //Mach *m = (void *)0;
  29. int
  30. incref(Ref *r)
  31. {
  32. int x;
  33. lock(&r->l);
  34. x = ++r->ref;
  35. unlock(&r->l);
  36. return x;
  37. }
  38. int
  39. decref(Ref *r)
  40. {
  41. int x;
  42. lock(&r->l);
  43. x = --r->ref;
  44. unlock(&r->l);
  45. if(x < 0)
  46. panic("decref pc=%#p", getcallerpc(&r));
  47. return x;
  48. }
  49. void
  50. procrestore(Proc *p)
  51. {
  52. uint64_t t;
  53. if(p->kp)
  54. return;
  55. cycles(&t);
  56. p->pcycles -= t;
  57. fpuprocrestore(p);
  58. }
  59. /*
  60. * Save the mach dependent part of the process state.
  61. * NB: the caller should mmuflushtlb after procsave().
  62. * procsave/procrestore don't touch the mmu, they
  63. * care about fpu, mostly.
  64. */
  65. void
  66. procsave(Proc *p)
  67. {
  68. uint64_t t;
  69. cycles(&t);
  70. p->pcycles += t;
  71. fpuprocsave(p);
  72. }
  73. static void
  74. linkproc(void)
  75. {
  76. Proc *up = externup();
  77. spllo();
  78. up->kpfun(up->kparg);
  79. pexit("kproc dying", 0);
  80. }
  81. void
  82. kprocchild(Proc* p, void (*func)(void*), void* arg)
  83. {
  84. /*
  85. * gotolabel() needs a word on the stack in
  86. * which to place the return PC used to jump
  87. * to linkproc().
  88. */
  89. p->sched.pc = PTR2UINT(linkproc);
  90. p->sched.sp = PTR2UINT(p->kstack+KSTACK-BY2SE);
  91. p->sched.sp = STACKALIGN(p->sched.sp);
  92. p->kpfun = func;
  93. p->kparg = arg;
  94. }
  95. /*
  96. * put the processor in the halt state if we've no processes to run.
  97. * an interrupt will get us going again.
  98. * The boot TC in nix can't halt, because it must stay alert in
  99. * case an AC makes a handler process ready.
  100. * We should probably use mwait in that case.
  101. */
  102. void
  103. idlehands(void)
  104. {
  105. if(machp()->NIX.nixtype != NIXAC)
  106. halt();
  107. }