You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@httpd.apache.org by Ben Hyde <bh...@pobox.com> on 1999/05/18 16:40:20 UTC

ap_current_thread?

I would like to have a routine in the APR API like so:

   ap_thread_t *ap_current_thread(void)


Let's work a little on the issue of what the thread
model looks like.

Let's look as some of the current code in 1.3.

API_EXPORT(void *) ap_palloc(struct pool *a, int reqsize)
{
   .. try to use a block alrady in the pool ...
   .. rarely fail ... then
    ap_block_alarms();
    (void) ap_acquire_mutex(alloc_mutex);
     ... utilize the global freelist of large blocks ...
    (void) ap_release_mutex(alloc_mutex);
    ap_unblock_alarms();
   .. etc ...
}

There are two syncronization things going on here.
 1) blocking signals.
 2) multiplexing the global freelist of large blocks.

The blocking of signals needs to change.

   ap_block_alarms(<expression that gets current thread>);

One of the many dimensions of this context debate is what
  <expression that gets current thread>
expression is.  

   a)  cntx->thread
   b)  pool->thread
   c)  ap_current_thread()

I have been arguing that B is the right awnser.

I'd like to change my mind.

I now think C is the right awnser.  Can the advocates of the context
explain why they would prefer not to have a

   ap_thread *ap_current_thread(void)

routine?

 - ben

Re: ap_current_thread?

Posted by Ben Hyde <bh...@pobox.com>.
Ryan Bloom <rb...@raleigh.ibm.com> writes:

> >    ap_thread *ap_current_thread(void)
> 
> I have avoided writing this routine, because I am not sure of the best way
> to do it.  I would rather not have a thread table inside of APR, that is
> what the OS is for.  I need to determine if just calling pthread_self (or
> it's equivalent) is enough, or if it is possible that in the future I
> would need to store my own thread info.


I've been assuming roughly that this is what a thread
create would look like..

  #define MAKE_INSTANCE(p,type) ((type *)ap_palloc(p,sizeof(type)))

  ap_thread_t *ap_thread_create(ap_thread_t *parent, 
                                ap_thread_main_t *f, 
                                void *thunk)
  {
    ap_pool_t *thread_pool = ap_make_sub_pool(parent->pool);
    ap_thread_t *t = MAKE_INSTANCE(thread_pool, ap_thread_t);
   
    t->user_data = NULL; 
    t->pool = thread_pool;
    t->parent = parent_thread;
    t->interupt_handling = ...
    ... platform specific code ...
    ... push(thread, parent->children)...
    return t;
  }

I.e. that every thread would have it's own private pool
for it's fast working storage, and that the tree of 
threads would reside in the tree of pools.

Thread_pool as shown above is critical to making allocation
lock free in the usual case for majority of thread allocation.

Since the platform specific code, is platform specific, it can
use thread local storage to store the state that implements
current_thread.  So I agree that the thread table is a platform
issue, not necessarily represented in APR.  The thread tree, I
think it deserves to be represented in APR.

 - ben


Re: ap_current_thread?

Posted by Ryan Bloom <rb...@raleigh.ibm.com>.
> > Two different flags.  One flag in the context is for being signal safe,
> > another is for being cancellation safe.  IMHO, when we are in a section
> > of code like this one, we just disallow cancellation of this thread, or
> > signals.
> 
> I assume by "cancellation of this thread" you mean thread's pool cleaups
> are run via to ap_destroy_pool and the thread is then destroyed.

Yes.  There is a function in pthreads that lets me hook into it's cleanup
stack.  I keep meaning to put that code in, but I also keep forgetting.
I'll get to it soon, I promise.  Basically, whenever the thread goes away,
the VERY last thing it will ALWAYS do is a cleanup of it's own pool.  This
will be accomplished with pthread_cleanup_push in the pthread
implementation, and I am assuming that other thread impl's have similar
functions.

> 
> What do you mean by "signal" is that a thread or a process operation -
> why is it per context?

signal is a UNIX signal.  In it's cleanest form, it is a process
operation, but once you add threads into the picture, you also have the
ability to signal any thread within the process.  If the signal is coming
from within the same process, you CAN (with pthread_kill), but don't have
to,  signal a specific thread.  If the signal is coming from another
process (using kill of killpg), it is undefined which thread gets the
signal.  There is no way of knowing in advance which thread will get the
signal, unless only one thread is listening for the signal.  On Linux,
this isn't quite true, but it's close.  It is per context for the precise
reason that it is allowed on both a thread and/or a process.  I can 
block signals for just this thread, or just this process, or all
threads within this process, or all process, or any combination of the
above.

In my mind, this makes it bigger than threads or processes, and that makes
it a context issue.

> > We don't actually have to pass a thread pointer down to
> > ap_block_alarms, because we only care about the current thread.  The OS
> > takes care of figuring out which thread we mean.
> 
> Agreed, in fact you don't need it in the context either.

I am confused.  The message about ap_current_thread made it look like you
were advocating:

ap_block_alarms(ap_current_thread())

I would rather not have a current thread pointer in the context type.  I
would like the context type to have a pool, some flags for APR's use, and
a place for the user to store some data if they desire.  That's it.  If we
find more stuff to put into the context later, so be it.  I am having a
hard time figuring out where else to put these APR flags if not in a
context.  I could put them in the process/thread types, but then the user
would have to specify them multiple times.  I could put them in the pool,
but they have nothing to do with a pool (except that the pool code will
use them), and this seems like a HUGE hack to me.  Contexts make the most
sense for this , IMHO.

> No long jump - it is the easiest design to agree on.  So be it.

Hey, does this mean we are coming close to an agreement??? :)

Ryan

_______________________________________________________________________
Ryan Bloom		rbb@raleigh.ibm.com
4205 S Miami Blvd	
RTP, NC 27709		It's a beautiful sight to see good dancers 
			doing simple steps.  It's a painful sight to
			see beginners doing complicated patterns.	



Re: ap_current_thread?

Posted by Ben Hyde <bh...@pobox.com>.
Ryan Bloom <rb...@raleigh.ibm.com> writes:

> Two different flags.  One flag in the context is for being signal safe,
> another is for being cancellation safe.  IMHO, when we are in a section
> of code like this one, we just disallow cancellation of this thread, or
> signals.

I assume by "cancellation of this thread" you mean thread's pool cleaups
are run via to ap_destroy_pool and the thread is then destroyed.

What do you mean by "signal" is that a thread or a process operation -
why is it per context?

> We don't actually have to pass a thread pointer down to
> ap_block_alarms, because we only care about the current thread.  The OS
> takes care of figuring out which thread we mean.

Agreed, in fact you don't need it in the context either.

> > If threads are never: unwound, canceled, interupted, or signaled then
> > there is no need an API on the thread to manage if that
> > unwinding/canceling/interupting/signalling is enabled/disabled at any
> > given moment.
> 
> I do not believe we will be doing any longjmp's within threads.  As far as
> I know, this is a very dangerous operation, and it is not recommended.  I
> know the current state of the hybrid server has no setjump or longjmp
> calls in it, and we took great care to make sure they aren't needed.

No long jump - it is the easiest design to agree on.  So be it.

 - ben

Re: ap_current_thread?

Posted by Ryan Bloom <rb...@raleigh.ibm.com>.
> > I don't understand why ap_block_alarms needs the current thread.
> > ap_block_alarms is used to make sure that we aren't going to be
> > interrupted by receiving a signal while in this code.
> 
> I thought we had decided to attempt to provide for
> canceling/interupting, etc. individual threads so that in at least
> some cases we could terminate with prejudice threads that seem to have
> gone astray.  I'm right about that, arn't I.

Two different flags.  One flag in the context is for being signal safe,
another is for being cancellation safe.  IMHO, when we are in a section
of code like this one, we just disallow cancellation of this thread, or
signals.  We don't actually have to pass a thread pointer down to
ap_block_alarms, because we only care about the current thread.  The OS
takes care of figuring out which thread we mean.

> 
> If threads are never: unwound, canceled, interupted, or signaled then
> there is no need an API on the thread to manage if that
> unwinding/canceling/interupting/signalling is enabled/disabled at any
> given moment.

I do not believe we will be doing any longjmp's within threads.  As far as
I know, this is a very dangerous operation, and it is not recommended.  I
know the current state of the hybrid server has no setjump or longjmp
calls in it, and we took great care to make sure they aren't needed.

Ryan

_______________________________________________________________________
Ryan Bloom		rbb@raleigh.ibm.com
4205 S Miami Blvd	
RTP, NC 27709		It's a beautiful sight to see good dancers 
			doing simple steps.  It's a painful sight to
			see beginners doing complicated patterns.	


Re: ap_current_thread?

Posted by Ben Hyde <bh...@pobox.com>.
Ryan Bloom <rb...@raleigh.ibm.com> writes:

> I don't understand why ap_block_alarms needs the current thread.
> ap_block_alarms is used to make sure that we aren't going to be
> interrupted by receiving a signal while in this code.

I thought we had decided to attempt to provide for
canceling/interupting, etc. individual threads so that in at least
some cases we could terminate with prejudice threads that seem to have
gone astray.  I'm right about that, arn't I.

If threads are never: unwound, canceled, interupted, or signaled then
there is no need an API on the thread to manage if that
unwinding/canceling/interupting/signalling is enabled/disabled at any
given moment.

 - ben

Re: ap_current_thread?

Posted by Ryan Bloom <rb...@raleigh.ibm.com>.
I'm am really not sure I follow you.  I agree this function is needed.  I
haven't quite gotten to it.  The original spec was created by taking the
NSPR calls that were made in the apache-nspr repository and determining
what they did.  We never made a call to get the current thread in
apache-nspr.

> There are two syncronization things going on here.
>  1) blocking signals.
>  2) multiplexing the global freelist of large blocks.
> 
> The blocking of signals needs to change.
> 
>    ap_block_alarms(<expression that gets current thread>);
> 
> One of the many dimensions of this context debate is what
>   <expression that gets current thread>
> expression is.  

I don't understand why ap_block_alarms needs the current thread.
ap_block_alarms is used to make sure that we aren't going to be
interrupted by receiving a signal while in this code.  In 1.3, the only
signals the child dealt with were HUP, TERM, and USR1.  All three signal
handlers checked the value of alarms_blocked (probably not the right
name), and defered what they had to do if we were in the middle of a
critical section.

Because this code is now going into APR, and we are allowing users to set
their own signal handlers, we can't garauntee they will set the equivalent
of alarms_blocked correctly, nor even check when important, so we aren't
going to make them.  Instead, we are basically going to give them the
option of blocking all signals in the critical section, or not depending
on what they are coding.  For example, somebody writing code that will
NEVER be interrupted would not want to block any signals in APR.  Most
people will want to block siganls.

This is not a thread issue!  I still do not understand why you want to say
it is.  This is an issue about how APR functions.  How ALL of APR will
function in the users code.

> 
>    a)  cntx->thread
>    b)  pool->thread
>    c)  ap_current_thread()
> 
> I have been arguing that B is the right awnser.
> 
> I'd like to change my mind.
> 
> I now think C is the right awnser.  Can the advocates of the context
> explain why they would prefer not to have a

I do not think any of the context advocates have said this function isn't
necessary.  If you look at the original or current context implementation,
you will see no mention of threads.  I conceeded to put threads into
contexts at some point in the future when this discussion began, because
you asked me to.  That is the only time threads and contexts were ever
mixed.

> 
>    ap_thread *ap_current_thread(void)
> 
> routine?

I have avoided writing this routine, because I am not sure of the best way
to do it.  I would rather not have a thread table inside of APR, that is
what the OS is for.  I need to determine if just calling pthread_self (or
it's equivalent) is enough, or if it is possible that in the future I
would need to store my own thread info.

Ryan

_______________________________________________________________________
Ryan Bloom		rbb@raleigh.ibm.com
4205 S Miami Blvd	
RTP, NC 27709		It's a beautiful sight to see good dancers 
			doing simple steps.  It's a painful sight to
			see beginners doing complicated patterns.