home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / unix / volume28 / m0 / part05 / l_proc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-06-06  |  7.7 KB  |  405 lines

  1. /*
  2.     l_proc.c
  3. */
  4. /*  Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
  5.  
  6.     Distributed under the terms of the GNU General Public License
  7.     version 2 of june 1991 as published by the Free Software
  8.     Foundation, Inc.
  9.  
  10.              This file is part of M0.
  11.  
  12. M0 is distributed in the hope that it will be useful, but WITHOUT ANY
  13. WARRANTY.  No author or distributor accepts responsibility to anyone for
  14. the consequences of using it or for whether it serves any particular
  15. purpose or works at all, unless he says so in writing.  Refer to the GNU
  16. General Public License for full details. 
  17.  
  18. Everyone is granted permission to copy, modify and redistribute M0, but
  19. only under the conditions described in the GNU General Public License. 
  20. A copy of this license is supposed to have been given to you along with
  21. M0 so you can know your rights and responsibilities.  It should be in a
  22. file named LICENSE.  Among other things, the copyright notice and this
  23. notice must be preserved on all copies.  */
  24.  
  25. #include "l_proto.h"
  26.  
  27.  
  28. mproc current, time_queue;
  29.  
  30. static ushort next_pid;
  31.  
  32. /* ------------------------------------------------------------------------ */
  33.  
  34. static retcode
  35. time_insert(mproc p, eindex t)
  36. {
  37.     eindex tout = new_element(p, T_TIME);
  38.     eptr ep = eaddr(p,tout);
  39.     struct time_s *tp = &(ep->V.tim);
  40.     mproc q;
  41.  
  42.  
  43.     memcpy(tp, &(eaddr(p,t)->V.tim), sizeof(struct time_s));
  44.     p->timeout = tout;
  45.  
  46.     if (!time_queue) {
  47.         time_queue = p;
  48.         p->timelink = 0;
  49.         return OK;
  50.     }
  51.     if (time_gt(&(eaddr(time_queue,time_queue->timeout)->V.tim), tp)) {
  52.         p->timelink = time_queue;
  53.         time_queue = p;
  54.         return OK;
  55.     }
  56.     for (q = time_queue; q->timelink; q = q->timelink)
  57.         if (time_gt(&(eaddr(q,q->timeout)->V.tim), tp))
  58.             break;
  59.     p->timelink = q->timelink;
  60.     q->timelink = p;
  61.     return OK;
  62. }
  63.  
  64.  
  65. static retcode
  66. time_remove(mproc p)
  67. {
  68.     struct time_s *tp;
  69.     mproc q;
  70.  
  71.     decref(p, p->timeout);
  72.     p->timeout = 0;
  73.  
  74.     if (time_queue == p)
  75.         time_queue = p->timelink;
  76.     else {
  77.         for (q = time_queue; q->timelink != p; q = q->timelink);
  78.         q->timelink = p->timelink;
  79.     }
  80.     p->timelink = 0;
  81.     return OK;
  82. }
  83.  
  84.  
  85. /* ----------------------------------------------------------------------
  86.    get_queue
  87.  
  88.    increments the reference to the key only if a new queue is created
  89.    does NOT increment the refcnt of the queue!
  90. */
  91. static eindex
  92. get_queue(eindex key)
  93. {
  94.     eindex q = dict_get(0, queuedict, key);
  95.  
  96.     TRACE(5, printf("get_queue %d: queue key ref count after dict_get: %d\n", key, eprefcnt(gaddr(key))))
  97.  
  98.     if (q)
  99.         return q;
  100.     q = new_element(0, T_QUEUE);
  101.     epattr(gaddr(q)) |= A_EXEC;
  102.     dict_def(0, queuedict, key, q);
  103.     decref(0, q);
  104.  
  105.     return q;
  106. }
  107.  
  108.  
  109. /* ----------------------------------------------------------------------
  110.    queue_append
  111.  
  112. */
  113. static retcode
  114. queue_append(mproc p, eindex qk)
  115. {
  116.     eindex q = get_queue(qk);
  117.     eptr qp = eaddr(p,q);
  118.  
  119.     if ((epattr(qp)&A_EXEC) && qp->V.que.head == 0)
  120.         qp->V.que.head = p;
  121.     else {
  122.         if(!qp->V.que.tail)
  123.             qp->V.que.tail = p;
  124.         else {
  125.             mproc p2 = qp->V.que.tail;
  126.             while (p2->qtail)
  127.                 p2 = p2->qtail;
  128.             p2->qtail = p;
  129.         }
  130.         p->state = S_BLOCKED;
  131.     }
  132.     eplen(qp) += 1;
  133.  
  134.     p->qkey = qk;
  135.     incref(p, qk);
  136.  
  137.  
  138.     return OK;
  139. }
  140.  
  141.  
  142. static retcode
  143. queue_remove(mproc p)
  144. {
  145.     eindex q = get_queue(p->qkey);
  146.     eptr pq = eaddr(p,q);
  147.     mproc p2;
  148.  
  149.     TRACE(5, printf("queue_remove %d: queue key ref count after get_queue: %d\n", p->qkey, erefcnt(p,p->qkey)))
  150.  
  151.     if (pq->V.que.head == p) {
  152.         if (epattr(pq)&A_EXEC) {
  153.             p2 = pq->V.que.tail;
  154.             pq->V.que.head = p2;
  155.             if (p2) {
  156.                 pq->V.que.tail = p2->qtail;
  157.                 p2->qtail = 0;
  158.                 p2->state = S_RUNNING;
  159.                 if (p2->timeout) {
  160.                     time_remove(p2);
  161.                     p2->os[p2->osp++] = new_element(p2, T_INT);
  162.                 }
  163.             }
  164.         } else
  165.             pq->V.que.head = 0;
  166.     } else {
  167.         p2 = pq->V.que.tail;
  168.         if (p2 == p)
  169.             pq->V.que.tail = p->qtail;
  170.         else {
  171.             while (p2->qtail != p)
  172.                 p2 = p2->qtail;
  173.             p2->qtail = p->qtail;
  174.         }
  175.     }
  176.     p->qtail = 0;
  177.     eplen(pq) -= 1;
  178.     if (eplen(pq)==0 && (epattr(pq)&A_EXEC))
  179.         dict_undef(0, queuedict, p->qkey);
  180.  
  181.     TRACE(5, printf("queue_remove2 %d: queue key ref count after dict_undef: %d\n", p->qkey, erefcnt(p,p->qkey)))
  182.  
  183.     decref(p, p->qkey);
  184.     p->qkey = 0;
  185.  
  186.     p->state = S_RUNNING;
  187.     return OK;
  188. }
  189.  
  190.  
  191. /* msgr string must be global */
  192.  
  193. retcode
  194. new_proc(eindex msgrstr, eindex orig)
  195. {
  196.     eindex ud, qk, m = 0, c, d;
  197.     eptr ep, mp = gaddr(msgrstr);
  198.     mproc p = (mproc) calloc(1, sizeof(struct mproc_s));
  199.     retcode rc;
  200.  
  201.     if (!p)
  202.         return ERR_MALLOC_FAILED;
  203.  
  204.     if ((epattr(mp) & (A_SUB | A_FRAG)) || eprefcnt(mp) != 1) {
  205.         byteptr s = (byteptr) malloc(eplen(mp));
  206.         str_export(0, s, msgrstr, 0, eplen(mp));
  207.         m = msgrstr;
  208.         msgrstr = str_import(p, s, eplen(mp), eplen(mp));
  209.         mp = gaddr(msgrstr);
  210.     }
  211.  
  212.     rc = decomp_msgr(p, msgrstr, &qk, &c, &d);
  213.     if (rc != OK) {
  214.         if (m)
  215.             decref(0, msgrstr);
  216.         free(p);
  217.         return rc;
  218.     }
  219.     TRACE(5, printf("new proc 1/ queue key ref count: %d\n", erefcnt(p,qk)))
  220.  
  221.     p->last_error = OK;
  222.     p->state = S_RUNNING;
  223.  
  224.     p->ds[p->dsp++] = systemdict;
  225.     incref(p, systemdict);
  226.     ud = p->ds[p->dsp++] = new_dict(p);    /* user dict */
  227.  
  228.     dict_def(p, ud, msgr_name, msgrstr);
  229.     if (m)
  230.         decref(p, msgrstr);
  231.     dict_def(p, ud, code_name, c);
  232.     decref(p, c);
  233.     if (d) {
  234.         dict_def(p, ud, data_name, d);
  235.         decref(p, d);
  236.     } else
  237.         dict_def(p, ud, data_name, null_val);
  238.     dict_def(p, ud, orig_name, orig ? orig : null_val);
  239.  
  240.     p->es[p->esp++] = msgr_start;
  241.     incref(p, msgr_start);
  242.  
  243.     if (!current)
  244.         current = p->next = p->last = p;
  245.     else {
  246.         p->next = current;
  247.         p->last = current->last;
  248.         p->last->next = p;
  249.         current->last = p;
  250.     }
  251.  
  252.     p->pid = next_pid++;
  253.     rc = enqueue(p, qk, 0);
  254.     decref(p, qk);
  255.  
  256.     TRACE(5, printf("new proc 2/ queue key ref count: %d\n", erefcnt(p,qk)))
  257.     TRACE(1, printf("  ## new process %d\n", p->pid))
  258.  
  259.     return rc;
  260. }
  261.  
  262.  
  263. void
  264. remove_proc(mproc p)
  265. {
  266.     eindex *ip;
  267.     eptr ep;
  268.     int i;
  269.  
  270.  
  271.     TRACE(1, printf("  ## removing process %d\n", p->pid))
  272.  
  273.     if (p->qkey)
  274.         dequeue(p);
  275.     if (p->timeout)
  276.         time_remove(p);
  277.     if (p->err_element)
  278.         decref(p,p->err_element);
  279.     for (i=p->osp, ip=p->os; i > 0; i--, ip++)
  280.         decref(p, *ip);
  281.     for (i=p->dsp, ip=p->ds; i > 0; i--, ip++)
  282.         decref(p, *ip);
  283.     for (i=p->esp, ip=p->es; i > 0; i--, ip++)
  284.         decref(p, *ip);
  285.  
  286.     for (i = 1, ep = p->local; i <= MAXLOCALS; i++, ep++)
  287.         if (eptype(ep) != T_EMPTY)
  288.             decref(p, i);
  289.  
  290.     if (current == p && p->next == p)
  291.         current = 0;
  292.     else {
  293.         if (current == p)
  294.             current = p->next;
  295.         p->next->last = p->last;
  296.         p->last->next = p->next;
  297.     }
  298.     free(p);
  299. }
  300.  
  301.  
  302. retcode
  303. enqueue(mproc p, eindex qkey, eindex t)
  304. {
  305.     if (p->qkey)
  306.         dequeue(p);
  307.     queue_append(p, qkey);
  308.     if (p->state != S_BLOCKED)
  309.         return OK;
  310.  
  311.     if (t)
  312.         time_insert(p, t);
  313.  
  314.     return YIELD_CPU;
  315. }
  316.  
  317.  
  318. void
  319. dequeue(mproc p)
  320. {
  321.     TRACE(5, printf("dequeue %d: queue key ref count: %d\n", p->qkey, erefcnt(p,p->qkey)))
  322.  
  323.     queue_remove(p);
  324.     if (p->timeout) {
  325.         time_remove(p);
  326.         p->os[p->osp++] = new_element(p, T_INT);
  327.         p->state = S_RUNNING;
  328.     }
  329.  
  330.     return;
  331. }
  332.  
  333.  
  334. void
  335. timeout(mproc p)
  336. {
  337.     eindex r = new_element(p, T_INT);
  338.  
  339.     queue_remove(p);
  340.     time_remove(p);
  341.  
  342.     eaddr(p,r)->V.i = 1;
  343.     p->os[p->osp++] = r;
  344.     p->state = S_RUNNING;
  345.  
  346.     return;
  347. }
  348.  
  349.  
  350. void
  351. queue_state(eindex qk, sint stopped)
  352. {
  353.     eindex q = get_queue(qk);
  354.     eptr qp= gaddr(q);
  355. /*
  356.     decref(0, qk);
  357. */
  358.     if (stopped)
  359.         epattr(qp) &= ~A_EXEC;
  360.     else if (eplen(qp) == 0)
  361.         dict_undef(0, queuedict, qk);
  362.     else {
  363.         epattr(qp) |= A_EXEC;
  364.         if (!qp->V.que.head) {
  365.             mproc p = qp->V.que.tail;
  366.             qp->V.que.head = p;
  367.             qp->V.que.tail = p->qtail;
  368.             p->qtail = 0;
  369.             p->state = S_RUNNING;
  370.             if (p->timeout) {
  371.                 time_remove(p);
  372.                 p->os[p->osp++] = new_element(p, T_INT);
  373.             }
  374.         }
  375.     }
  376.     return;
  377. }
  378.  
  379.  
  380. get_proc_stats(uint *active, uint *blocked, uint *timeout)
  381. {
  382.     mproc p = current;
  383.  
  384.     *active = *blocked = *timeout = 0;
  385.  
  386.     if (!current)
  387.         return 0;
  388.  
  389.     do {
  390.         if (p->state == S_RUNNING)
  391.             *active +=1;
  392.         else if (p->state == S_BLOCKED)
  393.             *blocked += 1;
  394.         p = p->next;
  395.     } while (p != current);
  396.  
  397.     for (p = time_queue; p; p = p->timelink)
  398.         *timeout += 1;
  399.  
  400.  
  401.     *blocked -= *timeout;
  402.  
  403.     return 0;
  404. }
  405.