Pelles C forum

Pelles C => Bug reports => Topic started by: 0x69 on May 02, 2012, 02:23:53 PM

Title: C11 - thread creation problem
Post by: 0x69 on May 02, 2012, 02:23:53 PM
Hi,

At first - thanks for such great C compiler which already implements C11 features, which not exists in many many other C compilers.

However when i try to execute such code:
Code: [Select]
#include <stdio.h>
#include <threads.h>

#define NUM_THREADS 10

int testFunction(void * data) {
printf("%d-th thread up\n", *(int*)data);
return 0;
}

int main(void) {
thrd_t threadId[NUM_THREADS];
int i;

for (i=0; i < NUM_THREADS; ++i)
if (thrd_create(threadId+i, testFunction, &i) != thrd_success)
printf("%d-th thread create error\n",i);

return 0;
}

I get that some threads not prints it's message. I suspect that this may be thread concurrency problem on shared resource. But this should result in out-of-order prints - not in skipping printf function calls - am I right ? Is it bug in thrd_create() function ? Or it is just "a bug" in my head ? Please explain ...
Title: Re: C11 - thread creation problem
Post by: iZzz32 on May 02, 2012, 03:28:57 PM
Disclaimer: I did not read C11 standard yet. But:

There are two problems. The first is:
Quote from: C11 draft
5.1.2.2.3
If the return type of the main function is a type compatible with int, a return from the
initial call to the main function is equivalent to calling the exit function
and later in 7.22.4.4:
The exit function causes normal program termination to occur.
You should somehow wait until your threads terminate. For example, do thrd_sleep in main() before return.

And the second problem is that when you call thrd_start, it waits until execution of the thread begins and returns. And after that there arises a race-condition: sometimes *data is read first by the thread and sometimes ++i in main would be faster. Again you should do some sort of synchronization and wait until your thread reads *data before starting the next thread.

Upd. Here is how it works on my computer:

Quote from: Without synchronization

C:\>pocc /c /MT test.c && polink test.obj && test.exe
5-th thread up
5-th thread up
5-th thread up
5-th thread up
5-th thread up

Quote from: With simple synchronization (looping on boolean value; it is a bad practice!)

C:\>pocc /c /MT test.c && polink test.obj && test.exe
0-th thread up
1-th thread up
2-th thread up
3-th thread up
4-th thread up
5-th thread up
6-th thread up
7-th thread up
8-th thread up
9-th thread up
Title: Re: C11 - thread creation problem
Post by: AlexN on May 02, 2012, 03:39:10 PM
I am also not sure if the created tasks have the ability to write at the standard-output (without extra code).
I would try to write from each task into an extra file, this is perhaps easier for first expreiments. ;)
Title: Re: C11 - thread creation problem
Post by: TimoVJL on May 02, 2012, 04:14:20 PM
Modified for testing. Run it several times to see differences.
Code: [Select]
#include <stdio.h>
#include <threads.h>

#define NUM_THREADS 10

int testFunction(void * data) {
printf("%d-th thread up\n", *(int*)data);
return 0;
}

int main(void) {
thrd_t threadId[NUM_THREADS];
int i, it[NUM_THREADS];

printf("start\n");
for (i=0; i < NUM_THREADS; ++i) {
it[i] = i;
if (thrd_create(threadId+i, testFunction, &it[i]) != thrd_success)
printf("%d-th thread create error\n",i);
}
printf("end\n");
_getch();
return 0;
}
Title: Re: C11 - thread creation problem
Post by: 0x69 on May 02, 2012, 05:41:33 PM
Thanks to all !
Title: Re: C11 - thread creation problem
Post by: alex-o2 on November 02, 2016, 09:11:09 PM
You should wait for the threads in the main program, otherwise it just ends before the threads... Eg. like this:
Code: [Select]
    // wait for all threads
    for (i=0; i < NUM_THREADS; ++i)
        thrd_join(threadId[i], NULL);