I have this program in C:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OUTPUTNAME "write.out"
#define OUTPUTNAME1 "fprint.out"
void *syscall_writer_function();
void *stdlibrary_writer_function();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
main()
{
int rc1, rc2;
pthread_t thread1, thread2;
/* Create independent threads each of which will execute functions */
if( (rc1=pthread_create( &thread1, NULL, &stdlibrary_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &thread2, NULL, &syscall_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc2);
}
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *syscall_writer_function()
{
long i;
int fd;
if ((fd=open(OUTPUTNAME,O_WRONLY|O_CREAT,0644)) < 0){
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME);
exit(1);
}
for (i=0; i<50000; i++) { /* write 50,000 Ys with write */
if (write(fd,"Y",1) < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
pthread_mutex_lock( &mutex1 );
counter++;
printf("Syscall finished\n");
printf("Counter value: %d\n",counter);
close(fd);
exit(0);
pthread_mutex_unlock( &mutex1 );
}
void *stdlibrary_writer_function()
{
long i;
FILE *fp;
if ((fp=fopen(OUTPUTNAME1,"w")) == NULL) {
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME1);
exit(1);
}
for (i=0; i<400000; i++) { /* write 400,000 Xs with fprintf */
if (fprintf(fp,"X") < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
pthread_mutex_lock( &mutex2 );
counter++;
printf("Stdlibrary finished\n");
printf("Counter value: %d\n",counter);
fclose(fp);
exit(0);
pthread_mutex_unlock( &mutex2 );
}
It should give output from both the threads like:
Syscall finished
Counter value: 1
Stdlibrary finished
Counter value: 2
or vice versa with stdlibrary first and syscall second.
But, it only gives output like the following:
Syscall finished
Counter value: 1
Why is this happening? What is wrong?
Related
I am trying to make race condition and fix it with mutex lock. My code is working correct which is no race condition. Should not it make race condition?
#define MAX_RESOURCES 10
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void count);
void increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
int main () {
int decrease = 8;
int increase = 3;
pthread_create(&thread1, NULL, decrease_count, (void*) &decrease);
pthread_create(&thread2, NULL, increase_count, (void*) &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d",available_resources);
return 0;
}
void* decrease_count(void *count){
available_resources -= *((int *)count);
return NULL;
}
void* increase_count(void *count){
if(available_resources + *((int *)count) <= MAX_RESOURCES) {
available_resources += *((int *)count);
return 0;
}
return NULL;
}
Well, here, you are declaring in your thread function that you are going to be passed a reference to the increment/decrement value, so you can control how many counts each thread does when it runs.
The idea is to create a mutex in main, and use it in both threads to lock the resource, before doing the increment/decrement.
#define MAX_RESOURCES 10
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
int available_resources = 10;
void* decrease_count(void *count);
void* increase_count(void *count);
pthread_t thread1;
pthread_t thread2;
pthread_mutex_t the_mutex;
int main () {
int decrease = 8;
int increase = 3;
/* create the mutex before any of the threads has access to it */
int res = pthread_mutex_init(&the_mutex, NULL);
if (res < 0) {
fprintf(stderr, "pthread_create_mutex: %s\n",
strerror(errno));
}
pthread_create(&thread1, NULL, decrease_count, &decrease);
pthread_create(&thread2, NULL, increase_count, &increase);
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
printf("amount of resource: %d\n",available_resources);
return 0;
}
void* decrease_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
available_resources -= count;
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
return NULL;
}
void* increase_count(void *_count){
int count = *(int *)_count;
int res = pthread_mutex_lock(&the_mutex);
int overflow = 0;
if (res < 0) {
fprintf(stderr,
"%s: mutex lock: %s\n",
__func__,
strerror(errno));
}
if(available_resources + count <= MAX_RESOURCES) {
overflow = 1;
available_resources += count;
}
res = pthread_mutex_unlock(&the_mutex);
if (res < 0) {
fprintf(stderr, "%s: mutex unlock: %s\n",
__func__,
strerror(errno));
}
if (overflow) {
printf("got over the top(%d resources)\n",
MAX_RESOURCES);
}
return NULL;
}
I have this multithreaded program with two threads and I want to convert it to a multiprocess program so that the two thread become two process and it tells which process finishes first.
Here is the mutlithreaded program:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OUTPUTNAME "write.out"
#define OUTPUTNAME1 "fprint.out"
void *syscall_writer_function();
void *stdlibrary_writer_function();
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_mutex_t mutex2 = PTHREAD_MUTEX_INITIALIZER;
int counter = 0;
main()
{
int rc1, rc2;
pthread_t thread1, thread2;
/* Create independent threads each of which will execute functions */
if( (rc1=pthread_create( &thread1, NULL, &syscall_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc1);
}
if( (rc2=pthread_create( &thread2, NULL, &stdlibrary_writer_function, NULL)) )
{
printf("Thread creation failed: %d\n", rc2);
}
pthread_join( thread1, NULL);
pthread_join( thread2, NULL);
exit(EXIT_SUCCESS);
}
void *syscall_writer_function()
{
long i;
int fd;
if ((fd=open(OUTPUTNAME,O_WRONLY|O_CREAT,0644)) < 0){
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME);
exit(1);
}
for (i=0; i<50000; i++) { /* write 50,000 Ys with write */
if (write(fd,"Y",1) < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
pthread_mutex_lock( &mutex2 );
counter++;
printf("Syscall finished\n");
printf("Counter value: %d\n",counter);
close(fd);
pthread_mutex_unlock( &mutex2 );
}
void *stdlibrary_writer_function()
{
long i;
FILE *fp;
if ((fp=fopen(OUTPUTNAME1,"w")) == NULL) {
fprintf(stderr,"Can't open %s. Bye.\n",OUTPUTNAME1);
exit(1);
}
for (i=0; i<400000; i++) { /* write 400,000 Xs with fprintf */
if (fprintf(fp,"X") < 1) {
fprintf(stderr,"Can't write. Bye\n");
exit(1);
}
}
counter++;
printf("Stdlibrary finished\n");
printf("Counter value: %d\n",counter);
fclose(fp);
}
How to convert it to a multiprocess program in C?
I want to create two thread which output interleave like below
Thread1:1=>Ping!
Thread2:2=>Pong!
Thread1:3=>Ping!
Thread1:4=>Ping!
Thread2:5=>Pong!
Thread2:6=>Pong!
Thread1:7=>Ping!
Thread2:8=>Pong!
Thread1:9=>Ping!
..........
until 50
and my code is below
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i){
//create thread
res1 = pthread_create(&thread1, NULL, increment1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread1, NULL);
res2 = pthread_create(&thread2, NULL, increment2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join( thread2, NULL);
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread1:%d\nPing!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
void* increment2(void* arg) {
sem_wait(&sem);
count ++;
printf("Thread2:%d\nPong!\n",count);
fsync(fileno(stdout));
sem_post(&sem);
}
But I think that what I do isn't using two thread in parallel and is wrong, what I use is sequential alternative executing two thread and it isn't not in parallel.(By using pthread_join, thread2 will execute after thread1 finish).
I try to using semaphore it seem that it cannot assure the thread execution order.
What I want to ask is
1.how to using semaphore to assure the two thread order?
2.how to pause the thread and resume it? I think that I do is create new two pthread in a loop cycle.
Thank in advance.
Add a second semaphore and initialize it to zero so that thread1 is forced to first. Then increment1 and increment2 keep signally that it is the other threads turn to go. You had some minor hangups with where joined things that you can figure out.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
void* increment1(void* arg);
void* increment2(void* arg);
int count = 0;
sem_t sem1, sem2;
int main()
{
pthread_t thread[2];
int res = 0;
int number = 0;
int i = 0;
if (sem_init(&sem1, 0, 1) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem2, 0, 0) == -1)
{
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < 25; ++i)
{
res = pthread_create(&thread[0], NULL, increment1, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
res = pthread_create(&thread[1], NULL, increment2, NULL);
if (res != 0)
{
printf("Thread creation failed!!\n");
exit(EXIT_FAILURE);
}
for (int j = 0; j < 2; ++j)
{
pthread_join(thread[j], NULL);
}
}
exit(EXIT_SUCCESS);
}
void* increment1(void* arg)
{
sem_wait(&sem1);
count ++;
printf("Thread1:%d Ping!\n", count);
fsync(fileno(stdout));
sem_post(&sem2);
}
void* increment2(void* arg)
{
sem_wait(&sem2);
count ++;
printf("Thread2:%d Pong!\n", count);
fsync(fileno(stdout));
sem_post(&sem1);
}
Thank for you guys, I have modified it and it seems fine.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
int count = 0;
void* increment_1(void* arg);
void* increment_2(void* arg);
sem_t sem_1, sem_2;
sem_t c_sem;
int main() {
//variable initialize
pthread_t thread1, thread2;
int res1 = 0, res2 = 0;
int number = 0;
int i = 0;
//create semaphore
if (sem_init(&c_sem, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_1, 0, 1) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
if (sem_init(&sem_2, 0, 0) == -1){
printf("Semaphore creation failed!!\n");
exit(EXIT_FAILURE);
}
//create thread
res1 = pthread_create(&thread1, NULL, increment_1, NULL);
if (res1 != 0) {
printf("Thread1 creation failed!!\n");
exit(EXIT_FAILURE);
}
res2 = pthread_create(&thread2, NULL, increment_2, NULL);
if (res2 != 0) {
printf("Thread2 creation failed!!\n");
exit(EXIT_FAILURE);
}
//wait thread synchronization
pthread_join(thread1, NULL);
pthread_join(thread2, NULL);
exit(EXIT_SUCCESS);
}
void* increment_1(void* arg) {
while(1){
sem_wait(&sem_1);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_2);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread1:%d->Ping!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_2);
}
}
void* increment_2(void* arg) {
while(1){
sem_wait(&sem_2);
sem_wait(&c_sem);
if(count == 50){
sem_post(&c_sem);
sem_post(&sem_1);
exit(EXIT_SUCCESS);
}
count ++;
printf("Thread2:%d->Pong!\n",count);
fsync(fileno(stdout));
sem_post(&c_sem);
sem_post(&sem_1);
}
}
I am trying to use pthread mutex variables and barrier to synchronize the output of my program, but it is not working the way I want it to. Each thread is seeing its final value every 20 values (coming from the for loop) which is alright but I'm trying to make them all get to the same final value (if using 5 threads, all of them should see 100 as final value, with 4 threads, 80, etc)
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
int SharedVariable =0;
void *SimpleThread(void *args)
{
int num,val,rc;
int which =(int)args;
rc = pthread_mutex_lock(&mutex1);
for(num=0; num<20; num++){
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
//pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
//pthread_mutex_lock(&mutex1);
SharedVariable = val+1;
pthread_mutex_unlock(&mutex1);
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
//pthread_mutex_destroy(&mutex1);
//pthread_exit((void*) 0);
//pthread_mutex_unlock(&mutex1);
}
int main (int argc, char *argv[])
{
if(atoi(argv[1]) > 0){
int num_threads = atoi(argv[1]);
//pthread_mutex_init(&mutex1, NULL);
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_mutex_lock(&mutex1);
for(t=0; t< num_threads; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
//pthread_join(thread1);
}
rc= pthread_mutex_unlock(&mutex1);
}
else{
printf("ERROR: The parameter should be a valid positive number.");
exit(-1);
}
pthread_mutex_destroy(&mutex1);
pthread_exit(NULL);
}
Any suggestions or help is greatly appreciated!
Thanks in advanced!
You need to use a barrier (pthread_barrier_wait()) before checking for the final value - this ensures that no thread will proceed until all threads have reached the barrier.
In addition, you should be calling pthread_join() to wait for the threads to finish, and you only need to hold the mutex around the increment:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
pthread_mutex_t mutex1 = PTHREAD_MUTEX_INITIALIZER;
pthread_barrier_t barrier1;
int SharedVariable = 0;
void *SimpleThread(void *args)
{
int num,val;
int which = (int)args;
for(num = 0; num < 20; num++) {
#ifdef PTHREAD_SYNC
if(random() > RAND_MAX / 2)
usleep(10);
#endif
pthread_mutex_lock(&mutex1);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val + 1;
pthread_mutex_unlock(&mutex1);
}
pthread_barrier_wait(&barrier1);
val = SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
return 0;
}
int main (int argc, char *argv[])
{
int num_threads = argc > 1 ? atoi(argv[1]) : 0;
if (num_threads > 0) {
pthread_t threads[num_threads];
int rc;
long t;
rc = pthread_barrier_init(&barrier1, NULL, num_threads);
if (rc) {
fprintf(stderr, "pthread_barrier_init: %s\n", strerror(rc));
exit(1);
}
for (t = 0; t < num_threads; t++) {
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < num_threads; t++) {
pthread_join(threads[t], NULL);
}
}
else {
printf("ERROR: The parameter should be a valid positive number.\n");
exit(-1);
}
return 0;
}
Try to move the pthread_mutext_unlock(&mutext1) out of the for loop in your SimpleThread. You lock once and unlock mutiple(20) times in your original code.
Alternatively, you could move pthread_mutex_lock(&mutext1) into the for loop, just before you read and modify your SharedVariable. In this case, each thread's add-by-one operation may not consecutive but each thread will get the correct final value.
And before you read the final value of the SharedVariable, use a barrier to wait all the threads finish their job.
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.