I'm wanting to stop traffic of opposing direction from crashing om the bridge. if the randomized get all cars heading east it works fine. It hangs on west bound traffic. im have a feeling that there's a better was to stop threads from colliding as im using so many sem_post() and sem_wait()
any suggestions or help welcome, still just learning threads so i expect to be missing something.
eventually i want randomised traffic from both direction as well as trucks that need the bridge all to them selves where as cars can share so long as the traffic flow is the same.
#include <signal.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/sem.h>
#include <semaphore.h>
#define MAXCARS 5
#define MAXWAIT 10
#define CROSSINGTIME 2
int G_direction = 0;
int carNum;
int retVal=0, lower = 0, upper = 1;
int car_rid[MAXCARS];
pthread_t threads[MAXCARS];
sem_t direc_sem, car_E, car_W,bridge_sem;
const char* printRandoms() ///randomise the cars direction
{
int num = (rand() % (upper - lower + 1)) + lower;
if (num == 0){
//left headed west
return "west";
}else return "east";
//return num;
}
void *car(void *arg) {
int carNum = (int)(intptr_t)arg; //what car is it
const char* direction = printRandoms(); //random direction
printf(" car no %d is idling, planning to go %s \n",carNum, direction);// test print
sleep( rand() % MAXWAIT ); // wait a random amounnt of time
sem_wait(&direc_sem); //isolate the direction value
if(direction == "west"){
if (G_direction > 0){//g_direction -1 = one car headed west -2 two headed west
sem_wait(&car_E);//if traffic flow is in the wrong direction wait for the semaphore
}
G_direction--;//->> move ON the bridge
if (G_direction == -1){//if last car on bridge lock east bound traffic
sem_wait(&car_W);
}
}
sem_post(&direc_sem);
sem_wait(&direc_sem);//isolate the direction value
if(direction == "east"){
if (G_direction < 0){//g_direction 1 = one car headed east 2 two headed east
sem_wait(&car_W);//if traffic flow is in the wrong direction wait for the semaphore
}
G_direction++;//->> move ON the bridge
if (G_direction == 1){//if last car on bridge lock west bound traffic
sem_wait(&car_E);
}
}
sem_post(&direc_sem);
printf("car no %d goes ON the bridge heading %s \n", carNum,direction);
sleep(CROSSINGTIME);
printf("car no %d goes OFF the bridge heading %s \n", carNum, direction);
sem_wait(&direc_sem);//isolate the direction value
if(direction == "west"){
G_direction++;//->> move OFF the bridge
if (G_direction == 0){//if last car on bridge unlock other traffic
sem_post(&car_W);
}
}
sem_post(&direc_sem);
sem_wait(&direc_sem);//isolate the direction value
if(direction == "east"){
G_direction--;//->> move off the bridge
if (G_direction == 0){//if last car on bridge unlock other traffic
sem_post(&car_E);
}
}
sem_post(&direc_sem);
}
int main( void ){
sem_init(&direc_sem, 0, 1);
sem_init(&car_E, 0, 1);
sem_init(&bridge_sem, 0, 1);
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_create(&threads[i], NULL,car ,(void *)(intptr_t)i);
if(retVal!=0){
printf("pthread_create failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_join(threads[i], NULL);
if(retVal!=0){
printf("pthread_join failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
//sem_destroy(&carLock);
return 0;
}```
Related
I tried to solve the Sleeping Barber problem using the pthread functions.
code:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <pthread.h>
#include <unistd.h>
#define NR_CUSTOMERS 20
#define NR_CHAIRS 3 //chairs in the waiting room + barber chair
sem_t lock;
sem_t customer;
sem_t barber;
int waitingCustomers = 0;
int barberChair = 0;
void *th_customer(void *arg)
{
int myId = (int)(size_t)arg;
int tooBusy = 0;
usleep(1000 * (rand() % 20));
printf("[C%02d] Entering the barber shop\n", myId);
sem_wait(&lock);
if (waitingCustomers < NR_CHAIRS) //if there are still empty seats, the client waits
{
++waitingCustomers;
printf("[C%02d] %d customer(s) waiting\n", myId, waitingCustomers);
}
else
{
tooBusy = 1; //if not the client leaves because it is too crowded
}
sem_post(&lock);
if (tooBusy)
{
printf("[C%02d] Too busy, will come back another day.\n", myId);
}
else //one of the waiting customers is served
{
sem_wait(&customer);
sem_wait(&lock);
--waitingCustomers;
sem_post(&lock);
barberChair = myId;
sem_post(&barber);
printf("[C%02d] being served\n", myId);
usleep(1000);
}
return NULL;
}
void *th_barber()
{
for (;;)
{
sem_post(&customer);
sem_wait(&barber);
printf("[B ] Serving customer %d\n", barberChair);
usleep(1000);
}
return NULL;
}
int main()
{
int i;
pthread_t tidC[NR_CUSTOMERS], tidB;
srand(time(NULL));
sem_init(&lock, 0, 1);
sem_init(&customer, 0, 0);
sem_init(&barber, 0, 0);
pthread_create(&tidB, NULL, th_barber, NULL);
for (i = 0; i < NR_CUSTOMERS; i++)
{
pthread_create(&tidC[i], NULL, th_customer, (void *)(size_t)(i + 1));
}
for (i = 0; i < NR_CUSTOMERS; i++)
{
pthread_join(tidC[i], NULL);
}
pthread_cancel(tidB);
pthread_join(tidB, NULL);
sem_destroy(&lock);
sem_destroy(&customer);
sem_destroy(&barber);
return 0;
}
The problem: I'm worried about possible concurrence, not the data, that's correct, but in terms of not using available resources: a customer may not receive a haircut due to the maximum number of customers, but one is already on his way to the barber chair, but does he who enters just not notice that his place has just been vacated?
What other problems can be hidden?
I'm trying to wrap my head wrap my head around threads, I would like to have only one direction of car on the bridge at a time at at the moment only east bound cars work. i commented out line 37's randomized+ direction function and when substituting in "east"code works as expected, but when running "west" it hold and theres my issue. Any help appreciated.
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include <sys/sem.h>
#include <semaphore.h>
#define MAXCARS 5
#define MAXWAIT 10
#define CROSSINGTIME 2
int G_direction = 0;
int carNum;
int retVal=0, lower = 0, upper = 1;
int car_rid[MAXCARS];
pthread_t threads[MAXCARS];
sem_t direc_sem, car_E, car_W,bridge_sem;
const char* printRandoms() ///randomise the cars direction
{
int num = (rand() % (upper - lower + 1)) + lower;
if (num == 0){
//left headed west
return "west";
}else return "east";
//return num;
}
void *car(void *arg) {
int carNum = (int)(intptr_t)arg; //what car is it
const char* direction = "west";//printRandoms(); //random direction
printf("car no %d is idling, planning to go %s \n",carNum, direction);// test print
sleep( rand() % MAXWAIT ); // wait a random amounnt of time
sem_wait(&direc_sem);//isolate the direction value
if(strcmp(direction,"west") == 0){
if (G_direction > 0){//g_direction 1 = one car headed east 2 two headed east
sem_wait(&car_E);//if traffic flow is in the wrong direction wait for the semaphore
}
G_direction--;//->> move ON the bridge
if (G_direction == -1){//if last car on bridge lock west bound traffic
sem_wait(&car_W);
}
}
sem_post(&direc_sem);
sem_wait(&direc_sem);//isolate the direction value
if(strcmp(direction,"east") == 0){
if (G_direction < 0){//g_direction 1 = one car headed east 2 two headed east
sem_wait(&car_W);//if traffic flow is in the wrong direction wait for the semaphore
}
G_direction++;//->> move ON the bridge
if (G_direction == 1){//if last car on bridge lock west bound traffic
sem_wait(&car_E);
}
}
sem_post(&direc_sem);
printf("car no %d goes ON the bridge heading %s \n", carNum,direction);
sleep(CROSSINGTIME);
printf("car no %d goes OFF the bridge heading %s \n", carNum, direction);
sem_wait(&direc_sem);//isolate the direction value
if(strcmp(direction, "west") == 0){
G_direction++;//->> move OFF the bridge
if (G_direction == 0){//if last car on bridge unlock other traffic
sem_post(&car_W);
}
}
sem_post(&direc_sem);
sem_wait(&direc_sem);//isolate the direction value
if(strcmp(direction,"east") == 0){
G_direction--;//->> move off the bridge
if (G_direction == 0){//if last car on bridge unlock other traffic
sem_post(&car_E);
}
}
sem_post(&direc_sem);
}
int main( void ){
sem_init(&direc_sem, 0, 1);
sem_init(&car_E, 0, 1);
sem_init(&bridge_sem, 0, 1);
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_create(&threads[i], NULL,car ,(void *)(intptr_t)i);
if(retVal!=0){
printf("pthread_create failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_join(threads[i], NULL);
if(retVal!=0){
printf("pthread_join failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
//sem_destroy(&carLock);
return 0;
}
This code isn't finished yet so right know it should just print the lines out. but i cant figure out whats locking the first P( direc_sem );
#include <sys/types.h>
#include <sys/ipc.h>
#include <time.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <pthread.h>
#include "sem_ops.h"
#include <semaphore.h>
#define MAXCARS 5
#define MAXWAIT 20
#define CROSSINGTIME 4
int G_direction = 0, direc_sem, car_E;
int carNum;
int retVal=0, lower = 0, upper = 1;
int car_rid[MAXCARS];
pthread_t threads[MAXCARS];
const char* printRandoms()
{
int num = (rand() % (upper - lower + 1)) + lower;
if (num == 0){
//left headed west
return "west";
}else return "east";
//return num;
}
void *car(void *arg) {
int carNum = (int)(intptr_t)arg; //what car is it
const char* direction = printRandoms(); //random direction
printf(" car no %d is idling, planning to go %s \n",carNum, direction);// test print
sleep( rand() % MAXWAIT ); // wait a random amounnt of time
//P( reader_sem );
//readers++;
//if( readers == 1 )
// P( counter_sem );
//V( reader_sem );
P( direc_sem );
if (G_direction >=0){
G_direction++;//->> move on to bridge
if (G_direction == 1){//if first car on bridge lock other traffic
P(car_E);
}else {
printf("stuck");
}
}
V(direc_sem);
printf("car no %d goes on the bridge heading %s \n", carNum,direction);
sleep(CROSSINGTIME);
printf("car no %d goes off the bridge heading %s \n", carNum, direction);
P(direc_sem);
G_direction--;//->> move off the bridge
if (G_direction == 0){//if last car on bridge unlock other traffic
V(car_E);
}
V(direc_sem);
//bridge no longer empty
// printf("W car# %d => %d\n", carNum, G_direction);//print test
// }// wait till westbound car is free
}
void Truck(){
}
int main( void ){
direc_sem = semtran( IPC_PRIVATE );
car_E = semtran( IPC_PRIVATE );
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_create(&threads[i], NULL,car ,(void *)(intptr_t)i);
if(retVal!=0){
printf("pthread_create failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
for (int i = 0; i < MAXCARS; i++){
retVal = pthread_join(threads[i], NULL);
if(retVal!=0){
printf("pthread_join failed in %d_th pass\n",i);
exit(EXIT_FAILURE);
}
}
//sem_destroy(&carLock);
return 0;
}
compiled with wrong file definitely been at this too long thank you
We have to make a program that simulates the function of a booking system for seats in a theater. We have N_cust clients that call at the telephone center and N_tel people who answer the phone calls. Each call lasts from t_seathigh to t_seatlow seconds. The payment with the credit card is successful with probability P_cardsuccess. The two arguments that the program gets are the number of clients and the seed for rand_r.There is a thread for each client, and the clients have to wait for a person to talk on the phone. My problem is that the program runs but gives a segmentation fault or gets stuck in an infinite loop on the first loop of the function AwesomeThreadFunction.
I thought that maybe I have not handled the variable telefoners correctly since the program sometimes gets stuck in the first loop of the function but I don't know how exactly. I also don't know why I get this segmentation fault. Where exactly does my program try to access not allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <pthread.h>
#include "p3170013-p3170115-p3170097-res1.h"
#include <unistd.h>
#define N_seat 250
#define N_tel 8
#define N_seatlow 1
#define N_seathigh 5
#define t_seatlow 5
#define t_seathigh 10
#define P_cardsuccess 0.9
#define C_seat 20.0
#define BILLION 1E9
pthread_mutex_t lock_phone, lock_bank_account,lock_number_of_transfer,lock_wait_time, lock_service_time, lock_plan, lock_screen;
int plan[N_seat];
int phone_count=0,bank_account=0,tid=0,seats=0,telefoners=N_tel;
unsigned int seed;
float avg_wait_time=0,avg_service_time;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
void* AwesomeThreadFunction(void* vargc){
tid=*(int*)vargc;
struct timespec waitStart, waitEnd;
clock_gettime(CLOCK_REALTIME, &waitStart);
avg_wait_time-=(waitStart.tv_sec+waitStart.tv_nsec/BILLION);
pthread_mutex_lock(&lock_screen);
printf("%d\n",telefoners);
pthread_mutex_unlock(&lock_screen);
pthread_mutex_lock(&lock_phone);
while (telefoners == 0) {
pthread_cond_wait(&cond, &lock_phone);
}
telefoners--;
pthread_mutex_unlock(&lock_phone);
pthread_mutex_lock(&lock_screen);
printf("coooooooool\n");
pthread_mutex_unlock(&lock_screen);
clock_gettime(CLOCK_REALTIME, &waitEnd);
avg_wait_time+=(waitEnd.tv_sec+waitEnd.tv_nsec/BILLION);
struct timespec talkStart, talkEnd;
clock_gettime(CLOCK_REALTIME, &talkStart);
int how_many_seats=rand_r(&seed);
seed=how_many_seats;
how_many_seats=how_many_seats%(N_seathigh-N_seatlow)+N_seatlow;
int how_many_seconds=rand_r(&seed);
seed=how_many_seconds;
how_many_seconds=how_many_seconds%(t_seathigh-t_seatlow)+t_seatlow;
sleep(how_many_seconds);
if(seats==N_seat){
pthread_mutex_lock(&lock_screen);
printf("%d Reservation cancelled because the theater is full\n",*(int*)vargc);
pthread_mutex_unlock(&lock_screen);
}else if(seats+how_many_seats>N_seat){
pthread_mutex_lock(&lock_screen);
printf("%d Reservation cancelled because there are not enough seats available\n",*(int*)vargc);
pthread_mutex_unlock(&lock_screen);
}else{
int c=0,i=0;
pthread_mutex_lock(&lock_number_of_transfer);
pthread_mutex_unlock(&lock_number_of_transfer);
pthread_mutex_lock(&lock_plan);
while(c<how_many_seats){
if(!plan[i]){
plan[i]=tid;
c++;
}
i++;
}
seats+=how_many_seats;
pthread_mutex_unlock(&lock_plan);
int card_success=rand_r(&seed);
seed=card_success;
float tempp=(float)card_success/(float)RAND_MAX;
card_success=(tempp<=P_cardsuccess);
if(!card_success){
pthread_mutex_lock(&lock_screen);
printf("%d Reservation cancelled because the transaction with the credit card was not accepted\n",*(int*)vargc);
pthread_mutex_unlock(&lock_screen);
pthread_mutex_lock(&lock_plan);
c=0;i=0;
while(c<how_many_seats){
if(plan[i]==tid){
plan[i]=0;
c++;
}
pthread_mutex_lock(&lock_screen);
pthread_mutex_unlock(&lock_screen);
i++;
}
seats-=how_many_seats;
pthread_mutex_unlock(&lock_plan);
pthread_mutex_lock(&lock_number_of_transfer);
pthread_mutex_unlock(&lock_number_of_transfer);
}else{
pthread_mutex_lock(&lock_screen);
printf("%d Reservation completed successfully.The number of the transaction is %d, your seats are ",*(int*)vargc,*(int*)vargc);
pthread_mutex_unlock(&lock_screen);
c=0;i=0;
pthread_mutex_lock(&lock_plan);
while(c<how_many_seats){
if(plan[i]==*(int*)vargc){
pthread_mutex_lock(&lock_screen);
printf("%d ",i);
pthread_mutex_unlock(&lock_screen);
c++;
}
i++;
}
pthread_mutex_unlock(&lock_plan);
pthread_mutex_lock(&lock_screen);
printf("and the cost of the transaction is %.2f euros\n",how_many_seats*C_seat);
pthread_mutex_unlock(&lock_screen);
pthread_mutex_lock(&lock_bank_account);
bank_account+=how_many_seats*C_seat;
pthread_mutex_unlock(&lock_bank_account);
}
}
//we assume that the client is fully served when we have also printed out his/her result of the try to book seats
clock_gettime(CLOCK_REALTIME, &talkEnd);
double cow = ( talkEnd.tv_sec - talkStart.tv_sec ) + ( talkEnd.tv_nsec - talkStart.tv_nsec ) / BILLION;
pthread_mutex_lock(&lock_service_time);
avg_service_time+=cow;
pthread_mutex_unlock(&lock_service_time);
pthread_mutex_lock(&lock_phone);
telefoners++;
pthread_cond_signal(&cond);
pthread_mutex_unlock(&lock_phone);
pthread_exit(0);
}
int main(int argc,char* argv[]){
int i;
for(i=0;i<N_seat;i++){
plan[i] = 0;
}
//if user did not give the correct number of arguments
if(argc!=3){
printf("Wrong number of arguments\n");
return -1;
}
int N_cust=atoi(argv[1]),tel_available=N_tel,err;
i=0;
seed=atoi(argv[2]);
pthread_t *threads=(pthread_t*)malloc(N_cust*sizeof(pthread_t));
int threadid[N_cust];
//if we can't init one of the mutexes
pthread_mutex_init(&lock_phone, NULL);
pthread_mutex_init(&lock_bank_account, NULL);
pthread_mutex_init(&lock_number_of_transfer, NULL);
pthread_mutex_init(&lock_wait_time, NULL);
pthread_mutex_init(&lock_service_time, NULL);
pthread_mutex_init(&lock_plan, NULL);
pthread_mutex_init(&lock_screen, NULL);
//creating the threads
while(i<N_cust){
threadid[i]=i+1;
err = pthread_create(&(threads[i]), NULL, AwesomeThreadFunction, (void*)&threadid[i]); //func name
if (err){
printf("Thread can't be created :[%s]\n", strerror(err));
}
i++;
}
//join the threads
void *status;
for (i = 0; i < N_cust; i++) {
rc = pthread_join(threads[i], &status);
if (rc != 0) {
printf("ERROR: return code from pthread_join() is %d\n", rc);
exit(-1);
}
printf("Main: Thread %lu finished with status %d.\n", threads[i], *(int *)status);
}
//final output
for(i=0;i<N_seat;++i){
if(plan[i]){
printf("Seat %d / client %d\n",i+1,plan[i]);
}
}
printf("Total revenue from sales:\t%d\n",bank_account);
printf("Average waiting time:\t%f\n",(float)avg_wait_time/(float)N_cust);
printf("Average service time:\t%f\n",(float)avg_service_time/(float)N_cust);
free(threads);
//Destroy mutexes
pthread_mutex_destroy(&lock_phone);
pthread_mutex_destroy(&lock_bank_account);
pthread_mutex_destroy(&lock_number_of_transfer);
pthread_mutex_destroy(&lock_wait_time);
pthread_mutex_destroy(&lock_service_time);
pthread_mutex_destroy(&lock_plan);
pthread_mutex_destroy(&lock_screen);
pthread_cond_destroy(&cond);
return 0;
}
An immediate problem leading to segfault is in (irrelevant details omitted):
if(seats+how_many_seats>N_seat) {
....
} else {
int c=0,i=0;
pthread_mutex_lock(&lock_plan);
while(c<how_many_seats) {
if(!plan[i]){
plan[i]=tid;
c++;
}
i++;
}
seats+=how_many_seats;
pthread_mutex_unlock(&lock_plan);
The code determines if it can satisfy the request, and happily proceeds to reserving seats. Only then it locks the plan. Meanwhile, between testing for seats+how_many_seats>N_seat and locking the plan, another thread does the same and modifies the plan. After that there is less seats available than the first thread expects, and the while(c<how_many_seats) loop accesses plan off bounds.
I didn't check the rest; I expect other similar problems. The non-volatile globals are very suspicious. In any case, do yourself a favor and use more functions.
I am trying to square the numbers 1 - 10,000 with 8 threads. To clarify, I want the 1st thread to do 1^2, 2nd thread to do 2^2, ..., 8th thread to do 8^2, first thread to do 9^2... etc. The problem I am having is that instead of the above happening, each thread computes the squares of 1-10,000.
My code is below. I have marked sections that I'd rather those answering do not modify. Thanks in advance for any tips!
#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <pthread.h>
#define NUMBER_OF_THREADS 8
#define START_NUMBER 1
#define END_NUMBER 10000
FILE *f;
void *sqrtfunc(void *tid) { //function for computing squares
int i;
for (i = START_NUMBER; i<=END_NUMBER; i++){
fprintf(f, "%lu squared = %lu\n", i, i*i);
}
}
int main(){
//Do not modify starting here
struct timeval start_time, end_time;
gettimeofday(&start_time, 0);
long unsigned i;
f = fopen("./squared_numbers.txt", "w");
//Do not modify ending here
pthread_t mythreads[NUMBER_OF_THREADS]; //thread variable
long mystatus;
for (i = 0; i < NUMBER_OF_THREADS; i++){ //loop to create 8 threads
mystatus = pthread_create(&mythreads[i], NULL, sqrtfunc, (void *)i);
if (mystatus != 0){ //check if pthread_create worked
printf("pthread_create failed\n");
exit(-1);
}
}
for (i = 0; i < NUMBER_OF_THREADS; i++){
if(pthread_join(mythreads[i], NULL)){
printf("Thread failed\n");
}
}
exit(1);
//Do not modify starting here
fclose(f);
gettimeofday(&end_time, 0);
float elapsed = (end_time.tv_sec-start_time.tv_sec) * 1000.0f + \
(end_time.tv_usec-start_time.tv_usec) / 1000.0f;
printf("took %0.2f milliseconds\n", elapsed);
//Do not modify ending here
}