////////////////////////////////////////////////////////////////// PUBLIC //---------------------------------------------------- Fonctions publiques void Entrance ( TypeBarriere entrance ) // Algorithme : // 1. Dequeue a car from the mailbox (or wait for a car to arrive in // the mailbox) and decrement the number of available spots // 2. Read the number of available spots (from the shared memory) // 4. If there's enough space to go in directly, go to 6 // 5. Otherwise, place a request in the shared memory and wait for SIGUSR1 // 6. A spot is available for us, call GarerVoiture() // 7. Sleep for <ENTRANCE_SLEEP_DELAY> seconds // 8. Goto step 1. { //----------------------------------------------------- INITIALIZATION init ( ); //---------------------------------------------------------------- RUN for ( ; ; ) { Car next = waitForCar ( entrance ); int freeSpotsLeft = decrementFreeSpots ( ); DessinerVoitureBarriere ( entrance, next.priority ); // If there's no free spot right now, place a request // and wait patiently to be signaled by the exit gate // TODO: let GarerVoiture make the canGoIn check? if ( freeSpotsLeft < 0 ) { authorizationReceived = false; placeRequest ( entrance, next ); SetSignalHandler ( SIGUSR1, authorize ); while ( !authorizationReceived ) { pause ( ); } MaskSignal ( SIGUSR1 ); } // Allow the car to go in pid_t valetPid = GarerVoiture ( entrance ); currentValets[valetPid] = next; // Sleep for at least <ENTRANCE_SLEEP_DELAY> // before allowing another car in unsigned int remaining = ENTRANCE_SLEEP_DELAY; while ( remaining > 0 ) { remaining = sleep ( remaining ); } } } // Fin de Entrance
static void Moteur(TypeBarriere parametre) // Algorithme : // Phase moteur de la tâche Entree // S'occupe d'aller piocher un message dans la BaL associée à parametre, et à gérer cette voiture // (la faire entrer, ou attendre que ce soit son tour de rentrer si le parking est plein) { struct sembuf reserver = {MUTEX_MEMPARTAGEE, -1,0}; //p Operation --> Reservation struct sembuf liberer = {MUTEX_MEMPARTAGEE, 1, 0}; //v Operation --> liberation msgClavier* voiture = (msgClavier*) malloc(sizeof(struct msgClavier)); if(msgrcv(balId, voiture, TAILLE_MESSAGE, parametre, 0) != -1) { DessinerVoitureBarriere(parametre,voiture->typeVehicule); while(semop(semId,&reserver,1)==-1 && errno==EINTR); //Reservation de la memoire structMemoire *park = (structMemoire *) shmat(idMemPart, NULL, 0) ; //attachement if(park->nbPlacesLibres <= 0) { park->attente[parametre-1] = (*voiture); shmdt(park); //detachement semop(semId,&liberer,1); //Liberation de la memoire partagee AfficherRequete(parametre, voiture->typeVehicule, voiture->tArrivee); SetSemAttente(parametre,1); while(GetSemAttente(parametre) == 1){sleep(0.1);}; Effacer((TypeZone)(parametre+ETAT_P8)); // l'indice de la zone commence à ETAT_P8 + 1, les parametres des portes font le complément d'indice while(semop(semId,&reserver,1)==-1 && errno==EINTR); //Reservation de la memoire park = (structMemoire *) shmat(idMemPart, NULL, 0) ; //atta chement } park->nbPlacesLibres--; shmdt(park); //detachement semop(semId,&liberer,1); //Liberation de la memoire partagee pid_t garer=GarerVoiture(parametre); Voiturier temp; temp.mouvementGarer = garer; temp.voiture = voiture; mouvementPark.push_back(temp); sleep(ATTENTE); } } //----- fin de Moteur
////////////////////////////////////////////////////////////////// PUBLIC //---------------------------------------------------- Fonctions publiques void GestionEntree(int canalEntree[][2], int canalSortie[2], TypeBarriere typeEntree, int shmIdParking, int shmIdRequete, int semIdParam) { // --- INITIALISATION --- semId = semIdParam; numBarriere = typeEntree -1; decrSemEntree[0].sem_num = numBarriere; decrSemEntree[0].sem_op = -1; decrSemEntree[0].sem_flg = 0; // Canaux : On ferme tout sauf en lecture sur la barriere concernee for(unsigned int barriereEntree = 0; barriereEntree < NB_BARRIERES_ENTREE ; barriereEntree++) { if(barriereEntree != numBarriere) { close(canalEntree[barriereEntree][0]); close(canalEntree[barriereEntree][1]); } else { close(canalEntree[barriereEntree][1]); } } close(canalSortie[0]); close(canalSortie[1]); // -- Creation des handlers de SIGUSR2 // HandlerSIGUSR2 ne doit pas etre interrompu par SIGCHLD struct sigaction actionHandlerUSR2; actionHandlerUSR2.sa_handler = HandlerUSR2; sigemptyset(&actionHandlerUSR2.sa_mask); actionHandlerUSR2.sa_flags = 0; sigaddset(&actionHandlerUSR2.sa_mask, SIGCHLD); // -- Creation des handlers de SIGCHLD struct sigaction actionHandlerCHLD; actionHandlerCHLD.sa_handler = HandlerCHLD; sigemptyset(&actionHandlerCHLD.sa_mask); actionHandlerCHLD.sa_flags = 0; // -- Attachement des segments de memoires partagées ParkingMPPtr =(ParkingMP*) shmat(shmIdParking, NULL, 0); RequeteMPPtr =(RequeteMP*) shmat(shmIdRequete, NULL, 0); // -- Armement des signaux SIGUSR2 et SIGCHILD sigaction(SIGUSR2, &actionHandlerUSR2, NULL); sigaction(SIGCHLD, &actionHandlerCHLD, NULL); // -- Deblocage de SIGCHLD et SIGUSR2 sigset_t listeSignalDebloque; sigemptyset(&listeSignalDebloque); sigaddset(&listeSignalDebloque, SIGUSR2); sigaddset(&listeSignalDebloque, SIGCHLD); sigprocmask(SIG_UNBLOCK, &listeSignalDebloque, NULL); // -- MOTEUR -- while(true) { Voiture voitRecue; pid_t pidVoiturier; // On attend qu'une voiture arrive et on lui affecte son heure d'arrivee while(read(canalEntree[numBarriere][0], &voitRecue , sizeof(Voiture) ) == -1 && errno == EINTR ) ; time_t heureArrivee = (time(NULL)) % TEMPS_MAX; voitRecue.dateArrive = heureArrivee; // -- Quand une voiture arrive a une barriere // On dessine la voiture a la barriere DessinerVoitureBarriere(typeEntree, voitRecue.usager); // On recupere le semaphore de Requete while(semop(semId, decrSemRequete, 1) == -1 && errno == EINTR); // Si y a de une place de libre on gare la voiture, sinon on emet une requete et on attend qu'une place ce libere if(RequeteMPPtr->nbPlacesOccupees < NB_PLACES ) { RequeteMPPtr->nbPlacesOccupees++; semop(semId, incrSemRequete, 1); pidVoiturier = GarerVoiture(typeEntree); } else { RequeteMPPtr->requetes[numBarriere].voiture = voitRecue; RequeteMPPtr->requetes[numBarriere].barriere = typeEntree; AfficherRequete(typeEntree, voitRecue.usager, heureArrivee); semop(semId, incrSemRequete, 1); while(semop(semId, decrSemEntree, 1) == -1 && errno == EINTR); pidVoiturier = GarerVoiture(typeEntree); sleep(TEMPO); } // on garde le pid du Voiturier struct pidVoiture mapPidVoiture = {pidVoiturier, voitRecue}; listeFils.push_back(mapPidVoiture); } }
void Entree(TypeBarriere typeBarriere) { //definition des id d'acces au boites aux lettres et semaphores long msgBufEntreeId; long msgbufRequeteId; unsigned short semElementSyncEntree; TypeZone zoneEcranRequete; switch (typeBarriere) { case PROF_BLAISE_PASCAL : //deja initialises aux bonnes valeurs; msgBufEntreeId = MSGBUF_ID_ENTREE_P; msgbufRequeteId = MSGBUF_ID_REQUETE_P; semElementSyncEntree = SEMELM_SINC_ENTREE_P; zoneEcranRequete = REQUETE_R1; break; case AUTRE_BLAISE_PASCAL : msgBufEntreeId = MSGBUF_ID_ENTREE_A; msgbufRequeteId = MSGBUF_ID_REQUETE_A; semElementSyncEntree = SEMELM_SINC_ENTREE_A; zoneEcranRequete = REQUETE_R2; break; case ENTREE_GASTON_BERGER : msgBufEntreeId = MSGBUF_ID_ENTREE_GB; msgbufRequeteId = MSGBUF_ID_REQUETE_GB; semElementSyncEntree = SEMELM_SINC_ENTREE_GB; zoneEcranRequete = REQUETE_R3; break; default : std::cerr << "not an entry process error" << std::endl; return; break; } //initialisation init(); //phase moteur pid_t pidCurr; Voiture voiture; for(;;) { //appel bloquant, attente d'une demande d'entree if(msgrcv(msgbuffId, &voiture, sizeof(Voiture)-sizeof(long), msgBufEntreeId, 0) == -1) continue; // sarestart (sur les erreurs aussi) DessinerVoitureBarriere(typeBarriere, voiture.typeUsager); if(semVal(SEMELM_PLACEDISPO) > 0) { if((pidCurr = GarerVoiture(typeBarriere)) != -1) { semP(SEMELM_PLACEDISPO); mapVoiturier.insert(std::pair<pid_t, Voiture>(pidCurr, voiture)); } } else { //affiche requete AfficherRequete(typeBarriere,voiture.typeUsager,voiture.heureArrivee); Requete re; re.type = msgbufRequeteId; re.heureArrivee = voiture.heureArrivee; re.typeUsager = voiture.typeUsager; if(msgsnd(msgbuffId, &re, sizeof(Requete)-sizeof(long), 0 )==-1); semP(semElementSyncEntree); if((pidCurr = GarerVoiture(typeBarriere)) != -1) { //met à jour l'heure d'entree dans le parking voiture.heureArrivee = time(NULL); mapVoiturier.insert(std::pair<pid_t, Voiture>(pidCurr, voiture)); } Effacer(zoneEcranRequete); } } }