home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #19 / NN_1992_19.iso / spool / comp / sys / sequent / 530 < prev    next >
Encoding:
Text File  |  1992-09-04  |  5.9 KB  |  193 lines

  1. Path: sparky!uunet!mcsun!uknet!strath-cs!gor@cs.strath.ac.uk
  2. From: gor@cs.strath.ac.uk (Gordon Russell)
  3. Newsgroups: comp.sys.sequent
  4. Subject: A new approach to Unix Threads
  5. Message-ID: <10411@baird.cs.strath.ac.uk>
  6. Date: 4 Sep 92 09:28:56 GMT
  7. Sender: gor@cs.strath.ac.uk
  8. Organization: Comp. Sci. Dept., Strathclyde Univ., Glasgow, Scotland.
  9. Lines: 182
  10.  
  11.  
  12.  I have been working on a simple threads package which preferably
  13. would work on the two classes of machines I currently have access to..
  14. sun4s and a sequent symmetry. I have been trying to achieve this
  15. through the use of a context switch during signal handling (triggered
  16. under a setitimer event). However, this does not appear to work
  17. well on the symmetry (but only slightly better on the Sun4s :-) ).
  18. Could someone out there help me by having a quick look at my code?
  19. Sorry to waste general news bandwidth with a program (it is pretty small
  20. though). Even some suggestions would be useful, for I am at the end of my
  21. teather. 
  22.  
  23. This program is not the best one I have to do this. The best that I have
  24. achieved so far is one which doesn't core dump, but will corrupt the
  25. totals being calculated in the two tasks of the context switch occurred
  26. during a calculation loop. I have a feeling that the signal handler just
  27. does not allow me the access to system registers that I require.
  28. Again, please dont flame me for posting a program..., but feel free
  29. to email me or post with any (helpfull) comments.
  30.  
  31. PS I know about the threads package which comes in xtank, but it is a
  32.    volenterary (sp?) thread switch, which is unsuitable for my application.
  33.    
  34.  
  35. /* Compile with -DSYMMETRY */
  36.  
  37. #include <stdio.h>
  38. #include <signal.h>
  39. #include <sys/time.h>
  40.  
  41. #define TASK_OFF (1<<(SIGVTALRM-1))
  42. #define TASK_ON  (0)
  43. #define INTERVAL (500000)
  44.  
  45. #define DISABLE_TASK_SWITCH() sigsetmask(TASK_OFF)
  46. #define ENABLE_TASK_SWITCH()  sigsetmask(TASK_ON)
  47.  
  48. typedef struct {
  49.   int number_of_tasks;
  50.   struct sigcontext *context;
  51.   int last_task;
  52. } task_structure;
  53.  
  54. static task_structure TASKINFO;
  55.  
  56. /*
  57.  * Copy the current context to its save buffer in task_structure, and write in
  58.  * the next context.
  59.  */
  60. void swap_context(newcont,oldcont,context)
  61. int newcont,oldcont;
  62. struct sigcontext *context;
  63. {
  64.  TASKINFO.context[oldcont] = *context;
  65.  *context = TASKINFO.context[newcont]; 
  66. }
  67.  
  68. /*
  69.  * SIGNAL handler routine, which selects the next thread, swaps to that
  70.  * context, and then returns, thus activating the new thread.
  71.  */
  72. task_control(sig,code,context)
  73. int sig,code;
  74. struct sigcontext *context;
  75. {
  76. struct itimerval timer;
  77. int newcontext_no;
  78.  
  79.   /* Get the next thread's process id */
  80.   newcontext_no = TASKINFO.last_task+1;
  81.   if (newcontext_no > TASKINFO.number_of_tasks) newcontext_no = 0;
  82.  
  83.   /* Select the new thread */
  84.   swap_context(newcontext_no,TASKINFO.last_task,context);
  85.   TASKINFO.last_task = newcontext_no;
  86.  
  87.   /* Set the round-robin scheduler interrupt timer */
  88.   timer.it_value.tv_sec = 0;
  89.   timer.it_value.tv_usec = INTERVAL;
  90.   timer.it_interval.tv_sec = 0;
  91.   timer.it_interval.tv_usec = 0;
  92.   if (setitimer(ITIMER_VIRTUAL,&timer,NULL)) perror();
  93. }
  94.  
  95. void startup_tasking()
  96. {
  97. struct itimerval timer;
  98. struct sigvec task_struct;
  99. struct sigstack sig;
  100.  
  101.   /* Initialise the save buffer with enough space to save the MAIN thread */
  102.   TASKINFO.number_of_tasks = 0;
  103.   TASKINFO.context   = (struct sigcontext *)malloc(sizeof(struct sigcontext));
  104.   TASKINFO.last_task = 0;
  105.  
  106.   /* Create a signal stack for the scheduler to run on */
  107.   sig.ss_sp = (char *)malloc(1024);
  108.   sig.ss_onstack = 0;
  109.   if (sigstack (&sig,NULL) != 0) perror();
  110.  
  111.   /* Insert the scheduler into the signal handler table */
  112.   task_struct.sv_handler = task_control;
  113.   task_struct.sv_mask    = TASK_OFF;
  114. #ifdef SYMMETRY
  115.   task_struct.sv_onstack = 1;
  116. #endif
  117.   if (sigvec(SIGVTALRM,&task_struct,NULL) != 0) perror;
  118.  
  119.   /* Start off the timer to activate scheduler */
  120.   timer.it_value.tv_sec = 0;
  121.   timer.it_value.tv_usec = INTERVAL;
  122.   timer.it_interval.tv_sec = 0;
  123.   timer.it_interval.tv_usec = 0;
  124.   if (setitimer(ITIMER_VIRTUAL,&timer,NULL)) perror();
  125. }
  126.  
  127. /*
  128.  * This identifies a function as a task.
  129.  */
  130. void background_task(task_addr)
  131. void (* task_addr)();
  132. {
  133. char *newstack;
  134. struct sigcontext *cont;
  135. int bank,reg;
  136.   DISABLE_TASK_SWITCH();             /* Dont allow the scheduler to run here */
  137.   newstack = (char *)malloc(4000);   /* Create a new stack for the process */
  138.   TASKINFO.number_of_tasks+=1;       /* Increment the no of threads in system */
  139.   TASKINFO.context = (struct sigcontext *)
  140.            realloc(TASKINFO.context,(TASKINFO.number_of_tasks+1) * sizeof(struct sigcontext));
  141.  
  142.   /* Set up the initial state of the new thread */
  143. #ifdef SYMMETRY
  144.   cont = TASKINFO.context+TASKINFO.number_of_tasks;
  145.   cont->sc_onstack = 0;              /* sigstack state to restore */
  146.   cont->sc_mask    = TASK_ON ;       /* signal mask to restore */
  147.   cont->sc_sp      = (int)newstack;  /* sp to restore */
  148.   cont->sc_pc      = (int)task_addr; /* pc to restore */
  149. #endif
  150.  
  151.   ENABLE_TASK_SWITCH();              /* Restart the scheduler now */
  152. }
  153.  
  154. void task2()
  155. {
  156. int a,b,c;
  157.   c=0;
  158.   do {
  159.     DISABLE_TASK_SWITCH();
  160.     b=0; for (a=1; a<90000; a++) b+=a;
  161.     ENABLE_TASK_SWITCH();
  162.     printf ("Completed 90000 sum %x\n",b);
  163.   }while (1);
  164. }
  165.  
  166. void task1()
  167. {
  168. int a,b,c;
  169.   c=0;
  170.   do {
  171.     b=0; for (a=1; a<100000; a++) b+=a;
  172.     printf ("Completed 100000 sum %x\n",b);
  173.   }while (1);
  174. }
  175.  
  176. main()
  177. {
  178.   startup_tasking();
  179.   ENABLE_TASK_SWITCH(); 
  180.   background_task(task2); 
  181.   task1();
  182. }
  183.  
  184.  
  185. +--------------------------------+-------------------------------------------+
  186. |  Gordon Russell                |  EMAIL     : gor@cs.strath.ac.uk          |
  187. |  L13.13a, Livingstone Tower,   |  TELEPHONE : 041-552-4400   Ex 3703       |
  188. |  University Of Strathclyde,    |  FAX       : 041-552-0775                 |
  189. |  26 Richmond Street,           +-------------------------------------------+
  190. |  Glasgow, G1 1XH               | Spelling mistakes within this document are|
  191. |  Scotland, UK                  | caused by internet compaction algorithms. |
  192. +--------------------------------+-------------------------------------------+
  193.