1

I have an assigment in which at first i have to make the following process tree: here

I have succeeded in doing this, but after this I also have to create 5 threads in process P8 (which in another task have to be synchronized in a given way) and 6 threads in process P4. The main task at this point is to synchronize certain threads from P8 and P4 in this way: Thread 1 from P4 has to end before Thread 1 from P8, but Thread 4 from P4 can start only after Thread 1 from P8 ended (starting / ending a thread means that i have to print a message). I have tried doing the following and it made sense to me: This is the main program:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/wait.h>
#include "a2_helper.h"

int thread_numbers[35];
int started = 0;
int finished = 0;
int barr_count = 0;

sem_t *msem;
sem_t *sem_aux;
sem_t *sem_thd;
sem_t *sem_one;
sem_t *sem_two;

typedef struct thd_s
{
    int id;
    pthread_t thd;
    pthread_mutex_t *lock;
    pthread_cond_t *cond;
    int process_nr;
}THD;

void *thread_function_diff(void *args)
{
    THD *thd = (THD *)args;

    if (thd->process_nr == 8 && thd->id == 1)
    {
        info(BEGIN, thd->process_nr, thd->id);
        sem_wait(sem_one);
        info(END, thd->process_nr, thd->id);
        sem_post(sem_two);
    }
    else if (thd->process_nr == 4 && thd->id == 1)
    {
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
        sem_post(sem_one);
    }
    else if (thd->process_nr == 4 && thd->id == 4)
    {
        sem_wait(sem_two);
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
    }
    else
    {
        info(BEGIN, thd->process_nr, thd->id);
        info(END, thd->process_nr, thd->id);
    }

    pthread_exit(0);
}

void *thread_function_barr(void *args)
{
    THD *thd = (THD *)args;

    sem_wait(msem);
//
//    if (thd->id == 31 || thd->id == 32 || thd->id == 33 || thd->id == 34)
//    {
//        info(BEGIN, thd->process_nr, thd->id);
//        sem_post(sem_thd);
//        sem_wait(sem_aux);
//        info(END, thd->process_nr, thd->id);
//    }
//    else
//    {
//        if (thd->id == 13)
//        {
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            sem_wait(sem_thd);
//            info(BEGIN, thd->process_nr, thd->id);
//            info(END, thd->process_nr, thd->id);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//            sem_post(sem_aux);
//        }
//        else
//        {
            info(BEGIN, thd->process_nr, thd->id);
            info(END, thd->process_nr, thd->id);
//        }
//    }

    sem_post(msem);

    pthread_exit(0);
}

void *thread_function(void *args)
{
    THD *thd = (THD *)args;

    pthread_mutex_lock(thd->lock);
    while (started == 0 && thd->id == 3)
    {
        pthread_cond_wait(thd->cond, thd->lock);
    }
    info(BEGIN, thd->process_nr, thd->id);
    pthread_mutex_unlock(thd->lock);

    info(END, thd->process_nr, thd->id);
    pthread_mutex_lock(thd->lock);
    if (thd->id == 3)
    {
        finished = 1;
        pthread_cond_signal(thd->cond);
    }
    pthread_mutex_unlock(thd->lock);

    pthread_exit(0);
}

void *thread_function5(void *args)
{
    THD *thd = (THD *)args;

    started = 1;
    info(BEGIN, thd->process_nr, thd->id);
    pthread_cond_signal(thd->cond);

    pthread_mutex_lock(thd->lock);
    while (finished == 0)
    {
        pthread_cond_wait(thd->cond, thd->lock);
    }
    info(END, thd->process_nr, thd->id);
    pthread_mutex_unlock(thd->lock);

    pthread_exit(0);
}

int main()
{
    init();
    info(BEGIN, 1, 0);

    sem_one = sem_open("sem_one", O_CREAT, 0644, 0);
    sem_two = sem_open("sem_two", O_CREAT, 0644, 0);

    pid_t pid2 = -1, pid3 = -1, pid8 = -1;

    pid8 = fork();
    if (pid8 == 0)
    {
        info(BEGIN, 8, 0);

        THD thds[5];
        pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
        pthread_cond_t cond = PTHREAD_COND_INITIALIZER;

        for (int i = 4; i >= 0; i--)
        {
            thds[i].id = i + 1;
            thds[i].process_nr = 8;
            thds[i].lock = &lock;
            thds[i].cond = &cond;

            if (thds[i].id == 5)
            {
                pthread_create(&(thds[i].thd), NULL, thread_function5, &thds[i]);
            }
            else if (thds[i].id == 1)
            {
                pthread_create(&(thds[i].thd), NULL, thread_function_diff, &thds[i]);
            }
            else
            {
                pthread_create(&(thds[i].thd), NULL, thread_function, &thds[i]);
            }
        }

        for (int i = 4; i >= 0; i--)
        {
            pthread_join(thds[i].thd, NULL);
        }

        pthread_cond_destroy(&cond);
        pthread_mutex_destroy(&lock);

        info(END, 8, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    pid2 = fork();
    if (pid2 == 0)
    {
        info(BEGIN, 2, 0);

        pid_t pid4 = -1, pid5 = -1, pid9 = -1;

        pid4 = fork();
        if (pid4 == 0)
        {
            info(BEGIN, 4, 0);

            THD thds[6];

            for (int i = 5; i >= 0; i--)
            {
                thds[i].id = i + 1;
                thds[i].process_nr = 4;
                thds[i].lock = NULL;
                thds[i].cond = NULL;
                pthread_create(&(thds[i].thd), NULL, thread_function_diff, &thds[i]);
            }

            for (int i = 5; i >= 0; i--)
            {
                pthread_join(thds[i].thd, NULL);
            }

            info(END, 4, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        pid5 = fork();
        if (pid5 == 0)
        {
            info(BEGIN, 5, 0);

            THD thds[36];
            sem_unlink("thdsemaphore");
            sem_unlink("auxsemaphore");
            sem_unlink("barriersemaphore");

            msem = sem_open("barriersemaphore", O_CREAT, 0644, 5);
            sem_aux = sem_open("auxsemaphore", O_CREAT, 0644, 0);
            sem_thd = sem_open("thdsemaphore", O_CREAT, 0644, 0);
            pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;

            for (int i = 35; i >= 0; i--)
            {
                if (i + 1 == 13)
                {
                    thread_numbers[i] = 36;
                }
                else
                {
                    thread_numbers[i] = i + 1;
                }

                thds[i].id = i + 1;
                thds[i].process_nr = 5;
                thds[i].lock = &lock;
                thds[i].cond = NULL;
                pthread_create(&(thds[i].thd), NULL, thread_function_barr, &thds[i]);
            }

            for (int i = 35; i >= 0; i--)
            {
                pthread_join(thds[i].thd, NULL);
            }

            pid_t pid6 = -1;
            pid6 = fork();
            if (pid6 == 0)
            {
                info(BEGIN, 6, 0);
                info(END, 6, 0);
                exit(0);
            }
            else
            {
                wait(NULL);
            }

            pthread_mutex_destroy(&lock);

            sem_close(sem_thd);
            sem_unlink("thdsemaphore");
            sem_close(sem_aux);
            sem_unlink("auxsemaphore");
            sem_close(msem);
            sem_unlink("barriersemaphore");

            info(END, 5, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        pid9 = fork();
        if (pid9 == 0)
        {
            info(BEGIN, 9, 0);

            info(END, 9, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        info(END, 2, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    pid3 = fork();
    if (pid3 == 0)
    {
        info(BEGIN, 3, 0);

        pid_t pid7 = -1;

        pid7 = fork();
        if (pid7 == 0)
        {
            info(BEGIN, 7, 0);

            info(END, 7, 0);
            exit(0);
        }
        else
        {
            wait(NULL);
        }

        info(END, 3, 0);
        exit(0);
    }
    else
    {
        wait(NULL);
    }

    sem_close(sem_one);
    sem_close(sem_two);
    sem_unlink("sem_one");
    sem_unlink("sem_two");

    info(END, 1, 0);
    return 0;
}

The problem is that if I try doing it this way, Thread 1 from P8 will wait endlessly to get permission on the semaphore, but that permision is given by Thread 1 from P4, which never gets the chance to run, because in the main function, I have to make sure the main thread from any process should not end before any other thread and all the processes should wait for their child processes to end.

This is a2_helper.h:

#ifndef __A2_HELPER_H__
#define __A2_HELPER_H__

#define BEGIN 1
#define END 2

void init();
int info(int action, int processNr, int threadNr);

#endif

This is a2_helper.c:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h> 
#include <sys/socket.h>
#include <netinet/in.h>
#include <semaphore.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/prctl.h>
#include <signal.h>

#include "a2_helper.h"

#define SEM_NAME "A2_HELPER_SEM_17871"
#define SERVER_PORT 1988

#define XSTR(s) STR(s)
#define STR(s) #s
#define CHECK(c) if(!(c)){perror("info function failed at line " XSTR(__LINE__)); break;}

int initialized = 0;

int info(int action, int processNr, int threadNr){
    int msg[6];
    int sleepTime = 0;
    int sockfd = -1;
    struct sockaddr_in serv_addr;
    sem_t *sem = SEM_FAILED;
    int err = -1;

    if(initialized == 0){
        printf("init() function not called\n");
        return -1;
    }
    do{
        CHECK((sem = sem_open(SEM_NAME, 0)) != SEM_FAILED);

        //prepare the message
        msg[0] = action;
        msg[1] = processNr;
        msg[2] = threadNr;
        msg[3] = getpid();
        msg[4] = getppid();
        msg[5] = pthread_self();

        CHECK((sockfd = socket(AF_INET, SOCK_STREAM, 0)) >= 0);

        memset(&serv_addr, 0, sizeof(serv_addr));
        serv_addr.sin_family = AF_INET;
        serv_addr.sin_port = htons(SERVER_PORT);

        CHECK(sem_wait(sem) == 0);
        err = -2;
        if(connect(sockfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) >= 0){
            CHECK(write(sockfd, msg, sizeof(msg)) == sizeof(msg));
            CHECK(read(sockfd, &sleepTime, sizeof(sleepTime)) == sizeof(sleepTime));
            printf("[T] ");
        }else{
            printf("[ ] ");
        }
        printf("%s P%d T%d pid=%d ppid=%d tid=%d\n", msg[0]==BEGIN?"BEGIN":" END ", msg[1], msg[2], msg[3], msg[4], msg[5]);
        CHECK(sem_post(sem) == 0);
        err = -1;
        usleep(sleepTime);
        err = 0;
    }while(0);
    if(sockfd >= 0){
        close(sockfd);
    }
    if(err==-2){
        sem_post(sem);
    }
    return err;
}

void atfork_prepare(){
    sem_t *sem = SEM_FAILED;
    do{
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        CHECK(sem_wait(sem) == 0);
    }while(0);
}

void atfork_parent(){
    sem_t *sem = SEM_FAILED;
    do{
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        CHECK(sem_post(sem) == 0);
    }while(0);
}

void atfork_child(){
    prctl(PR_SET_PDEATHSIG, SIGHUP);
}

void init(){
    sem_t *sem = SEM_FAILED;
    if(initialized != 0){
        printf("init() function already called\n");
        return;
    }
    do{
        pthread_atfork(atfork_prepare, atfork_parent, atfork_child);
        sem_unlink(SEM_NAME);
        CHECK((sem = sem_open(SEM_NAME, O_CREAT, 0644, 1)) != SEM_FAILED);
        initialized = 1;
    }while(0);
}

a2_helper.c and a2_helper.h were already implemented and I only have to use them.

8
  • 1
    Is it just me, or are assignments getting sillier? In the real world, requirements like this don't exist. Why are educators wasting student effort, and their own, on carp like this? Manuel: can you still pass without answering.this, some alternative? If so, do it, since this exercise is of zip usefulness:( Commented May 11, 2019 at 6:26
  • I could pass without doing it, and i also feel that this gets the assignment rather difficult and i don`t know what to say about it, but by struggling to find a solution to this problem i got really curious about the solution of this. Commented May 11, 2019 at 6:36
  • stackoverflow.com is NOT a free code design site. Please post a minimal reproducible example so we can reproduce the problem and therefore help you debug it Commented May 11, 2019 at 7:01
  • the function: fork() has three kinds of returned values The code should be checking for all three conditions Commented May 11, 2019 at 7:02
  • 1
    should always check for errors from calls to C library functions. Otherwise, when something goes wrong, you will only see a crash (or other incorrect behavior) and have no idea as to why the incorrect behavior occurred Commented May 11, 2019 at 7:04

1 Answer 1

1

I think the problem is your wait()’s. Main forks pid8, then waits for it to complete before moving on to fork pid2 ( which in turn forks pid4). Pid2 cannot run until pid8 has completed; so their threads cannot co-ordinate.

Instead of waiting after each fork, you should fire off (from main) all three, then wait three times. In pid2, you should do the same thing.

I am not sure what the expected output is, but when I changed it, it went from printing 11 lines and hanging to generating this and exitting:

[ ] BEGIN P1 T0 pid=17861 ppid=17097 tid=1351051072
[ ] BEGIN P2 T0 pid=17863 ppid=17861 tid=1351051072
[ ] BEGIN P8 T0 pid=17862 ppid=17861 tid=1351051072
[ ] BEGIN P3 T0 pid=17864 ppid=17861 tid=1351051072
[ ] BEGIN P8 T1 pid=17862 ppid=17861 tid=1308952320
[ ] BEGIN P8 T5 pid=17862 ppid=17861 tid=1342523136
[ ] BEGIN P8 T4 pid=17862 ppid=17861 tid=1334130432
[ ] BEGIN P4 T0 pid=17867 ppid=17863 tid=1351051072
[ ] BEGIN P4 T6 pid=17867 ppid=17863 tid=1342523136
[ ] BEGIN P7 T0 pid=17871 ppid=17864 tid=1351051072
[ ] BEGIN P8 T2 pid=17862 ppid=17861 tid=1317345024
[ ] BEGIN P4 T3 pid=17867 ppid=17863 tid=1317345024
[ ] BEGIN P9 T0 pid=17879 ppid=17863 tid=1351051072
[ ] BEGIN P4 T5 pid=17867 ppid=17863 tid=1334130432
[ ] BEGIN P4 T1 pid=17867 ppid=17863 tid=1300559616
[ ]  END  P4 T5 pid=17867 ppid=17863 tid=1334130432
[ ]  END  P4 T6 pid=17867 ppid=17863 tid=1342523136
[ ] BEGIN P4 T2 pid=17867 ppid=17863 tid=1308952320
[ ]  END  P7 T0 pid=17871 ppid=17864 tid=1351051072
[ ]  END  P8 T2 pid=17862 ppid=17861 tid=1317345024
[ ] BEGIN P8 T3 pid=17862 ppid=17861 tid=1325737728
[ ] BEGIN P5 T0 pid=17873 ppid=17863 tid=1351051072
[ ]  END  P4 T3 pid=17867 ppid=17863 tid=1317345024
[ ]  END  P9 T0 pid=17879 ppid=17863 tid=1351051072
[ ]  END  P4 T1 pid=17867 ppid=17863 tid=1300559616
[ ]  END  P8 T1 pid=17862 ppid=17861 tid=1308952320
[ ]  END  P4 T2 pid=17867 ppid=17863 tid=1308952320
[ ]  END  P8 T3 pid=17862 ppid=17861 tid=1325737728
[ ]  END  P3 T0 pid=17864 ppid=17861 tid=1351051072
[ ] BEGIN P5 T34 pid=17873 ppid=17863 tid=1325737728
[ ] BEGIN P5 T33 pid=17873 ppid=17863 tid=1317345024
[ ] BEGIN P5 T31 pid=17873 ppid=17863 tid=1300559616
[ ] BEGIN P4 T4 pid=17867 ppid=17863 tid=1325737728
[ ] BEGIN P5 T36 pid=17873 ppid=17863 tid=1342523136
[ ] BEGIN P5 T30 pid=17873 ppid=17863 tid=1292166912
[ ]  END  P5 T33 pid=17873 ppid=17863 tid=1317345024
[ ]  END  P5 T30 pid=17873 ppid=17863 tid=1292166912
[ ] BEGIN P5 T35 pid=17873 ppid=17863 tid=1334130432
[ ] BEGIN P5 T2 pid=17873 ppid=17863 tid=1057171200
[ ]  END  P5 T36 pid=17873 ppid=17863 tid=1342523136
[ ]  END  P5 T34 pid=17873 ppid=17863 tid=1325737728
[ ]  END  P8 T5 pid=17862 ppid=17861 tid=1342523136
[ ]  END  P8 T4 pid=17862 ppid=17861 tid=1334130432
[ ]  END  P4 T4 pid=17867 ppid=17863 tid=1325737728
[ ]  END  P5 T31 pid=17873 ppid=17863 tid=1300559616
[ ]  END  P5 T35 pid=17873 ppid=17863 tid=1334130432
[ ]  END  P4 T0 pid=17867 ppid=17863 tid=1351051072
[ ] BEGIN P5 T26 pid=17873 ppid=17863 tid=1258596096
[ ] BEGIN P5 T28 pid=17873 ppid=17863 tid=1275381504
[ ] BEGIN P5 T29 pid=17873 ppid=17863 tid=1283774208
[ ]  END  P5 T28 pid=17873 ppid=17863 tid=1275381504
[ ]  END  P5 T2 pid=17873 ppid=17863 tid=1057171200
[ ]  END  P8 T0 pid=17862 ppid=17861 tid=1351051072
[ ]  END  P5 T26 pid=17873 ppid=17863 tid=1258596096
[ ] BEGIN P5 T27 pid=17873 ppid=17863 tid=1266988800
[ ]  END  P5 T29 pid=17873 ppid=17863 tid=1283774208
[ ] BEGIN P5 T25 pid=17873 ppid=17863 tid=1250203392
[ ] BEGIN P5 T24 pid=17873 ppid=17863 tid=1241810688
[ ]  END  P5 T27 pid=17873 ppid=17863 tid=1266988800
[ ]  END  P5 T25 pid=17873 ppid=17863 tid=1250203392
[ ] BEGIN P5 T23 pid=17873 ppid=17863 tid=1233417984
[ ]  END  P5 T24 pid=17873 ppid=17863 tid=1241810688
[ ] BEGIN P5 T22 pid=17873 ppid=17863 tid=1225025280
[ ] BEGIN P5 T17 pid=17873 ppid=17863 tid=1183061760
[ ]  END  P5 T22 pid=17873 ppid=17863 tid=1225025280
[ ]  END  P5 T23 pid=17873 ppid=17863 tid=1233417984
[ ] BEGIN P5 T14 pid=17873 ppid=17863 tid=1157883648
[ ]  END  P5 T17 pid=17873 ppid=17863 tid=1183061760
[ ] BEGIN P5 T18 pid=17873 ppid=17863 tid=1191454464
[ ] BEGIN P5 T13 pid=17873 ppid=17863 tid=1149490944
[ ] BEGIN P5 T15 pid=17873 ppid=17863 tid=1166276352
[ ]  END  P5 T14 pid=17873 ppid=17863 tid=1157883648
[ ]  END  P5 T18 pid=17873 ppid=17863 tid=1191454464
[ ] BEGIN P5 T11 pid=17873 ppid=17863 tid=1132705536
[ ]  END  P5 T13 pid=17873 ppid=17863 tid=1149490944
[ ]  END  P5 T15 pid=17873 ppid=17863 tid=1166276352
[ ] BEGIN P5 T10 pid=17873 ppid=17863 tid=1124312832
[ ] BEGIN P5 T5 pid=17873 ppid=17863 tid=1082349312
[ ]  END  P5 T11 pid=17873 ppid=17863 tid=1132705536
[ ] BEGIN P5 T7 pid=17873 ppid=17863 tid=1099134720
[ ] BEGIN P5 T4 pid=17873 ppid=17863 tid=1073956608
[ ]  END  P5 T5 pid=17873 ppid=17863 tid=1082349312
[ ]  END  P5 T7 pid=17873 ppid=17863 tid=1099134720
[ ]  END  P5 T4 pid=17873 ppid=17863 tid=1073956608
[ ]  END  P5 T10 pid=17873 ppid=17863 tid=1124312832
[ ] BEGIN P5 T6 pid=17873 ppid=17863 tid=1090742016
[ ] BEGIN P5 T3 pid=17873 ppid=17863 tid=1065563904
[ ] BEGIN P5 T8 pid=17873 ppid=17863 tid=1107527424
[ ] BEGIN P5 T9 pid=17873 ppid=17863 tid=1115920128
[ ] BEGIN P5 T12 pid=17873 ppid=17863 tid=1141098240
[ ]  END  P5 T6 pid=17873 ppid=17863 tid=1090742016
[ ]  END  P5 T12 pid=17873 ppid=17863 tid=1141098240
[ ]  END  P5 T8 pid=17873 ppid=17863 tid=1107527424
[ ]  END  P5 T9 pid=17873 ppid=17863 tid=1115920128
[ ] BEGIN P5 T20 pid=17873 ppid=17863 tid=1208239872
[ ] BEGIN P5 T21 pid=17873 ppid=17863 tid=1216632576
[ ] BEGIN P5 T19 pid=17873 ppid=17863 tid=1199847168
[ ] BEGIN P5 T16 pid=17873 ppid=17863 tid=1174669056
[ ]  END  P5 T3 pid=17873 ppid=17863 tid=1065563904
[ ]  END  P5 T20 pid=17873 ppid=17863 tid=1208239872
[ ]  END  P5 T21 pid=17873 ppid=17863 tid=1216632576
[ ]  END  P5 T19 pid=17873 ppid=17863 tid=1199847168
[ ]  END  P5 T16 pid=17873 ppid=17863 tid=1174669056
[ ] BEGIN P5 T32 pid=17873 ppid=17863 tid=1308952320
[ ] BEGIN P5 T1 pid=17873 ppid=17863 tid=1048778496
[ ]  END  P5 T1 pid=17873 ppid=17863 tid=1048778496
[ ]  END  P5 T32 pid=17873 ppid=17863 tid=1308952320
[ ] BEGIN P6 T0 pid=17916 ppid=17873 tid=1351051072
[ ]  END  P6 T0 pid=17916 ppid=17873 tid=1351051072
[ ]  END  P5 T0 pid=17873 ppid=17863 tid=1351051072
[ ]  END  P2 T0 pid=17863 ppid=17861 tid=1351051072
[ ]  END  P1 T0 pid=17861 ppid=17097 tid=1351051072
Sign up to request clarification or add additional context in comments.

3 Comments

You are saying that I should eliminate the part which contains: else { wait(NULL); } for P2, P3 and P8 and try to call wait(NULL) three times?
yes, call wait three times after starting all the sub processes, so just before closing and unlinking the semaphores in main, or issuing the info(END... in pid2.
It seems that this was the solution, i suppose what it was doing before was waiting for each process to finish before proceeding to the next one and in this case it wouldn`t have been any parallelism.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.