I use pthread_create to create 10 child threads, passes an integer to the thread_func
#define THREAD_NUM 10
void *thread_func(void *arg)
{
int v = (int)arg;
printf("v = %d\n", v);
return (void*)0;
}
int main(int argc, const char *argv[])
{
pthread_t pids[THREAD_NUM];
int rv;
int i;
for (i = 0; i < THREAD_NUM; i++) {
rv = pthread_create(&pids[i], NULL, thread_func, (void*)i);
if (rv != 0) {
perror("failed to create child thread");
return 1;
}
}
return 0;
}
I was wondering why it outputs different result everytime not just
v = 1
v = 2
...
v = 9
You have to wait for all the threads to complete in the main using pthread_join, only then u can see all of them display some value
#include <stdio.h>
#include <pthread.h>
#define THREAD_NUM 10
void *thread_func(void *arg)
{
int v = (int)arg;
printf("v = %d\n", v);
return (void*)0;
}
int main(int argc, const char *argv[])
{
pthread_t pids[THREAD_NUM];
int rv;
int i;
for (i = 0; i < THREAD_NUM; i++) {
rv = pthread_create(&pids[i], NULL, thread_func, (void*)i);
if (rv != 0) {
perror("failed to create child thread");
return 1;
}
}
for (i = 0; i < THREAD_NUM; i++) {
pthread_join(pids[i], NULL);
}
return 0;
}
Sample run output:
[root#fc ~]# ./a.out
v = 0
v = 2
v = 4
v = 6
v = 7
v = 8
v = 9
v = 5
v = 3
v = 1
I think your question is why it is not printing them in order like v=1 v = 2 ... v = 9. That is because the kernel schedules the threads and they can be scheduled in any order. If you want synchronized output you need to use locks and condition variables.
In my case I am having proper out put.
I have done some modification. Can you give a try to it?
#include <stdio.h>
#include <pthread.h>
#define THREAD_NUM 10
void *thread_func(void *arg)
{
int v = *(int *)arg;
printf("v = %d\n", v);
return (void*)0;
}
int main(int argc, const char *argv[])
{
pthread_t pids[THREAD_NUM];
int rv;
int i;
for (i = 0; i < THREAD_NUM; i++) {
rv = pthread_create(&pids[i], NULL, thread_func, (void*)&i);
if (rv != 0) {
perror("failed to create child thread");
return 1;
}
}
return 0;
}
Briefly, echo of the threads in your program is an independent scheduling unit, which means they can actually or virtually run parallelly in an order determined by the scheduler in your operating system kernel, and this order changes run to run according to your system circumstances at that time.
Related
This question already has answers here:
How to use shared memory with Linux in C
(5 answers)
Closed 4 years ago.
This is essentially what I want to do, but the outputs are junk data. What are some of the different options I have for making the child's array visible from inside the parent process?
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
int main()
{
int foo[3]; //initialize array
pid_t pid;
pid = fork(); //create child thread
if (pid == 0) { //child:
foo[0] = 0; foo[1] = 1; foo[2] = 2; //populate array
}
else { //parent:
wait(NULL); //wait for child to finish
printf("%d %d %d", foo[0], foo[1], foo[2]); //print contents of array
}
return 0;
}
Using mmap you can create a shared memory block in your parent process. This is a basic example removing error checking for brevity.
You want to sure the proper protections and flags are set for your needs. Then hand off the address returned by mmap to your child process.
#include <stdio.h>
#include <stdlib.h>
#include <sys/mman.h>
#include <sys/wait.h>
#include <unistd.h>
#define LIMIT_MAP 5
void child_worker(void *map)
{
int map_value = -1;
int idx = 0;
while (map_value != LIMIT_MAP) {
map_value = *((int *) map + (idx * sizeof(int)));
printf("Map value: %d\n", map_value);
idx++;
sleep(2);
}
}
int main(int argc, char *argv[])
{
printf("Starting Parent Process...\n");
long page_size = sysconf(_SC_PAGESIZE);
void *memory_map = mmap(0, page_size, PROT_WRITE | PROT_READ,
MAP_SHARED | MAP_ANONYMOUS, 0, 0);
printf("Memory map created: <%p>\n", memory_map);
pid_t pid = fork();
if (pid == 0) {
sleep(1);
printf("Starting child process\n");
child_worker(memory_map);
printf("Exiting child process...\n");
return 0;
} else {
printf("Continuing in parent process\n");
int set_values[5] = { 1, 2, 3, 4, 5 };
for (int i=0; i < 5; i++) {
printf("Setting value: %d\n", set_values[i]);
*((int *) memory_map + (sizeof(int) * i)) = set_values[i];
sleep(1);
}
waitpid(pid, NULL, 0);
printf("Child process is finished!\n");
}
return 0;
}
If fork isn't a requirement and your platform allows for it, pthread is one option. Depending on how your array is being operated on, create a thread pool passing each worker thread a copy of your array.
This is a contrived example but maybe you can pull something from it:
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdbool.h>
#include <pthread.h>
#define THREAD_COUNT 3
#define ITER_LIMIT 7
struct worker_params {
int idx;
int max;
bool done;
double *data;
double condition;
};
void *worker(void *arg)
{
struct worker_params *wp = (struct worker_params *) arg;
int count = 0;
while ( 1 ) {
wp->data[wp->idx] = drand48();
if (wp->max == count)
wp->done = true;
sleep(1);
count++;
}
return NULL;
}
int main(int argc, char *argv[])
{
double data[THREAD_COUNT] = { 0.0 };
pthread_t worker_1, worker_2, worker_3;
pthread_t worker_threads[] = { worker_1, worker_2, worker_3 };
struct worker_params wps[] = {
{ .idx=0, .condition=0.1, .data=data, .done=0 },
{ .idx=1, .condition=0.2, .data=data, .done=0 },
{ .idx=2, .condition=0.3, .data=data, .done=0},
};
for (int i=0; i < THREAD_COUNT; i++) {
wps[i].max = (rand() % ITER_LIMIT) + 2;
pthread_create(&worker_threads[i], NULL, worker, (void *) &wps[i]);
}
// Continue on main execution thread
int running = 1;
while ( running ) {
for (int i=0; i < THREAD_COUNT; i++) {
if (wps[i].done) {
printf("Limit hit in worker <%d>\n", i + 1);
running = 0;
break;
}
printf("Data in worker <%d> :: %g\n", i + 1, wps[i].data[i]);
}
sleep(1);
}
return 0;
}
Here is what I need to do:
Write a pthread program that takes an integer command line argument n,
spawns n threads that will each generate a random numbers between -100
and 100, and then computes and prints out the sum of these random
numbers. Each thread needs to print out the random number it
generates.
Here is what I have:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
int randomNum=0;
int randomSum=0;
void *randomNumberGenerator(void *id){
int *myid = (int *)id;
randomNum = rand()% 201 + (-100);
printf("%d\n", randomNum);
randomSum+=randomNum;
}
int main (int argc , char *argv[]){
int command;
char *strNumThreads = NULL;
int i;
while((command = getopt(argc, argv, "n:"))!=-1){
if(command == 'n'){
strNumThreads = optarg;
break;
}
}
int numThreads = atoi(strNumThreads);
pthread_t thread;
int newThread;
for(i = 0; i<numThreads; i++){
srand(time(NULL));
pthread_create(&thread, NULL, randomNumberGenerator, (void*)i);
}
pthread_exit(NULL);
printf("%d\n" , randomSum);
return 0;
}
For some reason randomSum is not getting printed.
randomNum is a variable that is shared among all threads, so you need a mutex
when you access the variable, because randomSum+=randomNum; is not an atomic
operation. The current process might get interrupted and another process is
scheduled which changes both variables. When the interrupted process resumes, it
will overwrite randomNum and you end up with garbage.
Also you have to wait for all threads to finish until you print the sum. For
that you have to execute pthread_wait.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
// can be a global variable
int randomSum=0;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void *randomNumberGenerator(void *id){
int randomNum=0; // does not need to be a global variable
randomNum = rand()% 201 + (-100);
printf("%d\n", randomNum);
pthread_mutex_lock(&mutex);
randomSum+=randomNum;
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
int main (int argc , char *argv[]){
int command;
char *strNumThreads = NULL;
int i;
while((command = getopt(argc, argv, "n:"))!=-1){
if(command == 'n'){
strNumThreads = optarg;
break;
}
}
// initializing the randomizer
srand(time(NULL));
int numThreads = atoi(strNumThreads);
if(numThreads == 0)
{
fprintf(stderr, "Invalid number of threads\n");
return 1;
}
pthread_t threads[numThreads];
for(i = 0; i<numThreads; i++){
pthread_create(threads + i, NULL, randomNumberGenerator, NULL);
}
for(i = 0; i < numThreads; ++i)
pthread_join(threads[i], NULL);
printf("%d\n" , randomSum);
return 0;
}
You really need to learn how to use the libraries you are using. pthread_exit
must be used by the threads to tell the system "I'm finished", calling it in the
main thread makes no sense.
pthread_create(&thread, NULL, randomNumberGenerator, (void*)i);
I consider this an uggly hack, what you should do is create an array with the
ids of the threads and pass every thread a pointer to its id, like this:
int ids[numThreads];
for(i = 0; i<numThreads; i++){
ids[i] = i;
pthread_create(&thread, NULL, randomNumberGenerator, ids+i);
}
and in the thread you can do
void *randomNumberGenerator(void *idp) {
int *id = idp;
printf("My thread id is %d\n", *id);
...
pthread_exit(NULL);
}
And if your worker threads are just calculating a value, you can use
pthread_exit to return that value back to the main thread. For example:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <getopt.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
struct thdata {
int id;
int random;
};
void *randomNumberGenerator(void *data) {
struct thdata *ret = data;
ret->random = rand()% 201 + (-100);
printf("thread with id %d: random %d\n", ret->id, ret->random);
pthread_exit(data);
}
int main (int argc , char *argv[]){
int i;
// initializing the randomizer
srand(time(NULL));
int numThreads = 5;
if(numThreads == 0)
{
fprintf(stderr, "Invalid number of threads\n");
return 1;
}
pthread_t threads[numThreads];
struct thdata data[numThreads];
for(i = 0; i<numThreads; i++){
data[i].id = i;
pthread_create(threads + i, NULL, randomNumberGenerator, data+i);
}
int randomSum = 0;
for(i = 0; i < numThreads; ++i)
{
struct thdata *data;
pthread_join(threads[i], (void**) &data);
randomSum += data->random;
}
printf("The sum of the random values is: %d\n" , randomSum);
return 0;
}
Which gives me the output (for 5 threads):
thread with id 0: random 72
thread with id 4: random -94
thread with id 1: random 1
thread with id 2: random -74
thread with id 3: random 42
The sum of the random values is: -53
You currently have a data race in place, because you have multiple threads accessing randomSum concurrently. Here's a solution, with comments, using Mutexes to solve the problem.
Note how using a struct to hold the sum and it's mutex allows us to get rid of all globals.
As a plus, I replaced your random generator with a proper one on POSIX systems. Note that your multiple calls to srand() are wrong, and cause less randomicity. You should only ever call srand() once, to generate the seed.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
#include <limits.h>
#include <time.h>
#include <pthread.h>
static bool HAS_URANDOM = true; // Global
unsigned int random_uint() {
unsigned int r_uint;
// Try to open the random generator device
FILE *f = fopen("/dev/urandom", "r");
if (f == NULL) {
if (HAS_URANDOM) {
// Warn that urandom isn't working, but fallthrough to rand()
printf("---- Failed loading random generator device /dev/urandom. Defaulting to rand().\n");
srand((unsigned int) time(NULL));
HAS_URANDOM = false;
}
r_uint = (unsigned int) rand();
} else {
// If we have urandom, just read from it and cast to uint
fread(&r_uint, sizeof(r_uint), 1, f);
fclose(f);
}
return r_uint;
}
// Inclusive range
// https://stackoverflow.com/a/17554531/2080712
unsigned int generate_uint(unsigned int lower, unsigned int upper) {
if (upper - lower == UINT_MAX) {
fprintf(stderr, "Invalid bounds on generate_int().\n");
exit(EXIT_FAILURE);
}
unsigned int r_uint;
const unsigned int range = 1 + (upper - lower);
if (range == 0) {
fprintf(stderr, "Invalid range!\n---- upper=%d\n---- lower=%d\n---- range=%d\n", upper, lower, range);
exit(EXIT_FAILURE);
}
const unsigned int buckets = UINT_MAX / range;
const unsigned int limit = buckets * range;
/* Create equal size buckets all in a row, then fire randomly towards
* the buckets until you land in one of them. All buckets are equally
* likely. If you land off the end of the line of buckets, try again. */
do {
r_uint = random_uint();
} while (r_uint >= limit);
unsigned int res = lower + (r_uint / buckets);
return res;
}
typedef struct {
pthread_mutex_t lock; // Our lock to avoid data races
long sum; // The sum value
} sum_t;
// Thread function
void *do_sum(void *arg) {
sum_t *sum = (sum_t*)(arg); // Reinterpret the argument as sum_t
int val = generate_uint(0, 100) - 100; // Generate an integer in the range we want
pthread_mutex_lock(&sum->lock); // Lock the value
sum->sum += val; // Sum
pthread_mutex_unlock(&sum->lock); // Unlock the value
return NULL;
}
int main(int argc, char *argv[]) {
// Guarantee argument
if(argc != 2) {
printf("Please provide a number of threads.\n");
exit(EXIT_FAILURE);
}
// Get our thread count
long count = strtol(argv[1], NULL, 10);
// Allocate threads
pthread_t threads[count];
// Create & initialize sum structure
sum_t sum;
pthread_mutex_init(&(sum.lock), NULL);
sum.sum = 0;
// Run sum threads
for (long i = 0; i < count; ++i) {
pthread_create(&(threads[i]), NULL, do_sum, &sum);
}
// Wait until they have finished
for (long i = 0; i < count; ++i) {
pthread_join(threads[i], NULL);
}
// Destroy the mutex lock
pthread_mutex_destroy(&(sum.lock));
// Print result
printf("%ld\n", sum.sum);
return 0;
}
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <stdlib.h>
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
void* thread_even(void* arg);
void* thread_odd(void* arg);
int main(int argc, char** argv) {
pthread_t tid[2];
pthread_create(&tid[0], 0, &thread_even, 0);
pthread_create(&tid[1], 0, &thread_odd, 0);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
return 0;
}
void* thread_even(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 != 0)
{
printf("Thread 1: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
void* thread_odd(void* arg) {
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
{
if(i%2 == 0)
{
printf("Thread 2: %d", i);
}
}
pthread_mutex_unlock(&mutex);
return NULL;
}
The above is the code I am working on but I get a segment fault error... What I want to achieve is, for example,
when I compile it and run with an argument 8 (./number 8)
it should print out
thread 1: 1
thread 2: 2
thread 1: 3
... etc till the number, 8.
in which thread 1s should represent the even numbers and the thread 2s stand for the odd numbers.
Please help... I want to develop my knowledge about C but have no one to ask..
Thanks.
Looks like you are passing 0 AKA NULL to the last parameter of pthread_create, and then doing the following:
int* thread_id = (int*)arg;
pthread_mutex_lock(&mutex);
for(int i = 1; i <= *thread_id; i++)
So, thread_id will certainly be NULL, referencing it will be a SEGFAULT.
If you want to pass an upper bound for each thread to run to, do you can do something like this:
int main(int argc, char** argv) {
pthread_t tid[2];
int *ids = malloc(2 * sizeof(int));
ids[0] = 10; /* upper bound for thread 1 */
ids[1] = 10; /* upper bound for thread 2 */
pthread_create(&tid[0], 0, &thread_even, &ids[0]);
pthread_create(&tid[1], 0, &thread_odd, &ids[1]);
pthread_join(tid[0], NULL);
pthread_join(tid[1], NULL);
free(ids);
return 0;
}
There are ways to do this without resorting to heap allocation, but this is the most straight forward.
My program's desired functionality:
Using the command line user inputs N and M. N is the number of new threads that will be created and M is the number of how much every thread increments the global variable A.
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
void *Thread(void* x){
int i;
int n = *((int*)x);
for (i = 0; i<n; i++){
A++;
}
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
return 0;
}
The problem is that every time I run it there's a different output.
Screenshot of my terminal when i run the program multiple times in a row
The problem is that you are creating multiple threads that in parallel are trying to modify your static A global variable at the same time, without any kind of protection.
That means that depending on the scheduling of the threads, the changes on your global variable will not be atomic, producing this effect.
You can solve this with a mutex, declare it with:
pthread_mutex_t mutex;
And initialise / release it with pthread_mutex_init and pthread_mutex_destroy.
Inside of the thread, before doing the change protect the resource to change with pthread_mutex_lock, and release it with pthread_mutex_unlock. So the code will be changed like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
static int A = 0;
pthread_mutex_t mutex;
void *Thread(void* x){
int i;
int n = *((int*)x);
pthread_mutex_lock(&mutex);
A += n;
pthread_mutex_unlock(&mutex);
}
int main(int argc, char* argv[]){
int i;
int N = atoi(argv[1]);
int M = atoi(argv[2]);
pthread_mutex_init(&mutex, NULL);
pthread_t *thread = (pthread_t *) malloc(sizeof(pthread_t)*N);
if(!thread){
printf("No memory\n");
exit(2);
}
for (i = 0; i< N; i++){
if (pthread_create(&thread[i], NULL, Thread, &M)){
printf("Not able to create a thread\n");
exit(1);
}
}
for(i = 0; i< N; i++)
pthread_join(thread[i], NULL);
printf("A = %d\n", A);
pthread_mutex_destroy(&mutex);
return 0;
}
I keep getting a seg fault (core dump) after pthread_join in my program. It prints out the expected result just fine, but seg faults when joining the thread. I have looked at several other discussions on this topic, but none of the suggested solutions seem to work in my case. Here is what my compile command looks like (no compile warnings or errors):
$ gcc -Wall -pthread test.c -o test
Here is the output:
$ ./test
1 2 3 4 5 6 7 8 9 10
Segmentation fault (core dumped)
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
void *fillArray(int *size) {
int i;
for (i = 0; i < *size; i++) {
array[i] = i+1;
}
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
rc = pthread_create(&thread, NULL, fillArray(&size), &res);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Any ideas what could be the cause?
This doesn't compile for me: It fails with
dummy.cpp: In function ‘int main(int, char**)’:
dummy.cpp:29: error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
dummy.cpp:29: error: initializing argument 3 of ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
Which is because you're actually calling fillArray and passing its result to pthread_create, rather than passing the function pointer. I expect your code will need to look more like this (UNTESTED!) : (Note I changed signature of fillArray, created data struct type to pass to fillArray, changed how pthread_create is called)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
struct fillArrayData {
int * array;
int size;
int * result;
};
void *fillArray(void *void_data) {
fillArrayData * data = (fillArray*)void_data;
for (int i = 0; i < data.size; i++) {
data.array[i] = i+1;
}
//You could fill in some return info into data.result here if you wanted.
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
fillArrayData data;
data.array = array;
data.size = 10;
rc = pthread_create(&thread, NULL, fillArray, &data);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Error in
Calling function pointer
passing parameter to thread handler
In pthread prototype of pthread_create below
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
1st argument - pthread_variable
2nd argument - thread attrubutes
3rd argument - thread handler(function pointer name)
4th argument - variable need to pass thread handler.
In 4th argument - if two thread want to share single variable, then create global variable, and the pass this variable when creating thread.
sample program:
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
further details here