home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
f
/
ftp-102.zip
/
ftape-1.02
/
driver
/
thread.c
< prev
next >
Wrap
C/C++ Source or Header
|
1992-10-12
|
5KB
|
199 lines
/* Do very lightweight threads in interrupt routines.
Copyright (C) 1992 David L. Brown, Jr.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2, or (at your option)
any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
/*
* thread.c,v 1.4 1992/10/13 01:45:01 dbrown Exp
*
* thread.c,v
* Revision 1.4 1992/10/13 01:45:01 dbrown
* Added FSF copyright.
*
* Revision 1.3 1992/09/12 23:15:23 dbrown
* Renamed suspend to th_suspend.
*
* Revision 1.2 1992/09/07 16:44:01 dbrown
* Changed names of routines for Kernel use.
*
* Revision 1.1 1992/09/07 14:46:24 dbrown
* Added thread code.
*
*/
#include "thread.h"
/* Register variable declarations. */
register long int bx asm ("bx");
register long int si asm ("si");
register long int di asm ("di");
register long int bp asm ("bp");
register long int sp asm ("sp");
#ifdef KERNEL
# define abort th_error
/*volatile*/ void
th_error ()
{
panic ("th thread stack underflow.");
}
#endif
volatile void abort ();
/* Create a thread and return non-zero if successfully. */
int
th_create (thread *th,
int stack_size,
void *stack,
func *function,
void *arg)
{
long **tsp;
th->stack = (long *) stack;
if (th->stack == 0)
return 0;
tsp = (long **) th->stack + (stack_size / sizeof (long *));
/* Push argument. */
*--tsp = (long *) arg;
/* Push abort in case the thread tries to return. */
*--tsp = (long *) abort;
th->slave.sp = (long *) tsp;
th->slave.bp = 0; /* Not relevant. */
th->slave.bx = 0; /* These don't matter much. */
th->slave.si = 0; /* Just clear them for cleanness. */
th->slave.di = 0;
th->slave.pc = (void *) function;
return 1;
}
/* Perform one thread operation until next suspend. The argument is
given as the return value from suspend. */
void *
th_thunk (thread *th, void *arg)
{
/* Save the general registers. */
th->master.bx = bx;
th->master.si = si;
th->master.di = di;
/* Save the return PC. */
th->master.pc = (void *) ((void **) &th)[-1];
/* Save the caller's FP, not our own. */
th->master.bp = (void *) ((void **) &th)[-2];
/* Save the caller's BP, not our own. */
th->master.sp = (void *) &th;
{
register const __typeof (th[0]) *t asm ("cx");
register void *a asm ("ax");
t = th;
a = arg;
bx = (long int) t->slave.bx;
si = (long int) t->slave.si;
di = (long int) t->slave.di;
bp = (long int) t->slave.bp;
sp = (long int) t->slave.sp;
asm volatile ("jmp %*%0" : : "g" (t->slave.pc), "a" (a));
}
}
/* Suspend the thread. The arg is returned to the call to thunk. */
void *
th_suspend (thread *th, void *arg)
{
/* Save the general registers. */
th->slave.bx = bx;
th->slave.si = si;
th->slave.di = di;
/* Save the return PC. */
th->slave.pc = (void *) ((void **) &th)[-1];
/* Save the caller's FP, not our own. */
th->slave.bp = (void *) ((void **) &th)[-2];
/* Save the caller's BP, not our own. */
th->slave.sp = (void *) &th;
{
register const __typeof (th[0]) *t asm ("cx");
register void *a asm ("ax");
t = th;
a = arg;
bx = (long int) t->master.bx;
si = (long int) t->master.si;
di = (long int) t->master.di;
bp = (long int) t->master.bp;
sp = (long int) t->master.sp;
asm volatile ("jmp %*%0" : : "g" (t->master.pc), "a" (a));
}
}
#ifdef TEST_THREADS
/* Test all of this. */
thread grunt;
int
sub_function (int value)
{
int result;
printf ("sub called = %d\n", value);
result = (int) suspend (&grunt, (void *) 2);
printf ("foo sub_function: suspend returned %d\n", result);
return 98;
}
void
foo (void *arg)
{
int result;
printf ("Foo called. arg = %d\n", (int) arg);
result = sub_function (99);
printf ("sub function returned %d\n", result);
suspend (&grunt, (void *) 4);
abort ();
}
main ()
{
int result;
create_thread (&grunt, 2048, foo, (void *) 1);
result = (int) thunk (&grunt, 0);
printf ("Thunk returned %d\n", result);
result = (int) thunk (&grunt, (void *) 3);
printf ("Thunk returned %d\n", result);
}
#endif /* TEST_THREADS */