🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.lang.misc
Article #5318

Re: From Modula to Oberon

#5318
From: Peter da Silva
Date: Fri, 25 Mar 1988 13:06
100 lines
2803 bytes
In article <1139@PT.CS.CMU.EDU>, edw@IUS1.CS.CMU.EDU (Eddie Wyatt) writes:
>>
>>  The debate about CLU iterators misses an important point: CLU iterators are
>>coroutines, which C does not have.

Coroutines in 'C' are easy to implement, though. Why, this whole O/S we're
reading news on (UNIX) is written as a set of coroutines in 'C'. (yes, it's
a simplification... but not much of one).

I'd like to see the following functions become standard in 'C':

COROUTINE -- Build a jmp_buf for a coroutine.

int coroutine(jump, entry, stack, stacksize);
struct jmp_buf *jump;
void (*entry)();
char *stack;
int stacksize;

This sets up the stack and jmp_buf so that a call to "longjmp(jmp_buf)"
will appear to be a call to entry(). It will return an error only if the
stack isn't large enough for a small routine that does nothing but call
the following function:

int switch(from, to, status)
struct jmp_buf *from, *to;
int status;
{
	int code;

	if(!(code=setjmp(from)))
		longjmp(to, status);

	return code;
}

Voila! Co-routines! Lightweight processes (best if you have the Berkeley
signal handler, I guess, so you could run it off alarms...):

struct proc {
	struct proc *next;
	struct proc *prev;
	char *stack;
	struct jmp_buf context;
};

struct proc *runq;	/* doubly linked circular queue */

sleep()
{
	struct proc *self;
	/* do nothing if no procs or I'm alone */
	if(!runq)
		return;
	if(runq->next == runq)
		return;
	self = runq;
	runq = runq->next;
	switch(&self->context, &runq->context, 1);
}

int spawn(entry, stacksize)
void (*entry)();
int stacksize;
{
	struct proc *p;

	if(!(p = malloc(sizeof *p)))
		return 0;
	if(!(p->stack = malloc(stacksize))) {
		free(p);
		return 0;
	}
	if(!coroutine(p, entry, p->stack, stacksize)) {
		free(p->stack);
		free(p);
		return 0;
	}
	p->stacksize = p;
	p->next = runq->next;
	p->prev = runq;
	runq->next->prev = p;
	runq->next = p;
	return p;
}

int delete(p) /* note, this version doesn't allow a process to delete itself! */
struct process *p;
{
	if(p==runq)
		return 0;

	p->next->prev = p->prev;
	p->prev->next = p->next;
	free(p->stack);
	free(p);
}
-- 
-- Peter da Silva  `-_-'  ...!hoptoad!academ!uhnix1!sugar!peter
-- Disclaimer: These U aren't mere opinions... these are *values*.
Technical Details
Message-ID: <1758@sugar.UUCP>
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!nuchat!sugar!peter
References: <2827@enea.se><1557@pasteur.Berkeley.Edu><3764@bloom-beacon.MIT.EDU><1139@PT.CS.CMU.EDU>

Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!utzoo!mnetor!uunet!nuchat!sugar!peter
From: peter@sugar.UUCP (Peter da Silva)
Newsgroups: comp.lang.misc,comp.unix.wizards,comp.lang.c
Subject: Re: From Modula to Oberon
Message-ID: <1758@sugar.UUCP>
Date: 25 Mar 88 13:06:36 GMT
References: <2827@enea.se><1557@pasteur.Berkeley.Edu><3764@bloom-beacon.MIT.EDU><1139@PT.CS.CMU.EDU>
Organization: Sugar Land UNIX - Houston, TX
Lines: 100
Summary: C almost supports coroutines. Her's what it needs.