Task 2: solution by Ville. ========================== /* Compile, for example: gcc pthread_example.c -lpthread -o pthread_example */ #include #include #include #include #include /* variable sum is shared by the threads */ int sum; /* thread */ void *runner(void *param); /* First thread */ main(int argc, char *argv[]) { key_t key; int semid; struct sembuf sb; pthread_t tid; pthread_attr_t attr; union semun { int val; struct semid_ds *buf; ushort *array; } arg; if (argc !=2){ fprintf(stderr,"Usage: %s \n",argv[0] ); exit(); } if (atoi(argv[1]) < 0) { fprintf(stderr,"(%d) must be >= 0\n",atoi(argv[1])); exit(); } if ((key = ftok("sema_example.c", 'J')) == -1) { printf("\n\nFTOK-ERROR\n\n"); exit(1); } if ((semid = semget(key,1, 0666 | IPC_CREAT)) == -1 ) { printf("\n\nSEMGET-ERROR \n\n"); exit(1); } arg.val = 1; if (semctl(semid, 0, SETVAL, arg) == -1) { printf("\n\nSEMCTL-ERROR\n\n"); exit(1); } /* Set attributes (default attributes are used) */ pthread_attr_init(&attr); /* Create a separate thread */ /* Pass a thread identifier (tid), attributes (attr), name of the */ /* function where the new thread will begin execution (runner), */ /* and the integer parameter provided on the command line (argv[1]) */ /* Now program has two threads: main and runner */ pthread_create(&tid,&attr,runner,argv[1]); /* main waits runner thread using pthread_join */ //pthread_join(tid,NULL); sleep(1); sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = 0; if (semop(semid, &sb, 1) == -1) { printf("\n\nLOCKING-ERROR\n\n"); exit(1); } /* print results of summing */ printf("Sum = %d\n",sum); sb.sem_op = 1; if (semop(semid, &sb, 1) == -1) { printf("\n\nUNLOCKING-ERROR\n\n"); exit(1); } } /* Second thread */ void *runner(void *param) { int upper = atoi(param); int i; key_t key; int semid; struct sembuf sb; if ((key = ftok("pthread_example.c", 'J')) == -1) { printf("\n\nFTOK-ERROR\n\n"); exit(1); } if ((semid = semget(key,1,0)) == -1 ) { printf("\n\nSEMGET-ERROR\n\n"); exit(1); } sb.sem_num = 0; sb.sem_op = -1; sb.sem_flg = 0; if (semop(semid, &sb, 1) == -1) { printf("\n\nLOCKING-ERROR\n\n"); exit(1); } sum = 0; if (upper > 0) { for (i=1; i<=upper; i++) sum +=i; } sb.sem_op = 1; if (semop(semid, &sb, 1) == -1) { printf("\n\nUNLOCKING-ERROR\n\n"); exit(1); } /* runner thread completes here */ pthread_exit(0); } Task 2: solution by Roman. ========================== /* Compile, for example: gcc pthread_example.c -lpthread -o pthread_example */ #include #include /* variable sum is shared by the threads */ int sum; pthread_mutex_t Sem=PTHREAD_MUTEX_INITIALIZER; /* thread */ void *runner1(void *param); void *runner2(void *param); /* First thread */ main(int argc, char *argv[]) { /* Thread identifier */ pthread_t tid1; pthread_t tid2; /* Attributes for a thread (stack size, scheduling ...) */ pthread_attr_t attr; if (argc !=2){ fprintf(stderr,"Usage: %s \n",argv[0] ); exit(); } if (atoi(argv[1]) < 0) { fprintf(stderr,"(%d) must be >= 0\n",atoi(argv[1])); exit(); } /* Set attributes (default attributes are used) */ pthread_attr_init(&attr); /* Create a separate thread */ /* Pass a thread identifier (tid), attributes (attr), name of the */ /* function where the new thread will begin execution (runner), */ /* and the integer parameter provided on the command line (argv[1]) */ /* Now program has two threads: main and runner */ sum=0; pthread_create(&tid1,&attr,runner1,argv[1]); pthread_create(&tid2,&attr,runner2,argv[1]); /* main waits runner thread using pthread_join */ pthread_join(tid2,NULL); pthread_join(tid1,NULL); printf("End balance = %d\n",sum); } /* Second thread */ void *runner1(void *param) { int upper = atoi(param); while (sum<=0) sleep(1); //is not possible to withdraw money //while balance is positive pthread_mutex_lock(&Sem); //we want atomic operation if (sum>=upper) { printf("Withdraw begins.."); sum-=upper; } pthread_mutex_unlock(&Sem); printf("Withdraw completed.."); printf("Balance = %d\n",sum); /* runner thread completes here */ pthread_exit(0); } void *runner2(void *param) { int i; printf("Tranfer begins..."); pthread_mutex_lock(&Sem); //this should be atomic according to a balance //of account for (i=1;i<=30000;i++) { sum +=1; if (i/10000 == i % 10000) sleep(1); } //after burst of 10000 wait a while //e.g. for flushing the cache etc.. pthread_mutex_unlock(&Sem); printf("Tranfer ends.."); printf("balance = %d\n",sum); /* runner thread completes here */ pthread_exit(0); } Task 2: solution by Jaroslav. ============================= /* Compile, for example: gcc pthread_example.c -lpthread -o pthread_example */ #include #include #include #include /* variable sum is shared by the threads */ int sum= 0; pthread_mutex_t mutex; /* thread */ void *runner0(void *param); void *runner1(void *param); /*********************************************** First thread */ int main(int argc, char *argv[]){ /* Thread identifier */ pthread_t tid0, tid1; /* Attributes for a thread (stack size, scheduling ...) */ pthread_attr_t attr; /* Set attributes (default attributes are used) */ pthread_attr_init(&attr); pthread_mutex_init(&mutex, NULL); /* initialize mutex */ pthread_mutex_lock(&mutex); /* Create a separate thread */ /* Pass a thread identifier (tid), attributes (attr), name of the */ /* function where the new thread will begin execution (runner), */ /* and the integer parameter provided on the command line (argv[1]) */ /* Now program has two threads: main and runner */ pthread_create(&tid0, &attr, runner0, NULL); pthread_create(&tid1, &attr, runner1, NULL); /* main waits runner thread using pthread_join */ pthread_join(tid0, NULL); pthread_join(tid1, NULL); // pthread_mutex_destroy(&mutex); /* destroy mutex */ return 0; } /******************************************* Second thread */ void *runner0(void *param){ pthread_mutex_lock(&mutex); /* lock the CS */ while(sum != -5){ sum--; /* changing shared variable */ printf("Thread0: %d\n", sum); /* print result of thread action */ sleep(2); } pthread_mutex_unlock(&mutex); /* unlock the CS */ /* runner0 thread completes here */ pthread_exit(NULL); } /******************************************* Third thread */ void *runner1(void *param){ while(sum != 5){ sum++; /* changing shared variable */ printf("Thread1: %d\n", sum); /*print result of thread action */ sleep(1); } pthread_mutex_unlock(&mutex); /* unlock the CS it was previously locked */ /* runner1 thread completes here */ pthread_exit(NULL); }