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