Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.programming.threads > #677 > unrolled thread

Is pthread_create( id, 0, f, &something_on_my_stack ); safe?

Started byJohann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com>
First post2011-11-21 03:29 +0000
Last post2011-11-22 21:06 +0100
Articles 13 — 8 participants

Back to article view | Back to comp.programming.threads


Contents

  Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> - 2011-11-21 03:29 +0000
    Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Ian Collins <ian-news@hotmail.com> - 2011-11-21 20:00 +1300
      Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Marcel Müller <news.5.maazl@spamgourmet.com> - 2011-11-21 08:48 +0100
      Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> - 2011-11-21 07:56 +0000
        Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Ian Collins <ian-news@hotmail.com> - 2011-11-21 21:01 +1300
        Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? David Schwartz <davids@webmaster.com> - 2011-11-21 12:06 -0800
          Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> - 2011-11-21 20:30 +0000
            Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Casper H.S. Dik <Casper.Dik@OrSPaMcle.COM> - 2011-11-21 23:07 +0000
              Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> - 2011-11-22 05:31 +0000
              Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? blmblm@myrealbox.com <blmblm.myrealbox@gmail.com> - 2011-11-25 17:49 +0000
            Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? David Schwartz <davids@webmaster.com> - 2011-11-23 12:53 -0800
    Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? Robert Wessel <robertwessel2@yahoo.com> - 2011-11-21 02:28 -0600
    Re: Is pthread_create( id, 0, f, &something_on_my_stack ); safe? "Ersek, Laszlo" <lacos@caesar.elte.hu> - 2011-11-22 21:06 +0100

#677 — Is pthread_create( id, 0, f, &something_on_my_stack ); safe?

FromJohann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com>
Date2011-11-21 03:29 +0000
SubjectIs pthread_create( id, 0, f, &something_on_my_stack ); safe?
Message-ID<4EC9C581.405E@2ndquadrant.com>
Hi all,

Given

  void *f( void *j )
  {
    int i = *((int *)j);
    //..
  }
 
  void g( void )
  {
    pthread_t *id = ...;
    int something_on_my_stack = 42; // Life, universe & everything
    pthread_create( id, 0, f, &something_on_my_stack );

is there any guarantee the value has been copied to f()s stack by the
time pthread_create() returns?

Or, to be a little bit more explicit, is there anything I can use for
safe argument passing to newly created threads without allocating new
memory and (presumably) have the threads free it?

My current design calls for two integers passed to the newly created
threads.  I want something both safe and clean.  That is, minimum of
code clutter.

  
-- 
   Johann Oskarsson                http://www.2ndquadrant.com/    |[]
   PostgreSQL Development, 24x7 Support, Training and Services  --+--
                                                                  |
   Blog: http://my.opera.com/myrkraverk/blog/

[toc] | [next] | [standalone]


#678

FromIan Collins <ian-news@hotmail.com>
Date2011-11-21 20:00 +1300
Message-ID<9iub8jF7g0U1@mid.individual.net>
In reply to#677
On 11/21/11 04:29 PM, Johann 'Myrkraverk' Oskarsson wrote:
> Hi all,
>
> Given
>
>    void *f( void *j )
>    {
>      int i = *((int *)j);
>      //..
>    }
>
>    void g( void )
>    {
>      pthread_t *id = ...;
>      int something_on_my_stack = 42; // Life, universe&  everything
>      pthread_create( id, 0, f,&something_on_my_stack );
>
> is there any guarantee the value has been copied to f()s stack by the
> time pthread_create() returns?

No.

> Or, to be a little bit more explicit, is there anything I can use for
> safe argument passing to newly created threads without allocating new
> memory and (presumably) have the threads free it?

I can't see any problem with

static int something_on_my_stack = 42;

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#679

FromMarcel Müller <news.5.maazl@spamgourmet.com>
Date2011-11-21 08:48 +0100
Message-ID<4eca026a$0$6570$9b4e6d93@newsspool3.arcor-online.net>
In reply to#678
On 21.11.2011 08:00, Ian Collins wrote:
> I can't see any problem with
>
> static int something_on_my_stack = 42;

Except that is no longer reentrant and you cannot run more than one 
thread in parallel this way.

The common way is to allocate something on the heap.


Marcel

[toc] | [prev] | [next] | [standalone]


#680

FromJohann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com>
Date2011-11-21 07:56 +0000
Message-ID<x6zkfp52nx.fsf@2ndquadrant.com>
In reply to#678
Ian Collins <ian-news@hotmail.com> writes:

Thank you.

> On 11/21/11 04:29 PM, Johann 'Myrkraverk' Oskarsson wrote:
>> Or, to be a little bit more explicit, is there anything I can use
>> for safe argument passing to newly created threads without
>> allocating new memory and (presumably) have the threads free it?
>
> I can't see any problem with
>
> static int something_on_my_stack = 42;

Unfortunately, the numbers are retrieved in a loop.  To be extra ex-
plicit, file descriptors from accept(), pipe() and friends.  I can't
see any way that does not involve either 1) memory allocation/freeing
or 2) synchronization.  Both seem unnecessary code bloat for such a
simple task.

I did not see it at the first glance at the FAQ.


-- 
   Johann Oskarsson                http://www.2ndquadrant.com/    |[]
   PostgreSQL Development, 24x7 Support, Training and Services  --+--
                                                                  |
   Blog: http://my.opera.com/myrkraverk/blog/

[toc] | [prev] | [next] | [standalone]


#681

FromIan Collins <ian-news@hotmail.com>
Date2011-11-21 21:01 +1300
Message-ID<9iuer1F7g0U2@mid.individual.net>
In reply to#680
On 11/21/11 08:56 PM, Johann 'Myrkraverk' Oskarsson wrote:
> Ian Collins<ian-news@hotmail.com>  writes:
>
> Thank you.
>
>> On 11/21/11 04:29 PM, Johann 'Myrkraverk' Oskarsson wrote:
>>> Or, to be a little bit more explicit, is there anything I can use
>>> for safe argument passing to newly created threads without
>>> allocating new memory and (presumably) have the threads free it?
>>
>> I can't see any problem with
>>
>> static int something_on_my_stack = 42;
>
> Unfortunately, the numbers are retrieved in a loop.  To be extra ex-
> plicit, file descriptors from accept(), pipe() and friends.  I can't
> see any way that does not involve either 1) memory allocation/freeing
> or 2) synchronization.  Both seem unnecessary code bloat for such a
> simple task.

Dynamic allocation is the idiomatic solution for any non-trivial 
situation.  Sometimes extra complexity is unavoidable.

-- 
Ian Collins

[toc] | [prev] | [next] | [standalone]


#683

FromDavid Schwartz <davids@webmaster.com>
Date2011-11-21 12:06 -0800
Message-ID<cae6c8c3-6406-485e-8cc2-7cda775a5f8d@h31g2000pro.googlegroups.com>
In reply to#680
On Nov 20, 11:56 pm, Johann 'Myrkraverk' Oskarsson
<joh...@2ndquadrant.com> wrote:

> Unfortunately, the numbers are retrieved in a loop.  To be extra ex-
> plicit, file descriptors from accept(), pipe() and friends.  I can't
> see any way that does not involve either 1) memory allocation/freeing
> or 2) synchronization.  Both seem unnecessary code bloat for such a
> simple task.

Here are the choices you have rejected:

1) Holding the value around until you are sure the new thread is done
with it (synchronization).

2) Giving the new thread its own copy so it can use it at its leisure
(memory allocating).

Even at a high level of generality, what could a third alternative
look like?

Your son needs a car. Either you share yours with him (option 1) or
you get him his own (option 2). What's the third choice?

DS

[toc] | [prev] | [next] | [standalone]


#684

FromJohann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com>
Date2011-11-21 20:30 +0000
Message-ID<x662id43re.fsf@2ndquadrant.com>
In reply to#683
David Schwartz <davids@webmaster.com> writes:

> On Nov 20, 11:56 pm, Johann 'Myrkraverk' Oskarsson
> <joh...@2ndquadrant.com> wrote:
>
>> Unfortunately, the numbers are retrieved in a loop.  To be extra
>> ex- plicit, file descriptors from accept(), pipe() and friends.  I
>> can't see any way that does not involve either 1) memory
>> allocation/freeing or 2) synchronization.  Both seem unnecessary
>> code bloat for such a simple task.
>
> Here are the choices you have rejected:

I did not reject them.  Both apply code overhead (as in, I write more
code) I have to maintain.  The more code I can get rid of the better.

> Your son needs a car. Either you share yours with him (option 1) or
> you get him his own (option 2). What's the third choice?

He buys his own.


-- 
   Johann Oskarsson                http://www.2ndquadrant.com/    |[]
   PostgreSQL Development, 24x7 Support, Training and Services  --+--
                                                                  |
   Blog: http://my.opera.com/myrkraverk/blog/

[toc] | [prev] | [next] | [standalone]


#685

FromCasper H.S. Dik <Casper.Dik@OrSPaMcle.COM>
Date2011-11-21 23:07 +0000
Message-ID<4ecad9c6$0$6961$e4fe514c@news2.news.xs4all.nl>
In reply to#684
Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> writes:

>David Schwartz <davids@webmaster.com> writes:

>> On Nov 20, 11:56 pm, Johann 'Myrkraverk' Oskarsson
>> <joh...@2ndquadrant.com> wrote:
>>
>>> Unfortunately, the numbers are retrieved in a loop.  To be extra
>>> ex- plicit, file descriptors from accept(), pipe() and friends.  I
>>> can't see any way that does not involve either 1) memory
>>> allocation/freeing or 2) synchronization.  Both seem unnecessary
>>> code bloat for such a simple task.
>>
>> Here are the choices you have rejected:

>I did not reject them.  Both apply code overhead (as in, I write more
>code) I have to maintain.  The more code I can get rid of the better.


If it's only one fd, cast it to a pointer and use the pointer as an
integer; there is really no reason to interpret the pointer as a
pointer, right?

Casper
-- 

[toc] | [prev] | [next] | [standalone]


#686

FromJohann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com>
Date2011-11-22 05:31 +0000
Message-ID<x6zkfo3epe.fsf@2ndquadrant.com>
In reply to#685
Casper H.S. Dik <Casper.Dik@OrSPaMcle.COM> writes:

> If it's only one fd, cast it to a pointer and use the pointer as an
> integer; there is really no reason to interpret the pointer as a
> pointer, right?

Alas, it's two or I'd probably do this.  I *might* restrict myself to
64bit compilations and encode the two integers in one pointer but
that's just silly and gains me nothing in maintainability.

Or I can "assume" the file descriptors are low and encode them both in
the same integer.  But that's even more silly and a maintenance
nightmare.


-- 
   Johann Oskarsson                http://www.2ndquadrant.com/    |[]
   PostgreSQL Development, 24x7 Support, Training and Services  --+--
                                                                  |
   Blog: http://my.opera.com/myrkraverk/blog/

[toc] | [prev] | [next] | [standalone]


#689

Fromblmblm@myrealbox.com <blmblm.myrealbox@gmail.com>
Date2011-11-25 17:49 +0000
Message-ID<9ja2ooFmj4U2@mid.individual.net>
In reply to#685
In article <4ecad9c6$0$6961$e4fe514c@news2.news.xs4all.nl>,
Casper H.S. Dik  <Casper.Dik@OrSPaMcle.COM> wrote:
> Johann 'Myrkraverk' Oskarsson <johann@2ndquadrant.com> writes:
> 
> >David Schwartz <davids@webmaster.com> writes:
> 
> >> On Nov 20, 11:56 pm, Johann 'Myrkraverk' Oskarsson
> >> <joh...@2ndquadrant.com> wrote:
> >>
> >>> Unfortunately, the numbers are retrieved in a loop. To be extra
> >>> ex- plicit, file descriptors from accept(), pipe() and friends. I
> >>> can't see any way that does not involve either 1) memory
> >>> allocation/freeing or 2) synchronization. Both seem unnecessary
> >>> code bloat for such a simple task.
> >>
> >> Here are the choices you have rejected:
> 
> >I did not reject them.  Both apply code overhead (as in, I write more
> >code) I have to maintain.  The more code I can get rid of the better.
> 
> 
> If it's only one fd, cast it to a pointer and use the pointer as an
> integer; there is really no reason to interpret the pointer as a
> pointer, right?
> 

There was a discussion of this topic in comp.lang.c recently:

http://groups.google.com/group/comp.lang.c/browse_thread/thread/9ce104bbf47d3fbc/c96cd19501ef372b?hl=en&q=#c96cd19501ef372b

I'm not sure it reached consensus, but the arguments against this
"use the pointer parameter to pass an integer" approach seemed
to boil down to "not guaranteed to work on all platforms" and
"likely to confuse other readers of the code".  To me the latter 
alone is a good reason to avoid it, but -- <shrug>.

-- 
B. L. Massingill
ObDisclaimer:  I don't speak for my employers; they return the favor.

[toc] | [prev] | [next] | [standalone]


#688

FromDavid Schwartz <davids@webmaster.com>
Date2011-11-23 12:53 -0800
Message-ID<8095043a-460b-4fd1-aa45-ae00da2aec7f@u10g2000prl.googlegroups.com>
In reply to#684
On Nov 21, 12:30 pm, Johann 'Myrkraverk' Oskarsson
<joh...@2ndquadrant.com> wrote:

> > Your son needs a car. Either you share yours with him (option 1) or
> > you get him his own (option 2). What's the third choice?
>
> He buys his own.

Well, yeah, that works in the hypothetical. But that wouldn't work in
this case. He wouldn't know what car to buy unless you wait until he's
finished buying a car, which is the synchronization you rejected.

DS

[toc] | [prev] | [next] | [standalone]


#682

FromRobert Wessel <robertwessel2@yahoo.com>
Date2011-11-21 02:28 -0600
Message-ID<hb2kc7hlrv0d2if3a8jcqvqrn1ghtafroq@4ax.com>
In reply to#677
On Mon, 21 Nov 2011 03:29:05 +0000, Johann 'Myrkraverk' Oskarsson
<johann@2ndquadrant.com> wrote:

>Hi all,
>
>Given
>
>  void *f( void *j )
>  {
>    int i = *((int *)j);
>    //..
>  }
> 
>  void g( void )
>  {
>    pthread_t *id = ...;
>    int something_on_my_stack = 42; // Life, universe & everything
>    pthread_create( id, 0, f, &something_on_my_stack );
>
>is there any guarantee the value has been copied to f()s stack by the
>time pthread_create() returns?
>
>Or, to be a little bit more explicit, is there anything I can use for
>safe argument passing to newly created threads without allocating new
>memory and (presumably) have the threads free it?
>
>My current design calls for two integers passed to the newly created
>threads.  I want something both safe and clean.  That is, minimum of
>code clutter.


Nothing really, in general.  Just allocate the memory and pass a
pointer to that.  It's simple, it works.

On occasion, it's reasonable to have the created thread post a
semaphore that the creator is waiting on, when the referenced items
are no longer needed.  That usually goes with needing to wait until
the created thread has started successfully (and is now ready to do
what ever it is it does), and having a large amount of startup data.
Of course in this case, you're now stuck passing the semaphore plus
the other data to the created thread, and that's going to be more work
than passing a couple of ints.

[toc] | [prev] | [next] | [standalone]


#687

From"Ersek, Laszlo" <lacos@caesar.elte.hu>
Date2011-11-22 21:06 +0100
Message-ID<Pine.LNX.4.64.1111222033040.25836@login03.caesar.elte.hu>
In reply to#677
On Mon, 21 Nov 2011, Johann 'Myrkraverk' Oskarsson wrote:

> Hi all,
>
> Given
>
>  void *f( void *j )
>  {
>    int i = *((int *)j);
>    //..
>  }
>
>  void g( void )
>  {
>    pthread_t *id = ...;
>    int something_on_my_stack = 42; // Life, universe & everything
>    pthread_create( id, 0, f, &something_on_my_stack );
>
> is there any guarantee the value has been copied to f()s stack by the
> time pthread_create() returns?
>
> Or, to be a little bit more explicit, is there anything I can use for
> safe argument passing to newly created threads without allocating new
> memory and (presumably) have the threads free it?
>
> My current design calls for two integers passed to the newly created
> threads.  I want something both safe and clean.  That is, minimum of
> code clutter.

If you don't need more than num_threads threads at any time:

static struct thread_arg
{
   int fd1,
       fd2;
} thread_arg[num_threads];

If you start a low fixed number of threads per core, this could work. (If 
you start threads for code organization purposes, not so much.) Just 
before (re-)starting thread #n (0 <= n < num_threads), fill in 
thread_arg[n], and pass &thread_arg[n] (written differently, thread_arg + 
n) to the start function. If necessary for other purposes, the thread can 
derive its own number from the arg address: (struct thread_arg *)arg - 
thread_arg.

If num_threads is not known at compile time, perhaps you could afford a 
single malloc() for the full array (and store the address in a "global" 
pointer). In C99 you might use a VLA that belongs to a block outliving all 
worker threads. As in:

struct thread_arg
{
   unsigned thread_nr;
   int fd1,
       fd2;
};

int
main(int argc, char **argv)
{
   unsigned num_threads;

   get_num_threads(&num_threads, argc, argv);

   {
     struct thread_arg thread_arg[num_threads];
     pthread_t worker[num_threads];
     unsigned u;

     for (u = 0u; u < num_threads; ++u) {
       struct thread_arg *cur;

       cur = thread_arg + u;
       cur->thread_nr = u;
       cur->fd1 = ...;
       cur->fd2 = ...;
       pthread_create(worker + u, 0, start_func, cur);
     }

     /* do whatever the "main thread" does */

     /* join all workers before thread_arg goes out of scope & life */
     for (u = 0u; u < num_threads; ++u) {
       pthread_join(worker[u], 0);
     }
   }

   return 0;
}

Laszlo

[toc] | [prev] | [standalone]


Back to top | Article view | comp.programming.threads


csiph-web