/* elevator_skeleton.c Header file for the elevator threads lab. Jim Plank CS560 Lab 2 January, 2009 */ #include #include #include #include #include "names.h" #include "elevator.h" #include "finesleep.h" #include "dllist.h" #define talloc(ty, sz) (ty *) malloc ((sz) * sizeof(ty)) void *FINESLEEPER; void move_to_floor(Elevator *e, int floor) { double diff; pthread_mutex_lock(e->lock); if (e->door_open) { fprintf(stderr, "Error at time %.3lf: Move to floor on elevator %02d with the door open.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } if (e->moving) { fprintf(stderr, "Error at time %.3lf: Move to floor on elevator %02d that is already moving.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } diff = floor - e->onfloor; if (diff < 0) diff = -diff; diff *= e->es->floor_to_floor_time; e->moving = 1; pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d moving from floor %02d to floor %02d.\n", finesleep_time(FINESLEEPER), e->id, e->onfloor, floor); fflush(stdout); pthread_mutex_unlock(e->es->lock); pthread_mutex_unlock(e->lock); finesleep_sleep(FINESLEEPER, diff); pthread_mutex_lock(e->lock); pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d arrives at floor %02d.\n", finesleep_time(FINESLEEPER), e->id, floor); fflush(stdout); pthread_mutex_unlock(e->es->lock); e->moving = 0; e->onfloor = floor; pthread_mutex_unlock(e->lock); } void open_door(Elevator *e) { if (e->door_open) { fprintf(stderr, "Error at time %.3lf: Open door called on elevator %02d with the door already open.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } if (e->moving) { fprintf(stderr, "Error at time %.3lf: Open door called on elevator %02d with the elevator moving.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d opening its door.\n", finesleep_time(FINESLEEPER), e->id); fflush(stdout); pthread_mutex_unlock(e->es->lock); finesleep_sleep(FINESLEEPER, e->es->door_time); pthread_mutex_lock(e->lock); pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d door is open.\n", finesleep_time(FINESLEEPER), e->id); fflush(stdout); pthread_mutex_unlock(e->es->lock); e->door_open = 1; pthread_mutex_unlock(e->lock); } void close_door(Elevator *e) { if (!e->door_open) { fprintf(stderr, "Error at time %.3lf: Close door called on elevator %02d with the door already open.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } if (e->moving) { fprintf(stderr, "Error at time %.3lf: Close door called on elevator %02d with the elevator moving.\n", finesleep_time(FINESLEEPER), e->id); exit(1); } pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d closing its door.\n", finesleep_time(FINESLEEPER), e->id); fflush(stdout); pthread_mutex_unlock(e->es->lock); finesleep_sleep(FINESLEEPER, e->es->door_time); pthread_mutex_lock(e->lock); pthread_mutex_lock(e->es->lock); printf("%8.3lf: Elevator %02d door is closed.\n", finesleep_time(FINESLEEPER), e->id); fflush(stdout); pthread_mutex_unlock(e->es->lock); e->door_open = 0; pthread_mutex_unlock(e->lock); } void get_on_elevator(Person *p) { Elevator *e; e = p->e; if (e == NULL) { fprintf(stderr, "Error at time %.3lf: %s %s called get_on_elevator with a NULL elevator.\n", finesleep_time(FINESLEEPER), p->fname, p->lname); exit(1); } pthread_mutex_lock(e->lock); if (!e->door_open) { fprintf(stderr, "Error at time %.3lf: %s %s get_on_elevator(%02d) - door closed.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } if (e->moving) { fprintf(stderr, "Error at time %.3lf: %s %s get_on_elevator(%02d) - elevator moving.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } if (e->onfloor != p->from) { fprintf(stderr, "Error at time %.3lf: %s %s get_on_elevator(%02d) - Elevator on wrong floor.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } dll_append(e->people, new_jval_v((void *) p)); p->ptr = e->people->blink; pthread_mutex_lock(e->es->lock); printf("%8.3lf: %s %s gets on elevator %02d on floor %02d.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id, e->onfloor); fflush(stdout); pthread_mutex_unlock(e->es->lock); pthread_mutex_unlock(e->lock); } void get_off_elevator(Person *p) { Elevator *e; e = p->e; if (e == NULL) { fprintf(stderr, "Error at time %.3lf: %s %s called get_off_elevator with a NULL elevator.\n", finesleep_time(FINESLEEPER), p->fname, p->lname); exit(1); } pthread_mutex_lock(e->lock); if (!e->door_open) { fprintf(stderr, "Error at time %.3lf: %s %s get_off_elevator(%02d) - door closed.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } if (e->moving) { fprintf(stderr, "Error at time %.3lf: %s %s get_off_elevator(%02d) - elevator moving.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } if (e->onfloor != p->to) { fprintf(stderr, "Error at time %.3lf: %s %s get_off_elevator(%02d) - Elevator on wrong floor.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id); exit(1); } dll_delete_node(p->ptr); p->ptr = NULL; pthread_mutex_lock(p->es->lock); printf("%8.3lf: %s %s gets off elevator %02d on floor %02d.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, e->id, e->onfloor); fflush(stdout); pthread_mutex_unlock(p->es->lock); pthread_mutex_unlock(e->lock); } void *person(void *arg) { Person *p; p = (Person *) arg; pthread_mutex_lock(p->es->lock); p->es->npeople_started++; printf("%8.3lf: %s %s arrives at floor %02d wanting to go to floor %02d.\n", finesleep_time(FINESLEEPER), p->fname, p->lname, p->from, p->to); fflush(stdout); pthread_mutex_unlock(p->es->lock); wait_for_elevator(p); get_on_elevator(p); wait_to_get_off_elevator(p); get_off_elevator(p); person_done(p); pthread_mutex_lock(p->es->lock); printf("%8.3lf: %s %s is done.\n", finesleep_time(FINESLEEPER), p->fname, p->lname); fflush(stdout); p->es->npeople_finished++; pthread_mutex_unlock(p->es->lock); pthread_mutex_destroy(p->lock); free(p->lock); pthread_cond_destroy(p->cond); free(p->cond); free(p); return NULL; } void *person_gen(void *arg) { Elevator_Simulation *es; pthread_t tid; double tosleep; Person *p; double perc; char *s; int pn; pn = 0; es = (Elevator_Simulation *) arg; while (1) { tosleep = -1.0 * log(1.0 - drand48()) * es->interarrival_time; finesleep_sleep(FINESLEEPER, tosleep); p = talloc(Person, 1); p->fname = FNAMES[lrand48()%200]; s = LNAMES[lrand48()%200]; p->lname = talloc(char, strlen(s)+20); sprintf(p->lname, "%s(%d)", s, pn); pn++; perc = drand48(); if (perc < 0.333333) { p->from = 1; p->to = lrand48()%(es->nfloors-1) + 2; } else if (perc < 0.6666667) { p->from = lrand48()%(es->nfloors-1) + 2; p->to = 1; } else { p->from = lrand48()%(es->nfloors) + 1; do { p->to = lrand48()%(es->nfloors) + 1; } while (p->from == p->to); } p->arrival_time = finesleep_time(FINESLEEPER); p->e = NULL; p->ptr = NULL; p->lock = talloc(pthread_mutex_t, 1); pthread_mutex_init(p->lock, NULL); p->cond = talloc(pthread_cond_t, 1); pthread_cond_init(p->cond, NULL); p->es = es; initialize_person(p); if (pthread_create(&tid, NULL, person, (void *) p) != 0) { pthread_mutex_lock(es->lock); printf("Pthread create for person %d failed\n", pn); fflush(stdout); exit(1); } pthread_detach(tid); } } void usage(char *s) { fprintf(stderr, "usage: elevator nfloors nelevators interarrival opentime floor_to_floor duration seed\n"); if (s != NULL) fprintf(stderr, "%s\n", s); exit(1); } main(int argc, char **argv) { Elevator_Simulation ES, *es; pthread_t tid; int i; Elevator *e; double duration; long seed; es = &ES; if (argc != 8) usage(NULL); if (sscanf(argv[1], "%d", &es->nfloors) != 1 || es->nfloors <= 1) { usage("Bad nfloors (must be > 1)"); } if (sscanf(argv[2], "%d", &es->nelevators) != 1 || es->nelevators <= 0) { usage("Bad nelevators (must be > 0)"); } if (sscanf(argv[3], "%lf", &es->interarrival_time) != 1 || es->interarrival_time <= 0) { usage("Bad interarrival (must be > 0)"); } if (sscanf(argv[4], "%lf", &es->door_time) != 1 || es->door_time <= 0) { usage("Bad opentime (must be > 0)"); } if (sscanf(argv[5], "%lf", &es->floor_to_floor_time) != 1 || es->floor_to_floor_time <= 0) { usage("Bad floor_to_floor (must be > 0)"); } if (sscanf(argv[6], "%lf", &duration) != 1 || duration <= 0) { usage("Bad duration (must be > 0)"); } if (sscanf(argv[7], "%ld", &seed) != 1) { usage("Bad seed"); if (seed == -1) seed = time(0); } srand48(seed); es->lock = talloc(pthread_mutex_t, 1); pthread_mutex_init(es->lock, NULL); es->npeople_started = 0; es->npeople_finished = 0; FINESLEEPER = finesleep_initialize(1); initialize_simulation(es); for (i = 0; i < es->nelevators; i++) { e = talloc(Elevator, 1); e->id = i+1; e->onfloor = 1; e->door_open = 0; e->moving = 0; e->people = new_dllist(); e->lock = talloc(pthread_mutex_t, 1); pthread_mutex_init(e->lock, NULL); e->cond = talloc(pthread_cond_t, 1); pthread_cond_init(e->cond, NULL); e->es = es; initialize_elevator(e); if (pthread_create(&tid, NULL, elevator, (void *) e) != 0) { printf("Pthread create for elevator %d failed\n", i); exit(1); } pthread_detach(tid); } if (pthread_create(&tid, NULL, person_gen, (void *) es) != 0) { printf("Pthread create for person_gen failed\n"); exit(1); } pthread_detach(tid); finesleep_sleep(FINESLEEPER, duration); pthread_mutex_lock(es->lock); printf("%8.3lf: Simulation Over. %10d Started. %10d Finished.\n", finesleep_time(FINESLEEPER), es->npeople_started, es->npeople_finished); exit(0); pthread_mutex_unlock(es->lock); }