home *** CD-ROM | disk | FTP | other *** search
- /*
- l_proc.c
- */
- /* Copyright (c) 1994 Christian F. Tschudin. All rights reserved.
-
- Distributed under the terms of the GNU General Public License
- version 2 of june 1991 as published by the Free Software
- Foundation, Inc.
-
- This file is part of M0.
-
- M0 is distributed in the hope that it will be useful, but WITHOUT ANY
- WARRANTY. No author or distributor accepts responsibility to anyone for
- the consequences of using it or for whether it serves any particular
- purpose or works at all, unless he says so in writing. Refer to the GNU
- General Public License for full details.
-
- Everyone is granted permission to copy, modify and redistribute M0, but
- only under the conditions described in the GNU General Public License.
- A copy of this license is supposed to have been given to you along with
- M0 so you can know your rights and responsibilities. It should be in a
- file named LICENSE. Among other things, the copyright notice and this
- notice must be preserved on all copies. */
-
- #include "l_proto.h"
-
-
- mproc current, time_queue;
-
- static ushort next_pid;
-
- /* ------------------------------------------------------------------------ */
-
- static retcode
- time_insert(mproc p, eindex t)
- {
- eindex tout = new_element(p, T_TIME);
- eptr ep = eaddr(p,tout);
- struct time_s *tp = &(ep->V.tim);
- mproc q;
-
-
- memcpy(tp, &(eaddr(p,t)->V.tim), sizeof(struct time_s));
- p->timeout = tout;
-
- if (!time_queue) {
- time_queue = p;
- p->timelink = 0;
- return OK;
- }
- if (time_gt(&(eaddr(time_queue,time_queue->timeout)->V.tim), tp)) {
- p->timelink = time_queue;
- time_queue = p;
- return OK;
- }
- for (q = time_queue; q->timelink; q = q->timelink)
- if (time_gt(&(eaddr(q,q->timeout)->V.tim), tp))
- break;
- p->timelink = q->timelink;
- q->timelink = p;
- return OK;
- }
-
-
- static retcode
- time_remove(mproc p)
- {
- struct time_s *tp;
- mproc q;
-
- decref(p, p->timeout);
- p->timeout = 0;
-
- if (time_queue == p)
- time_queue = p->timelink;
- else {
- for (q = time_queue; q->timelink != p; q = q->timelink);
- q->timelink = p->timelink;
- }
- p->timelink = 0;
- return OK;
- }
-
-
- /* ----------------------------------------------------------------------
- get_queue
-
- increments the reference to the key only if a new queue is created
- does NOT increment the refcnt of the queue!
- */
- static eindex
- get_queue(eindex key)
- {
- eindex q = dict_get(0, queuedict, key);
-
- TRACE(5, printf("get_queue %d: queue key ref count after dict_get: %d\n", key, eprefcnt(gaddr(key))))
-
- if (q)
- return q;
- q = new_element(0, T_QUEUE);
- epattr(gaddr(q)) |= A_EXEC;
- dict_def(0, queuedict, key, q);
- decref(0, q);
-
- return q;
- }
-
-
- /* ----------------------------------------------------------------------
- queue_append
-
- */
- static retcode
- queue_append(mproc p, eindex qk)
- {
- eindex q = get_queue(qk);
- eptr qp = eaddr(p,q);
-
- if ((epattr(qp)&A_EXEC) && qp->V.que.head == 0)
- qp->V.que.head = p;
- else {
- if(!qp->V.que.tail)
- qp->V.que.tail = p;
- else {
- mproc p2 = qp->V.que.tail;
- while (p2->qtail)
- p2 = p2->qtail;
- p2->qtail = p;
- }
- p->state = S_BLOCKED;
- }
- eplen(qp) += 1;
-
- p->qkey = qk;
- incref(p, qk);
-
-
- return OK;
- }
-
-
- static retcode
- queue_remove(mproc p)
- {
- eindex q = get_queue(p->qkey);
- eptr pq = eaddr(p,q);
- mproc p2;
-
- TRACE(5, printf("queue_remove %d: queue key ref count after get_queue: %d\n", p->qkey, erefcnt(p,p->qkey)))
-
- if (pq->V.que.head == p) {
- if (epattr(pq)&A_EXEC) {
- p2 = pq->V.que.tail;
- pq->V.que.head = p2;
- if (p2) {
- pq->V.que.tail = p2->qtail;
- p2->qtail = 0;
- p2->state = S_RUNNING;
- if (p2->timeout) {
- time_remove(p2);
- p2->os[p2->osp++] = new_element(p2, T_INT);
- }
- }
- } else
- pq->V.que.head = 0;
- } else {
- p2 = pq->V.que.tail;
- if (p2 == p)
- pq->V.que.tail = p->qtail;
- else {
- while (p2->qtail != p)
- p2 = p2->qtail;
- p2->qtail = p->qtail;
- }
- }
- p->qtail = 0;
- eplen(pq) -= 1;
- if (eplen(pq)==0 && (epattr(pq)&A_EXEC))
- dict_undef(0, queuedict, p->qkey);
-
- TRACE(5, printf("queue_remove2 %d: queue key ref count after dict_undef: %d\n", p->qkey, erefcnt(p,p->qkey)))
-
- decref(p, p->qkey);
- p->qkey = 0;
-
- p->state = S_RUNNING;
- return OK;
- }
-
-
- /* msgr string must be global */
-
- retcode
- new_proc(eindex msgrstr, eindex orig)
- {
- eindex ud, qk, m = 0, c, d;
- eptr ep, mp = gaddr(msgrstr);
- mproc p = (mproc) calloc(1, sizeof(struct mproc_s));
- retcode rc;
-
- if (!p)
- return ERR_MALLOC_FAILED;
-
- if ((epattr(mp) & (A_SUB | A_FRAG)) || eprefcnt(mp) != 1) {
- byteptr s = (byteptr) malloc(eplen(mp));
- str_export(0, s, msgrstr, 0, eplen(mp));
- m = msgrstr;
- msgrstr = str_import(p, s, eplen(mp), eplen(mp));
- mp = gaddr(msgrstr);
- }
-
- rc = decomp_msgr(p, msgrstr, &qk, &c, &d);
- if (rc != OK) {
- if (m)
- decref(0, msgrstr);
- free(p);
- return rc;
- }
- TRACE(5, printf("new proc 1/ queue key ref count: %d\n", erefcnt(p,qk)))
-
- p->last_error = OK;
- p->state = S_RUNNING;
-
- p->ds[p->dsp++] = systemdict;
- incref(p, systemdict);
- ud = p->ds[p->dsp++] = new_dict(p); /* user dict */
-
- dict_def(p, ud, msgr_name, msgrstr);
- if (m)
- decref(p, msgrstr);
- dict_def(p, ud, code_name, c);
- decref(p, c);
- if (d) {
- dict_def(p, ud, data_name, d);
- decref(p, d);
- } else
- dict_def(p, ud, data_name, null_val);
- dict_def(p, ud, orig_name, orig ? orig : null_val);
-
- p->es[p->esp++] = msgr_start;
- incref(p, msgr_start);
-
- if (!current)
- current = p->next = p->last = p;
- else {
- p->next = current;
- p->last = current->last;
- p->last->next = p;
- current->last = p;
- }
-
- p->pid = next_pid++;
- rc = enqueue(p, qk, 0);
- decref(p, qk);
-
- TRACE(5, printf("new proc 2/ queue key ref count: %d\n", erefcnt(p,qk)))
- TRACE(1, printf(" ## new process %d\n", p->pid))
-
- return rc;
- }
-
-
- void
- remove_proc(mproc p)
- {
- eindex *ip;
- eptr ep;
- int i;
-
-
- TRACE(1, printf(" ## removing process %d\n", p->pid))
-
- if (p->qkey)
- dequeue(p);
- if (p->timeout)
- time_remove(p);
- if (p->err_element)
- decref(p,p->err_element);
- for (i=p->osp, ip=p->os; i > 0; i--, ip++)
- decref(p, *ip);
- for (i=p->dsp, ip=p->ds; i > 0; i--, ip++)
- decref(p, *ip);
- for (i=p->esp, ip=p->es; i > 0; i--, ip++)
- decref(p, *ip);
-
- for (i = 1, ep = p->local; i <= MAXLOCALS; i++, ep++)
- if (eptype(ep) != T_EMPTY)
- decref(p, i);
-
- if (current == p && p->next == p)
- current = 0;
- else {
- if (current == p)
- current = p->next;
- p->next->last = p->last;
- p->last->next = p->next;
- }
- free(p);
- }
-
-
- retcode
- enqueue(mproc p, eindex qkey, eindex t)
- {
- if (p->qkey)
- dequeue(p);
- queue_append(p, qkey);
- if (p->state != S_BLOCKED)
- return OK;
-
- if (t)
- time_insert(p, t);
-
- return YIELD_CPU;
- }
-
-
- void
- dequeue(mproc p)
- {
- TRACE(5, printf("dequeue %d: queue key ref count: %d\n", p->qkey, erefcnt(p,p->qkey)))
-
- queue_remove(p);
- if (p->timeout) {
- time_remove(p);
- p->os[p->osp++] = new_element(p, T_INT);
- p->state = S_RUNNING;
- }
-
- return;
- }
-
-
- void
- timeout(mproc p)
- {
- eindex r = new_element(p, T_INT);
-
- queue_remove(p);
- time_remove(p);
-
- eaddr(p,r)->V.i = 1;
- p->os[p->osp++] = r;
- p->state = S_RUNNING;
-
- return;
- }
-
-
- void
- queue_state(eindex qk, sint stopped)
- {
- eindex q = get_queue(qk);
- eptr qp= gaddr(q);
- /*
- decref(0, qk);
- */
- if (stopped)
- epattr(qp) &= ~A_EXEC;
- else if (eplen(qp) == 0)
- dict_undef(0, queuedict, qk);
- else {
- epattr(qp) |= A_EXEC;
- if (!qp->V.que.head) {
- mproc p = qp->V.que.tail;
- qp->V.que.head = p;
- qp->V.que.tail = p->qtail;
- p->qtail = 0;
- p->state = S_RUNNING;
- if (p->timeout) {
- time_remove(p);
- p->os[p->osp++] = new_element(p, T_INT);
- }
- }
- }
- return;
- }
-
-
- get_proc_stats(uint *active, uint *blocked, uint *timeout)
- {
- mproc p = current;
-
- *active = *blocked = *timeout = 0;
-
- if (!current)
- return 0;
-
- do {
- if (p->state == S_RUNNING)
- *active +=1;
- else if (p->state == S_BLOCKED)
- *blocked += 1;
- p = p->next;
- } while (p != current);
-
- for (p = time_queue; p; p = p->timelink)
- *timeout += 1;
-
-
- *blocked -= *timeout;
-
- return 0;
- }
-