c - Problems with Pthreads; Changing value, etc -
i know title's vague, couldn't figure out else call it.
sleeper.h
#ifndef sleeper_h #define sleeper_h #include <unistd.h> int ridetime(int, int); void walkaroundtime(int); #endif sleeper.c
#include <stdio.h> #include <stdlib.h> #include "sleeper.h" int ridetime(int id, int car) { int seconds = ( rand() % 5) + 1 ; printf ("person %d riding car %d %d seconds.\n", id, car, seconds); sleep (seconds); return car; } void walkaroundtime(int id) { int seconds = (rand() % 10) + 1 ; printf ("person %d walking around %d seconds.\n", id, seconds); sleep (seconds); } bumper_cars.c
#include <stdio.h> #include <stdlib.h> #include <pthread.h> #include <time.h> #include "sleeper.h" void* person(void*); int getinline(int); void returncar(int); pthread_mutex_t lock = pthread_mutex_initializer; pthread_cond_t car_availability = pthread_cond_initializer; int available_cars; int num_cars; int* cars; int main(int argc, char* argv[]) { num_cars = atoi(argv[1]); int num_people = atoi(argv[2]); int sim_time = atoi(argv[3]); available_cars = num_cars; cars = calloc(num_cars, sizeof(int)); pthread_t* threads = calloc(num_people, sizeof(pthread_t)); srand((unsigned)time (null)); (int = 0; < num_cars; i++) { cars[i] = 1; } (int = 0; < num_people; i++) { int* id = malloc(sizeof(*id)); *id = + 1; pthread_create(&threads[i], null, person, (void*)(id)); } //printf("main: sleeping %d seconds\n", sim_time); sleep(sim_time); //printf("done sleeping.\n"); (int = 0; < num_people; i++) { pthread_cancel(threads[i]); } printf("simulation complete.\n"); pthread_mutex_destroy(&lock); free(cars); free(threads); exit(exit_success); } void* person(void* arg) { int car = 0; int id = *((int *) arg); while (1) { walkaroundtime(id); car = getinline(id); ridetime(id, car); returncar(car); } } int getinline(int id) { int car = 0; printf("person %d waiting car.\n", id); pthread_mutex_lock(&lock); if (available_cars == 0) { pthread_cond_wait(&car_availability,&lock); } (int = 0; < num_cars; i++) { if (cars[i] == 1) { car = + 1; cars[i] = 0; break; } } available_cars--; return car; } void returncar(int carid) { available_cars++; cars[carid] = 1; printf("car %d has been returned.\n", carid); pthread_cond_broadcast(&car_availability); pthread_mutex_unlock(&lock); } so... have 2 problems program. significant works 1 car. if there multiple cars , 1 taken other people still must wait returned.
the second, less significant problem when start code 1 car, id of car starts @ 0, alternates between 1 , 0, when should 1. looking @ code, it's not obvious me these problems originating... , gdb proving rather unhelpful.
the problem holding lock long once acquire car. modified function in way, changes noted in comments:
int getinline(int id) { int car = 0; printf("person %d waiting car.\n", id); pthread_mutex_lock(&lock); // use while loop because pthread_cond_wait() subject // spurious awakenings. while (available_cars == 0) { pthread_cond_wait(&car_availability,&lock); } (int = 0; < num_cars; i++) { if (cars[i] == 1) { car = + 1; cars[i] = 0; break; } } available_cars--; // unlock mutex here done acquiring car. // if don't unlock mutex here, no 1 else can acquire car. pthread_mutex_unlock(&lock); return car; } void returncar(int carid) { // lock mutex here before returning car. pthread_mutex_lock(&lock); available_cars++; // need -1 here because carid 1 bigger index. cars[carid-1] = 1; printf("car %d has been returned.\n", carid); pthread_cond_broadcast(&car_availability); pthread_mutex_unlock(&lock); } by way, noticed use rand() generate random numbers. however, if multiple threads call rand() @ same time same random number (at least that's happened when ran program). should use rand_r() instead , create different seeds each thread.
Comments
Post a Comment