From elan@cheme.cornell.edu Thu Apr 14 03:47:06 1994
Received: from nef.ens.fr by clipper.ens.fr (4.1/version 1.10 of 88/05/05)
 	id AA20398; Thu, 14 Apr 94 03:47:05 +0200
Return-Path: <elan@cheme.cornell.edu>
Received-Date: Thu, 14 Apr 94 03:47:05 +0200
Received: from VGER.CHEME.CORNELL.EDU by nef.ens.fr (5.65c8/ULM-1.0)
	Id AA27538 ; Thu, 14 Apr 1994 03:47:08 +0200
Received: from tasha.cheme.cornell.edu by vger.cheme.cornell.edu (MX V3.3 VAX)
          with SMTP; Wed, 13 Apr 1994 21:47:10 EST
Received: from localhost by tasha.cheme.cornell.edu  with SMTP
          (5.65//ident-1.0) id AA21779; Wed, 13 Apr 1994 21:46:59 -0400
Message-Id: <9404140146.AA21779@tasha.cheme.cornell.edu>
To: rideau@clipper (Francois-Rene Rideau)
Subject: Re: Questions about EThreads
In-Reply-To: Your message of "Wed, 13 Apr 94 23:25:59 +0700."
    <9404132125.AA17021@clipper.ens.fr>
Date: Wed, 13 Apr 94 21:46:58 -0400
From: elan@cheme.cornell.edu
X-Mts: smtp
Status: OR


Hey, glad to hear that they are working for you OK so far!

> 1) I deeply appreciated that ethreads was completely in C (no asm statement),
> and that it was that small (as compared to other packages I've seen).

Thanks!  The fact that I was developing it under 80x86 and SPARC concurrently
left me no other option :)

> 2) I saw that a potential bug with preemption (on saturated systems) was that
> a signal could occur inside the context switch...

I assume you mean here:

...
      /* We just set up the new context for a thread */ 
      _t_arm_timer();
      longjmp(pRunningThread->State, 1); 
...

between these two statements.  If not, then let me know, because it may well
be a race condition.  However, if you do mean between the two statements, the
SIGVTALRM is masked out at the beginning of a context switch, in _t_sig_handler,
with 

 sigset_t  sigOldMask = sigblock(sigmask(SIGVTALRM));

so that no signals can occur until the longjmp takes place, restoring the old
signal mask.

There is no 3 (unlucky number? :)

> 4) can I enrich threads by save/restore procedures to execute when switching
> context 

Yes.  This is an interesting idea.  Simply add the function pointers to the
Thread data structure, and then call them at the appropriate time, after the
signals are masked.  Actually, there are certain places in the code where I
print debug code, if you've called t_debug(FILE *), and the statements it prints
in the file can give you a hook into certain places (thread_exit, 
thread_context_in/out, etc...)  Look at calls to _t_debug_dump(String).

> (that is, procedures to execute so that a thread always leave the
> machine in a clean state) ? 

I'm not sure what exactly you mean by "in a clean state" but you should be able
to do just about whatever you want.

> Of course, I can modify
> thread.[hc], but perhaps you can tell me more about that. After all, maybe
> I just must keep such things away, and program my server so I don't need this
> feature...

It should be trivial to add, and I find it very interesting!!

> 5) Can you explain to me how I can use conditions ? This seems very unclear to
> me. The general principle I understand (at each tick, look for certain
> conditions, and activate a thread if condition verified).

Basically, there are two types of conditions with EThreads.  Timed conditions,
and regular conditions.  The latter are simple:  t_wait(cond) saves the thread's
state, and the thread is not executed again until some thread does a t_sig(cond)
(on the cond that the other thread was waiting on).  If more than one thread
is waiting on the same condition, then only one gets run.

Timed conditions is a way to have a thread automatically
get signalled periodically.  You register a timed condition, and then you thread
will get signalled time after time, with a frequency that you specify in your
call to 

void       cond_registerRT(Condition pCond, clock_t clockInterval);

> 6) Your XBreadFactory program was incredibly slow (run on Linux 1.0, XFree 2.0
> Mono VGA server, 486DX33). It looks like no changes occured for minutes !
> As it was always sleeping, I "while true; do kill -CONT ; done" 'ed it: it
> still was slow, but now I could see it move. At any click, the window is
> dismissed; is that normal ?

Hum, you could try modifying the "tickle factor" in the following lines, in 


  /* Create an app timeout to serve as a tickler */
  timer = XtAppAddTimeOut(context, 10, TickleXWindow, Box);
				   ^^^

and see what happens.  I developed it under an S3 server, so it may be that
the graphics are inherantly slow.

> 7) Your package seems to work, but actually I've not tested it much: only one
> thread running, not for much time.

I've actually tested it pretty extensively, and so did the TA who ran the 
course, with many threads, conditions, for memory leaks, etc...

> 8) I'd like to queue/unqueue threads upon SIGUSR1. Is it safe to do, or must I
> better set a fla from SIGUSR1, then have a condition on the flag ? 

What do you mean by queue/unqueue?  Do you mean for scheduling purposes?

> In the
> later case, won't that prevent the scheduler from exiting the threading
> activity when it sees all threads and conditions are not running ?

It might depend on whether you have selected to handle or not Real Time 
scheduling failures (RTSF), via t_startRT(), depending on what you mean.  If 
you are handling RTSF, then if the condition receives a signal, and there is 
no thread waiting for it, then a RTSF is said to have occured.


      if (!cond_is_empty(p->pCond))
	t_sig(p->pCond, (any_ptr)&p->rtTimingInfo, FALSE);
      else if (fHandleFailures)
	t_exit_all(T_HARD_RT_FAIL);

> 9) I may be slow to use your package, as I have to write a nano-compiler for
> a compiling course, and a nano-database application for a database course
> (and after that, I'll work at proving the sensibleness of the prover of the
> "B" Workbench for formal programming).

Sounds like fun :)

> 10) Can a thread context-switch to a given other thread, so that it chooses
> what to do of the time allocated to it ? What routine must I modify or
> add (if I must) ?

Right now the threads are scheduled in round robin fashion.  You could add a
parameter to the thread creation routine, that takes a thread to switch to,
and then modify the scheduling algorithm to look first to see if the thread
to follow is ready to run.  Not that hard to implement, and certainly another
curious option.

> 11) As you may have seen, these points have been ordered only in chronological
> order of the appearance of the idea in my tortuous mind.

That's the best way to do it :) I hope my answers have cleared up some of the 
questions you had!  I'll include them in a FAQ perhaps...

> 12) I transformed Boolean into an enum type in standard.h, and added three
> functions in queue.c: q_journey, q_size, and q_realsize. The first function
> executes some command for every node in the queue, the later return size of
> the queue and size of the queue plus size of the tail.

The boolean probably makes more sense like you have it, and then extra q_*
routines are interesting, to say the least.  It's great to see what you've
done as far as thinking of new functionality to add to the package!  I'm
busy cleaning up debug.c/h and then I'll probably make the first net release.

Take care, mon ami...

elan

PS Don't hesitate to ask more questions!

