I'm trying to write a program which will spawn an arbitrary number of threads, similar to the code I have in Convert a process based program into a thread based version?, which uses processes to do what I'm trying to accomplish, so far I have the following code, I'm getting a lot of warnings currently, but I'm really wondering if I'm approaching what I'm trying to do somewhat correctly.
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void *runner(void *param); //the thread
int main(int argc, char *argv[]) {
pthread_t tid = gettid();
pthread_attr_t attr;
if (argc != 2){
fprintf(stderr, "Usage: a.out <integer value>\n");
return -1;
}
if (atoi(argv[1]) < 0) {
fprintf(stderr, "Argument %d must be non negative\n", atoi(argv[1]));
return -1;
}
printf("My thread identifier is: %d\n", tid);
// default attributes
pthread_attr_init(&attr);
// create the thread
pthread_create(&tid, &attr, runner, argv[1]);
// wait for the thread to exit
pthread_join(tid, NULL);
}
void *runner(void *param){
//int i, upper = atoi(param);
int i;
srand48(gettid());
int max = nrand()%100;
if (max > 0){
for (i=1; i<=max; i++){
printf("Child %d executes iteration\n", param, i);
}
}
pthread_exit(0);
}
Appreciate any guidance I can get with this!
If I understand your objective, you want to create the number of threads as the command line parameter indicates.
(remembering that any specific OS can only support a fixed number of threads, which varies depending on the OS, so I will not validate the magnitude that number here.)
the following proposed code:
cleanly compiles
performs the desired functionality
documents why each header file is included
checks for error indications returned from C library functions, like pthread_create()
and now the proposed code:
#include <stdio.h> // printf(), perror(), NULL
#include <pthread.h> // pthread_create(), pthread_join(), pthread_t
#include <stdlib.h> // exit(), EXIT_FAILURE, atof()
void *runner(void *param); //the thread
int main(int argc, char *argv[])
{
if (argc != 2)
{
fprintf(stderr, "Usage: %s <integer value>\n", argv[0]);
exit( EXIT_FAILURE );
}
// might want to use: `strtol()` rather than `atoi()`
// so can check for errors
size_t maxThreads = (size_t)atoi(argv[1]);
pthread_t tid[ maxThreads ];
for( size_t i=0; i<maxThreads; i++ )
{
tid[i] = 0;
}
// create the threads
for( size_t i=0; i<maxThreads; i++ )
{
if( pthread_create( &tid[i], NULL, runner, (void *)i ) )
{
perror( "pthread_create failed" );
}
}
// wait for each thread to exit
for( size_t i = 0; i<maxThreads; i++ )
{
// if thread was created, then wait for it to exit
if( tid[i] != 0 )
{
pthread_join( tid[i], NULL );
}
}
}
void *runner(void *arg)
{
size_t threadNum = (size_t)arg;
printf( "in thread: %zu\n", threadNum );
pthread_exit( NULL );
}
a run with no command line parameter results in: (where the executable is named: untitled
Usage: ./untitled <integer value>
a run with a command line parameter of 10 results in:
in thread: 0
in thread: 4
in thread: 2
in thread: 6
in thread: 1
in thread: 5
in thread: 7
in thread: 8
in thread: 9
in thread: 3
which makes it clear that threads are run in no particular order
1: I see no function called gettid()
pthread_t tid = gettid();
srand48(gettid());
2: You cannot print pthread_t as an integer, it's a structure
printf("My thread identifier is: %d\n", tid);
3: it's rand(), I have not seen nrand() before.
int max = nrand()%100;
Fix these and edit the question if required.
Related
I'm using Linux to learn semaphore, trnna test the function sem_init. The code seems simple but the error is unexpected, don't know why. Here's the code and the errors is below the code.
#include <stdio.h>
#include <pthread.h>
#include <semaphore.h>
#include<unistd.h>
#include <stdlib.h>
#define NITER 1000000
int cnt = 0;
sem_t mutex;
sem_init(&mutex,0,1);
void * Count(void * a)
{
int i, tmp;
for(i = 0; i < NITER; i++)
{
sem_wait(&mutex);
tmp = cnt; /* copy the global cnt locally */
tmp = tmp+1; /* increment the local copy */
cnt = tmp; /* store the local value into the global cnt */
sem_post(&mutex);
}
}
int main(int argc, char * argv[])
{
pthread_t tid1, tid2;
if(pthread_create(&tid1, NULL, Count, NULL))
{
printf("\n ERROR creating thread 1");
exit(1);
}
if(pthread_create(&tid2, NULL, Count, NULL))
{
printf("\n ERROR creating thread 2");
exit(1);
}
if(pthread_join(tid1, NULL)) /* wait for the thread 1 to finish */
{
printf("\n ERROR joining thread");
exit(1);
}
if(pthread_join(tid2, NULL)) /* wait for the thread 2 to finish */
{
printf("\n ERROR joining thread");
exit(1);
}
if (cnt < 2 * NITER)
printf("\n BOOM! cnt is [%d], should be %d\n", cnt, 2*NITER);
else
printf("\n OK! cnt is [%d]\n", cnt);
pthread_exit(NULL);
}
my english is bad, if anything is hard to understand please tell me and ill respond you as soon as possible!thx
You can declare variables outside the main and the other function which mean that the variable is global .
But to call the function sem_init(&mutex,0,1); you should do it from the main or from another function. In your case , you have to do it in the main.
After moving the sem_init inside the main it compile
nabil#DESKTOP-8ECTID4:~/stackoverflow$ gcc bad.c -o bad -lpthread
nabil#DESKTOP-8ECTID4:~/stackoverflow$
I want to modify the multithread program on the Linux operating system using this Pthread API.
#include <pthread.h>
#include <stdio.h>
int sum;
void *runner(void *param);
int main(int argc, char *argv[]) {
pthread_t tid
pthread_attr_t attr;
if (argc != 2) {
fprintf(stderr, "usage: a.out <integer value>\n");
return -1;
}
if (atoi(argv[1]) < 0) {
fprintf(stderr, "%d must be >=0\n", atoi(argv[1]));
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_join(tid, NULL);
printf("sum = %d\n", sum);
}
void *runner(void *param);
{
int i, upper = atoi(param);
sum = 0;
for (i = 1; i <= upper; i++)
sum += i;
pthread exit(0);
}
I want to change that program into a program that has 2 threads that work together to add a number. But i don't know how to change it, Thanks again for any help that can be offered. I am sorry,because I'm not good at explaining.
first there is 3 errors : the pthread tid declaration has no ";", then there is one at the end of your runner()* function declaration, and last but not least, a underscore is missing on the last line pthread_exit(0)
beware ahah
ok for vars :
pthread_t tid;
pthread_t tid2;
pthread_attr_t attr;
pthread_attr_t attr2;
and in the code after the ifs, add this :
pthread_attr_init(&attr);
pthread_attr_init(&attr2);
pthread_create(&tid, &attr, runner, argv[1]);
pthread_create(&tid2, &attr2, runner, argv[2]); // not sure for argv[2]?
not sure for argv[2], it depends if it's 2 different numbers?
pthread_join are no use, they are here only for pausing threads, i think that if you want them to work in parallel, you need to only do "pthread_create" and they should work in parallel (but was i saw on my CS class on parallel programming 3 years ago, it will never be "real real" parallel because only the OS can control this and you need to be some kind of a super root to be able to really control the threads
I mean
it won't be faster because it will not be real parallel prog
I'm not exactly sure what you want, but a really quick and dirty solution based on the existing code is below. I'm assuming you just want two thread to sum a single variable to the input.
An explanation of what's going on: I had to fix some minor syntax issues you have in your code, one big one being the semicolon at the end of the runner function definition. I added a mutex to define a critical section in the runner's for loop. It makes sure only 1 thread can update the sum. I'm assuming you want the sum to equal the input, so we just increment it by 1 and check before incrementing whether the value is still below. Like I said, it's quite quick and dirty, not really the ideal solution. To create two threads, we just call the thread create function twice in main.
See https://computing.llnl.gov/tutorials/pthreads/#Mutexes for more important about mutexes and the pthread library.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
int sum = 0; // set it once globally
pthread_mutex_t mtx = PTHREAD_MUTEX_INITIALIZER;
void *runner(void *param);
int main(int argc, char *argv[]) {
pthread_t tid1, tid2;
pthread_attr_t attr;
if (argc != 2) {
fprintf(stderr, "usage: a.out <integer value>\n");
return -1;
}
if (atoi(argv[1]) < 0) {
fprintf(stderr, "%d must be >=0\n", atoi(argv[1]));
return -1;
}
pthread_attr_init(&attr);
pthread_create(&tid1, &attr, runner, argv[1]);
pthread_create(&tid2, &attr, runner, argv[1]);
pthread_join(tid1, NULL);
pthread_join(tid2, NULL);
printf("sum = %d\n", sum);
}
void *runner(void *param) {
int i, upper = atoi(param);
// sum = 0;
int t = pthread_self();
for (i = 1; i <= upper; i++) {
pthread_mutex_lock(&mtx);
if (sum < upper) {
printf("%d incrementing\n", t);
sum += 1;
}
pthread_mutex_unlock(&mtx);
}
pthread_exit(0);
}
Compile with cc -o main main.c -pthread.
I'm working on an exercise (see bold text below) on semaphores and synchronization for my Operative System course. The text of the exercise is this:
Pthread semaphores and mutexes
The C program gen_binary_numbers.c receives on the command line an integer n, and uses recursion to generate and display all binary numbers of n bits.Transform the recursive program into a concurrent one, replacing the recursive procedure with the generation of an appropriate number of processes that display the binary numbers (in any order).
This is my code, actually:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
int num, r, c;
pthread_mutex_t mutex;
void *genBin(void *arg);
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stdout, "\nUSAGE: %s <n>\n\n", argv[0]);
exit(EXIT_FAILURE);
}
int i;
num = atoi(argv[1]);
c = num;
r = 2;
for (i=1; i<num; i++) {
r=r*2;
}
pthread_mutex_init(&mutex, NULL);
pthread_t* p;
p = malloc(r*sizeof(pthread_t));
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &i)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
pthread_exit(0);
}
void *genBin (void *arg) {
int x;
int i=0;
x = *((int*)arg);
pthread_mutex_lock(&mutex);
while (i<num) {
if(x!=0) {
fprintf(stdout, "%d", x%2);
}
else {
fprintf(stdout, "0");
}
i++;
x/=2;
}
fprintf(stdout, "\n");
pthread_mutex_unlock(&mutex);
pthread_exit(0);
}
I think that the code should return the right solution, but sometimes the output doesn't return the correct number.
Example of correct output:
./genBin 3
100
101
010
110
001
011
111
000
Example of wrong output (because of duplicates):
./genBin 3
110
110
110
001
011
111
111
000
I think that the problem is in the synchronization between the mutex and the printf.
Is there an alternative solution to avoid confusing results?
Your code contains a race condition. In main, you pass the address of your iteration variable, i, as the thread function's argument. Each new thread then races with the main thread to read the value of i (via the provided pointer) before the main thread increments it. One way you could address that problem would be to use a semaphore to make the main thread wait after creating each thread until that thread has dereferenced its argument.
Also, I don't think you need to use a mutex in genBin(). The only shared data it accesses is stdout, via fprintf(), and that function operates as if it locks an exclusive lock associated with the specified stream. Moreover, with the mutex you get essentially no actual concurrency because each thread holds the mutex locked for almost the complete duration of its execution.
The problem is in this part:
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &i)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
There's data race because you are passing the address of i to all threads. You could use an temp array to pass the individual number to each thread.
Thanks to everyone! You solved my problem. This is the corrected code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
int num, r, c;
pthread_mutex_t mutex;
void *genBin(void *arg);
int main (int argc, char **argv) {
if (argc != 2) {
fprintf(stdout, "\nUSAGE: %s <n>\n\n", argv[0]);
exit(EXIT_FAILURE);
}
int i;
int *temp;
num = atoi(argv[1]);
c = num;
r = 2;
for (i=1; i<num; i++) {
r=r*2;
}
temp = malloc(r*sizeof(int));
pthread_mutex_init(&mutex, NULL);
pthread_t* p;
p = malloc(r*sizeof(pthread_t));
for (i=0;i<r;i++) {
temp[i] = i;
}
for (i=0;i<r;i++) {
if (pthread_create(&p[i], NULL, genBin, &temp[i])) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
for (i=0;i<r;i++) {
if (pthread_join(p[i], NULL)) {
fprintf(stderr, "Error creating thread.\n");
exit(EXIT_FAILURE);
}
}
pthread_mutex_destroy(&mutex);
free(temp);
free(p);
pthread_exit(0);
}
void *genBin (void *arg) {
int x;
int i=0;
int *v;
v = malloc(num*sizeof(int));
x = *((int*)arg);
for (i=0; i<num; i++) {
v[i] = x%2;
x/=2;
}
pthread_mutex_lock(&mutex);
for (i=0; i<num; i++) {
fprintf(stdout, "%d", v[i]);
}
fprintf(stdout, "\n");
pthread_mutex_unlock(&mutex);
free(v);
pthread_exit(0);
}
Learning about pthreads, but I'm having trouble getting them created. Here is my output and the gdb information:
In main(), creating thread 1
ERROR: return code from pthread_create() is 22 for thread 1
In main(), creating thread 2
ERROR: return code from pthread_create() is 22 for thread 2
In main(), creating thread 3
ERROR: return code from pthread_create() is 22 for thread 3
In main(), creating thread 4
ERROR: return code from pthread_create() is 22 for thread 4
In main(), creating thread 5
ERROR: return code from pthread_create() is 22 for thread 5
Program received signal SIGSEGV, Segmentation fault. 0xb7fb4d8a in
pthread_join (threadid=76038327, thread_return=0x0)
at pthread_join.c:46 46 pthread_join.c: No such file or directory.
And here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#define SBUFSIZE 1025
char errorstr[SBUFSIZE];
FILE* inputfp[5];
void* f(void* inpFile) {
fprintf(stderr, "%s\n", (char*)inpFile);
return NULL;
}
int main (int argc, char* argv[]) {
int i;
/* Thread Variables */
pthread_attr_t attr;
pthread_t *th[argc-2]; //one thread for each input file
/* allocate memory for the threads */
for (i = 0; i < (argc-2); i++) {
th[i] = (pthread_t *) malloc(sizeof(pthread_t));
inputfp[i] = fopen(argv[i], "r");
if (!inputfp[i]) {
sprintf(errorstr, "Error Opening Input File: %s", argv[i]);
perror(errorstr);
}
}
/* Create one thread for each input file */
for (i = 1; i < (argc - 1); i++) {
fprintf (stderr, "In main(), creating thread %1d\n", i);
int rc = pthread_create (th[i], &attr, f, inputfp[i-1]);
if (rc) {
printf("ERROR: return code from pthread_create() is %d for thread %d\n",
rc, i);
}
}
/* wait for the threads to finish */
for (i = 1; i < (argc - 1); i++) {
pthread_join(*th[i], 0);
}
return EXIT_SUCCESS;
}
I'm missing something, but I don't know what. Can anyone help? Thank you!
EDIT: Here is how I changed the code per the suggestion from Joachim Pileborg. I'm still getting error 22 returning from pthread_create(), but the SIGSEGV error on pthread_join is no longer occurring.
Anyone have any suggestions about how I can get the pthread_create() to return 0 (indicating a successful thread creation)? Thanks again!
int main (int argc, char* argv[]) {
int i;
/* Thread Variables */
pthread_attr_t attr;
pthread_t *th[argc-2]; //one thread for each input file
/* allocate memory for the threads */
for (i = 0; i < (argc-2); i++) {
th[i] = (pthread_t *) malloc(sizeof(pthread_t));
printf("%s\n", argv[i+1]);
inputfp[i] = fopen(argv[i+1], "r");
if (!inputfp[i]) {
sprintf(errorstr, "Error Opening Input File: %s", argv[i]);
perror(errorstr);
}
}
/* Create one thread for each input file */
for (i = 0; i < (argc - 2); i++) {
fprintf (stderr, "In main(), creating thread %1d\n", i);
int rc = pthread_create (th[i], &attr, f, inputfp[i]);
if (rc) {
printf("ERROR: return code from pthread_create() is %d for thread %d\n",
rc, i);
}
}
/* wait for the threads to finish */
for (i = 0; i < (argc - 2); i++) {
pthread_join(*th[i], 0);
}
return EXIT_SUCCESS;
}
You have one loop where you loop from zero to argc - 3, and uses the correct indexes (zero to "size of array minus one".
Then you have two loops where you loop from one to argc - 2, and use indexes from one to "size of array".
You should use the same loop as the first one in all three places.
I was trying to implement a checkpointing scheme based on multithreaded fork using fork combined with setjmp/longjmp. I was hoping my solution would work but as expected it didn't. The code is shown below with an example usage for checkpoint/rollback.
The main idea is to allocate stacks for the threads myself, as done by using the function pthread_create_with_stack and then just use a fork from the main thread. The forked process (checkpoint) is suspended at the beginning and when awoken (rollbacking), the main thread of the forked process recreates the threads by calling pthread_create and use the same stacks as threads in original process. Also longjmp is done in the thread routine at the beginning, so as to jump to the same point in the code when process was forked as a checkpoint. Note that all setjmp calls are done inside function my_pthread_barrier_wait so that no thread has acquired a lock.
I think the problem here is setjmp/lonjmp. Will getcontext/savecontext/makecontext help here, or anything else? Can even setjmp/longjmp be used in such a way here that it works? Any solution will be greatly appreciated.
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <unistd.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/types.h>
#include <setjmp.h>
#define PERFORM_JMP
#define NUM_THREADS 4
void *stackAddr[NUM_THREADS];
pthread_t thread[NUM_THREADS];
jmp_buf buf[NUM_THREADS];
pthread_attr_t attr[NUM_THREADS];
pthread_barrier_t bar;
sem_t sem;
pid_t cp_pid;
int rollbacked;
int iter;
long thread_id[NUM_THREADS];
void *BusyWork(void *t);
void sig_handler(int signum)
{
printf( "signal_handler posting sem!\n" );
sem_post( &sem );
}
int pthread_create_with_stack( void *(*start_routine) (void *), int tid )
{
const size_t STACKSIZE = 0xC00000; //12582912
size_t i;
pid_t pid;
int rc;
printf( "tid = %d\n", tid );
pthread_attr_init( &attr[tid] );
stackAddr[tid] = malloc(STACKSIZE);
pthread_attr_setstack( &attr[tid], stackAddr[tid], STACKSIZE );
thread_id[tid] = tid;
rc = pthread_create( &thread[tid], &attr[tid], start_routine, (void*)&thread_id[tid] );
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
return rc;
}
pid_t checkpoint()
{
pid_t pid;
int t, rc;
switch (pid=fork())
{
case -1:
perror("fork");
break;
case 0: // child process starts
sem_wait( &sem );
rollbacked = 1;
printf( "case 0: rollbacked = 1, my pid is %d\n", getpid() );
for( t = 1; t < NUM_THREADS; t++ )
{
printf( "checkpoint: creating thread %d again\n", t );
rc = pthread_create( &thread[t], &attr[t], BusyWork, (void*)&thread_id[t] );
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
return 1; // child process ends
default: // parent process starts
return pid;
}
}
void restart_from_checkpoint( pid_t pid )
{
printf( "Restart_from_checkpoint, sending signal to %d!\n", pid );
kill( pid, SIGUSR1 );
exit( 0 );
}
void take_checkpoint_or_rollback( int sig_diff )
{
if ( cp_pid )
{
if ( sig_diff )
{
printf( "rollbacking\n" );
if ( !rollbacked )
restart_from_checkpoint( cp_pid );
}
else
{
kill( cp_pid, SIGKILL );
cp_pid = checkpoint();
printf( "%d: cp_pid = %d!\n", getpid(), cp_pid );
}
}
else
cp_pid = checkpoint();
}
void my_pthread_barrier_wait( int tid, pthread_barrier_t *pbar )
{
pthread_barrier_wait( pbar );
#ifdef PERFORM_JMP
if ( tid == 0 )
{
if ( !rollbacked )
{
take_checkpoint_or_rollback( ++iter == 4 );
}
}
if ( setjmp( buf[tid] ) != 0 ) {}
else {}
printf( "%d: %d is waiting at the second barrier!\n", getpid(), tid );
#endif
pthread_barrier_wait( pbar );
}
void *BusyWork(void *t)
{
volatile int i;
volatile long tid = *((long*)t);
volatile double result = 0.0;
printf( "thread %ld in BusyWork!\n", tid );
#ifdef PERFORM_JMP
if ( rollbacked )
{
printf( "hmm, thread %ld is now doing a longjmp, goodluck!\n", tid );
longjmp( buf[tid], 1 );
}
#endif
printf("Thread %ld starting...\n",tid);
for ( i = 0; i < 10; i++)
{
result += (tid+1) * i;
printf( "%d: tid %ld: result = %g\n", getpid(), tid, result );
my_pthread_barrier_wait(tid, &bar);
}
printf("Thread %ld done. Result = %g\n", tid, result);
//pthread_exit((void*) t);
}
int main (int argc, char *argv[])
{
int rc;
long t;
void *status;
/* Initialize and set thread detached attribute */
pthread_barrier_init(&bar, NULL, NUM_THREADS);
#ifdef PERFORM_JMP
signal(SIGUSR1, sig_handler);
sem_init( &sem, 0, 0 );
#endif
for( t = 1; t < NUM_THREADS; t++ )
{
printf( "Main: creating thread %ld\n", t );
rc = pthread_create_with_stack( BusyWork, t ); // This is the line 52
if (rc)
{
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
thread_id[0] = 0;
BusyWork( &thread_id[0] );
/* Free attribute and wait for the other threads */
for(t=1; t<NUM_THREADS; t++)
{
rc = pthread_join(thread[t], &status);
if (rc)
{
printf("ERROR; return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: completed join with thread %ld having a status"
"of %ld\n",t,(long)status);
}
printf("Main: program completed. Exiting.\n");
pthread_exit(NULL);
}
What you're trying to do is simply impossible. fork is fundamentally incompatible with synchronization. Even if you could recreate threads reliably in the child process, they would have new thread ids, and thus they would not be the owners of the locks they're supposed to own.
The only way to do checkpointing is with advanced operating system support for it. This would have to include separate pid namespaces, so that the checkpointed copy of the program would have the same pid, and all its threads would have the same thread ids. Even then, if it's performing communication with other processes or the outside world, it won't work. I believe there are some tools for doing this on Linux, but I'm not familiar with them, and at this point you're getting to level of hacks where it's appropriate to ask if there's a better way to achieve what you're trying to do.