Thread View: comp.sys.sequent
1 messages
1 total messages
Started by Gordon Russell
Fri, 04 Sep 1992 09:28
A new approach to Unix Threads
Author: Gordon Russell
Date: Fri, 04 Sep 1992 09:28
Date: Fri, 04 Sep 1992 09:28
182 lines
6282 bytes
6282 bytes
I have been working on a simple threads package which preferably
would work on the two classes of machines I currently have access to..
sun4s and a sequent symmetry. I have been trying to achieve this
through the use of a context switch during signal handling (triggered
under a setitimer event). However, this does not appear to work
well on the symmetry (but only slightly better on the Sun4s :-) ).
Could someone out there help me by having a quick look at my code?
Sorry to waste general news bandwidth with a program (it is pretty small
though). Even some suggestions would be useful, for I am at the end of my
teather.
This program is not the best one I have to do this. The best that I have
achieved so far is one which doesn't core dump, but will corrupt the
totals being calculated in the two tasks of the context switch occurred
during a calculation loop. I have a feeling that the signal handler just
does not allow me the access to system registers that I require.
Again, please dont flame me for posting a program..., but feel free
to email me or post with any (helpfull) comments.
PS I know about the threads package which comes in xtank, but it is a
volenterary (sp?) thread switch, which is unsuitable for my application.
/* Compile with -DSYMMETRY */
#include <stdio.h>
#include <signal.h>
#include <sys/time.h>
#define TASK_OFF (1<<(SIGVTALRM-1))
#define TASK_ON (0)
#define INTERVAL (500000)
#define DISABLE_TASK_SWITCH() sigsetmask(TASK_OFF)
#define ENABLE_TASK_SWITCH() sigsetmask(TASK_ON)
typedef struct {
int number_of_tasks;
struct sigcontext *context;
int last_task;
} task_structure;
static task_structure TASKINFO;
/*
* Copy the current context to its save buffer in task_structure, and write in
* the next context.
*/
void swap_context(newcont,oldcont,context)
int newcont,oldcont;
struct sigcontext *context;
{
TASKINFO.context[oldcont] = *context;
*context = TASKINFO.context[newcont];
}
/*
* SIGNAL handler routine, which selects the next thread, swaps to that
* context, and then returns, thus activating the new thread.
*/
task_control(sig,code,context)
int sig,code;
struct sigcontext *context;
{
struct itimerval timer;
int newcontext_no;
/* Get the next thread's process id */
newcontext_no = TASKINFO.last_task+1;
if (newcontext_no > TASKINFO.number_of_tasks) newcontext_no = 0;
/* Select the new thread */
swap_context(newcontext_no,TASKINFO.last_task,context);
TASKINFO.last_task = newcontext_no;
/* Set the round-robin scheduler interrupt timer */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = INTERVAL;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
if (setitimer(ITIMER_VIRTUAL,&timer,NULL)) perror();
}
void startup_tasking()
{
struct itimerval timer;
struct sigvec task_struct;
struct sigstack sig;
/* Initialise the save buffer with enough space to save the MAIN thread */
TASKINFO.number_of_tasks = 0;
TASKINFO.context = (struct sigcontext *)malloc(sizeof(struct sigcontext));
TASKINFO.last_task = 0;
/* Create a signal stack for the scheduler to run on */
sig.ss_sp = (char *)malloc(1024);
sig.ss_onstack = 0;
if (sigstack (&sig,NULL) != 0) perror();
/* Insert the scheduler into the signal handler table */
task_struct.sv_handler = task_control;
task_struct.sv_mask = TASK_OFF;
#ifdef SYMMETRY
task_struct.sv_onstack = 1;
#endif
if (sigvec(SIGVTALRM,&task_struct,NULL) != 0) perror;
/* Start off the timer to activate scheduler */
timer.it_value.tv_sec = 0;
timer.it_value.tv_usec = INTERVAL;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 0;
if (setitimer(ITIMER_VIRTUAL,&timer,NULL)) perror();
}
/*
* This identifies a function as a task.
*/
void background_task(task_addr)
void (* task_addr)();
{
char *newstack;
struct sigcontext *cont;
int bank,reg;
DISABLE_TASK_SWITCH(); /* Dont allow the scheduler to run here */
newstack = (char *)malloc(4000); /* Create a new stack for the process */
TASKINFO.number_of_tasks+=1; /* Increment the no of threads in system */
TASKINFO.context = (struct sigcontext *)
realloc(TASKINFO.context,(TASKINFO.number_of_tasks+1) * sizeof(struct sigcontext));
/* Set up the initial state of the new thread */
#ifdef SYMMETRY
cont = TASKINFO.context+TASKINFO.number_of_tasks;
cont->sc_onstack = 0; /* sigstack state to restore */
cont->sc_mask = TASK_ON ; /* signal mask to restore */
cont->sc_sp = (int)newstack; /* sp to restore */
cont->sc_pc = (int)task_addr; /* pc to restore */
#endif
ENABLE_TASK_SWITCH(); /* Restart the scheduler now */
}
void task2()
{
int a,b,c;
c=0;
do {
DISABLE_TASK_SWITCH();
b=0; for (a=1; a<90000; a++) b+=a;
ENABLE_TASK_SWITCH();
printf ("Completed 90000 sum %x\n",b);
}while (1);
}
void task1()
{
int a,b,c;
c=0;
do {
b=0; for (a=1; a<100000; a++) b+=a;
printf ("Completed 100000 sum %x\n",b);
}while (1);
}
main()
{
startup_tasking();
ENABLE_TASK_SWITCH();
background_task(task2);
task1();
}
+--------------------------------+-------------------------------------------+
| Gordon Russell | EMAIL : gor@cs.strath.ac.uk |
| L13.13a, Livingstone Tower, | TELEPHONE : 041-552-4400 Ex 3703 |
| University Of Strathclyde, | FAX : 041-552-0775 |
| 26 Richmond Street, +-------------------------------------------+
| Glasgow, G1 1XH | Spelling mistakes within this document are|
| Scotland, UK | caused by internet compaction algorithms. |
+--------------------------------+-------------------------------------------+
Thread Navigation
This is a paginated view of messages in the thread with full content displayed inline.
Messages are displayed in chronological order, with the original post highlighted in green.
Use pagination controls to navigate through all messages in large threads.
Back to All Threads