threads without kernel mods

Richard Tobin richard at aiai.ed.ac.uk
Tue May 28 02:45:27 AEST 1991


In article <1991May20.123423.10388 at linus.mitre.org> jfjr at mbunix.mitre.org (Freedman) writes:
> I need to know about implementing threads or lightweight processes 
>without modifying kernel - ie strictly user level implementations.
>How is this accomplished? Some variant on setjmp/longjmp?

Setjmp() and longjmp() may do the trick, but it's extremely
unportable.  Once you have n stacks, you may be able to longjmp()
between them.  If this works, you still have the problem of getting
onto a new stack in the first place.  Under BSD-like systems you may
be able to use a completely disgusting hack due I think to Simon
Brown, which involves using sigstack() to set up an alternative
stack for signal handlers, and then sending yourself a signal.

Here's some code from a Lisp system:

#include "defs.h"
#include "structs.h"
#include <stdio.h>
#include <signal.h>
#include <setjmp.h>

typedef void Sigtype;

static jmp_buf newenv, oldenv;
static LispObject *(*threadfunction)();

static Sigtype threadstart()
{
    if(_setjmp(newenv) == 0)
	longjmp(oldenv, 1);

    (void)(*threadfunction)();

    /* If we get here, the thread has returned too far. */

    fprintf(stderr, "Panic!  Thread returned too far!\n");
    exit(1);
}

void create_thread(thread, fn)
struct thread_structure *thread;
LispObject *(*fn)();
{
    struct sigstack stack, ostack;
    struct sigvec vec, ovec;

    stack.ss_sp = (char *)(((int)thread->stack + thread->size - 1) & ~7);
    stack.ss_onstack = 0;

    sigstack(&stack, &ostack);

    vec.sv_handler = threadstart;
    vec.sv_mask = 0;
    vec.sv_flags = SV_ONSTACK;

    sigvec(SIGUSR1, &vec, &ovec);

    if(setjmp(oldenv) == 0)
    {
	kill(getpid(), SIGUSR1);

	/* We never get here, because threadstart longjmps */
    }

    /*
     * At this point, threadstart has done a setjmp(newenv).  When
     * we jump to it, it will call the function in threadfunction.
     */

    sigvec(SIGUSR1, &ovec, (struct sigvec *)0);
    sigstack(&ostack, (struct sigstack *)0);

    threadfunction = fn;

    _longjmp(newenv, 1);
}

-- Richard
-- 
Richard Tobin,                       JANET: R.Tobin at uk.ac.ed             
AI Applications Institute,           ARPA:  R.Tobin%uk.ac.ed at nsfnet-relay.ac.uk
Edinburgh University.                UUCP:  ...!ukc!ed.ac.uk!R.Tobin



More information about the Comp.unix.internals mailing list