Esempio n. 1
0
void *hydrogen_routine(void *arg) {
    thread_data *t_data = (thread_data *)arg;
    int thread_id = t_data->t_id;

    // acquire lock on mutex before accessing shared memory
    semwait(&mutex);

    // if enough C is waiting, continue past barrier
    printf("HYDROGEN %d reached barrier.\n", thread_id);
    if (waiting_h >= 3 && waiting_c >= 1) {
        printf("~~~~ Crossed barrier, created a Methane!\n\n");
        // release 4 H
        int i;
        for(i = 0; i < 3; i++) {
            semsignal(&sem_h);
        }
        waiting_h -= 3;
        semsignal(&sem_c);
        waiting_c--;
        // release lock on mutex
        semsignal(&mutex);
    }
    else {
        // not enough H or C is waiting, so wait at barrier
        waiting_h++;
        printf("Waiting Atoms -- C: %d | H: %d\n", waiting_c, waiting_h);
        // release lock on mutex
        semsignal(&mutex);
        semwait(&sem_h);
    }

    pthread_exit(EXIT_SUCCESS);

}
Esempio n. 2
0
static void semwait(int sem)
{
    struct sembuf sbuf = { .sem_num = 0, .sem_op = -1, .sem_flg = 0 };
    assert (semop(sem, &sbuf, 1) != -1);
}

static void semsignal(int sem)
{
    struct sembuf sbuf = { .sem_num = 0, .sem_op = 1, .sem_flg = 0 };
    assert (semop(sem, &sbuf, 1) != -1);
}

static pid_t fork_generator(
    int sem_labyrinth, int shm_stats, int shm_labyrinth, int top_x, int top_y,
    int left_x, int left_y
)
{
    pid_t child = fork();
    if (child != 0) { // Parent
        assert (child != -1);
        return child;
    } else // Child
        exit(generator(
            sem_labyrinth, shm_stats, shm_labyrinth, top_x, top_y, 
            left_x, left_y)
        );
}

// Retourne la cellule qui partage le même mur.
static CELL *cell_fellow(CELL *cell, WALL orientation);

// Retourne l'orientation opposée d'un mur
static WALL orientation_inv(WALL orientation);

// Vérifie que certains murs privés ne partagent pas à présent les mêmes groupes
// ou qu'ils ne sont pas devenus partagés lorsque on a lié les deux groupes.
static void update_private(
    LABYRINTH labyrinth, CELL walls[], int *last_private, int *first_shared
);

static int generator(
    int sem_labyrinth, int shm_stats, int shm_labyrinth, int top_x, int top_y,
    int left_x, int left_y
)
{
    int size = LABYRINTH_SIZE / 2;

    // Récupère les mémoires partagées.
    PARAL_STATS *stats = (PARAL_STATS *) shmat(shm_stats, NULL, 0);
    assert (stats != (PARAL_STATS *) -1);
    LABYRINTH labyrinth = (LABYRINTH) shmat(shm_labyrinth, NULL, 0);
    assert (labyrinth != (LABYRINTH) -1);

    // Retiens les murs non ouverts dans la zone du générateur (indice de la
    // cellule avec orientation du mur, utilise les bits dédiés au groupe
    // pour encoder l'indice).
    // Ajoute les murs non partagés à partir de la gauche et ceux partagés à
    // partir de la droite du vecteur.
    int n_walls = 2 * size * size;
    int last_private = -1
      , first_shared = n_walls;
    CELL walls[n_walls];

    semwait(sem_labyrinth); // Accède en lecture à des cellules partagées.
    for (int i = 0; i < size; i++) {
        for (int j = 0; j < size; j++) {
            int top_index  = (top_y + i)  * LABYRINTH_SIZE + top_x + j
              , left_index = (left_y + i) * LABYRINTH_SIZE + left_x + j;

            CELL *top_cell  = labyrinth + top_index
               , *left_cell = labyrinth + left_index;

            CELL top_fellow  = *cell_fellow(top_cell, WALL_TOP)
               , left_fellow = *cell_fellow(left_cell, WALL_LEFT);

            // Ajoute les murs sur des cases partagées à droite, les autres
            // à gauche.

            if (is_shared(*top_cell) && is_shared(top_fellow))
                walls[--first_shared] = WALL_TOP | (CELL) top_index;
            else
                walls[++last_private] = WALL_TOP | (CELL) top_index;

            if (is_shared(*left_cell) && is_shared(left_fellow))
                walls[--first_shared] = WALL_LEFT | (CELL) left_index;
            else
                walls[++last_private] = WALL_LEFT | (CELL) left_index;
        }
    }
    semsignal(sem_labyrinth);

    // Boucle tant qu'il reste des murs à supprimer.
    for (;;) {
        semwait(sem_labyrinth);

        // Vérifie que les murs partagés n'ont pas été supprimés par un autre
        // processus et qu'ils départagent toujours deux groupes différents.
        for (int i = n_walls - 1; i >= first_shared; i--) {
            CELL wall = walls[i];
            CELL index = wall & GROUP_MASK;
            WALL orientation = wall & WALLS_MASK;
            CELL *cell1 = labyrinth + index;
            CELL *cell2 = cell_fellow(cell1, orientation);

            bool can_be_removed =
                   is_wall(*cell1, orientation)
                && cell_root(labyrinth, cell1) != cell_root(labyrinth, cell2);

            if (!can_be_removed) // Ne peut plus supprimer ce mur.
                walls[i++] = walls[first_shared++];
        }

        // Sélectionne au hasard un mur dans les murs restants.
        int n_remaining = (last_private + 1) + (n_walls - first_shared);
        if (n_remaining == 0) {
            semsignal(sem_labyrinth);
            break;
        }
        int random_index = rand() % n_remaining;

        if (random_index <= last_private) {
            stats->hits++;
            semsignal(sem_labyrinth);

            // Cette partie de l'algorithme peut s'effectuer en même temps sur
            // différents processus :

            CELL wall = walls[random_index];
            CELL index = wall & GROUP_MASK;
            WALL orientation = wall & WALLS_MASK;
            CELL *cell1 = labyrinth + index;
            CELL *cell2 = cell_fellow(cell1, orientation);
            CELL *root1 = cell_root(labyrinth, cell1)
               , *root2 = cell_root(labyrinth, cell2);

            // Attache toujours une cellule qui n'appartient pas à un groupe
            // partagé à l'autre cellule. De cette manière, la racine d'un
            // groupe dont au moins une cellule est partagée sera une cellule
            // partagée. Ceci évite également de modifier une forêt qui pourrait
            // être modifiée par un autre processus au même moment.
            if (is_shared(*root1))
                cell_attach_group(root2, *root1);
            else
                cell_attach_group(root1, *root2);
            // Supprime le mur de la liste d'attente et des deux cellules.
            walls[random_index] = walls[last_private--];

            // Ces deux instructions sont équivalentes à ces deux instructions:
            // *cell1 &= ~orientation;
            // *cell2 &= ~orientation_inv(orientation);
            // A l'exception que le compilateur garantit que ces instructions
            // s'exécutent de manière atomique, et permet ainsi d'éviter que 
            // deux processus suppriment deux murs différents d'une même cellule
            // au même instant, ce qui engendrait une perte de l'une des deux
            // modifications.
            __sync_fetch_and_and(cell1, ~orientation);
            __sync_fetch_and_and(cell2, ~orientation_inv(orientation));
            // Une alternative aurait été d'acquérir la sémaphore sem_labyrinth
            // lorsque l'on change l'orientation d'une cellule qui est sur un
            // bord de la zone du générateur, mais cette méthode est
            // considérablement plus rapide.

            update_private(labyrinth, walls, &last_private, &first_shared);
        } else {
            stats->misses++;

            int wall_index = random_index - (last_private + 1) + first_shared;
            CELL wall = walls[wall_index];
            CELL index = wall & GROUP_MASK;
            WALL orientation = wall & WALLS_MASK;
            CELL *cell1 = labyrinth + index;
            CELL *cell2 = cell_fellow(cell1, orientation);
            CELL *root1 = cell_root(labyrinth, cell1);

            cell_attach_group(root1, *cell2);

            // Supprime le mur de la liste d'attente et des deux cellules.
            walls[wall_index] = walls[first_shared++];
            *cell1 &= ~orientation;
            *cell2 &= ~orientation_inv(orientation);

            semsignal(sem_labyrinth);
        }
    }
    return EXIT_SUCCESS;
}
Esempio n. 3
0
void * recepcionista_S(void *args)
{
	Cliente cli_ready;
	
	while(feito == 0)		// enquanto estiver em funcionamento
	{
		
		if(work == 2){		// quando receber ordem de fecho avisa os clientes que o carro nao esta pronto
			if(!IsEmpty(Qmec)){
				pthread_mutex_lock(&mutexDone);
				cli_ready = FrontAndDequeue(Qmec);
				pthread_mutex_unlock(&mutexDone);
				
				//informar o cliente que o carro não está terminado
				pthread_mutex_lock(&mutexRegis);
				regista(RECEPS, cli_ready.matricula, "Vou despachar o cliente com um SIGUSR2");
				pthread_mutex_unlock(&mutexRegis);
				kill(cli_ready.id, SIGUSR2);//enviado o sinal que o carro nao esta pronto
			}

			if(!IsEmpty(Qele)){
				pthread_mutex_lock(&mutexDone);
				cli_ready = FrontAndDequeue(Qele);
				pthread_mutex_unlock(&mutexDone);
				
				//informar o cliente que o carro não está terminado
				pthread_mutex_lock(&mutexRegis);
				regista(RECEPS, cli_ready.matricula, "Vou despachar o cliente com um SIGUSR2");
				pthread_mutex_unlock(&mutexRegis);
				kill(cli_ready.id, SIGUSR2);//enviado o sinal que o carro nao esta pronto
			}

			if(!IsEmpty(Qcha)){
				pthread_mutex_lock(&mutexDone);
				cli_ready = FrontAndDequeue(Qcha);
				pthread_mutex_unlock(&mutexDone);
				
				//informar o cliente que o carro não está terminado
				pthread_mutex_lock(&mutexRegis);
				regista(RECEPS, cli_ready.matricula, "Vou despachar o cliente com um SIGUSR2");
				pthread_mutex_unlock(&mutexRegis);
				kill(cli_ready.id, SIGUSR2);//enviado o sinal que o carro nao esta pronto
			}

			if(!IsEmpty(Qpin)){
				pthread_mutex_lock(&mutexDone);
				cli_ready = FrontAndDequeue(Qpin);
				pthread_mutex_unlock(&mutexDone);
				
				//informar o cliente que o carro não está terminado
				pthread_mutex_lock(&mutexRegis);
				regista(RECEPS, cli_ready.matricula, "Vou despachar o cliente com um SIGUSR2");
				pthread_mutex_unlock(&mutexRegis);
				kill(cli_ready.id, SIGUSR2);//enviado o sinal que o carro nao esta pronto
			}		
		}
		
		if(!IsEmpty(Qdone)){	// se tiver veiculos prontos
			pthread_mutex_lock(&mutexDone);
			cli_ready = FrontAndDequeue(Qdone);
			pthread_mutex_unlock(&mutexDone);
			
			//meter no parque
			pointer[posicao] = cli_ready;
			posicao++;
			
			//informar o cliente que o carro está no parque (pointer)
			pthread_mutex_lock(&mutexRegis);
			regista(RECEPS, cli_ready.matricula, "Vou despachar o cliente com um SIGUSR1");
			pthread_mutex_unlock(&mutexRegis);
			kill(cli_ready.id, SIGUSR1);		//enviado o sinal para tirar o carro do parque
			
			//Vou aguardar que o cliente retire o carro do parque
			semwait(semid);
		}
		else
		{
			if (work == 2) feito = 1;	// se passar da hora de fecho e todos os veiculos prontos tiverem sido levantados, nao espera mais!
		}
		
	}
	
	pthread_mutex_lock(&mutexRegis);
	regista(RECEPS,NULL,"Boa tarde chefe e ate amanha!");
	pthread_mutex_unlock(&mutexRegis);
	return NULL;
}
Esempio n. 4
0
int main(int argc, char** argv)
{
  printf("bus %s started\n", argv[1]);
  fflush(stdout);

  int semid, shmid;
  struct Common* shared;

  semid = semget(getSemKey(), NUM_SEMS, 0777);
  shmid = shmget(getSemKey(), 0, 0);
  shared = (struct Common *)shmat(shmid, 0, 0);

  semwait(semid, SEM_GATE_EMPTY);
  printf("Bus %s has arrived\n", argv[1]);
  fflush(stdout);

  semsignal(semid, SEM_BUS_BOARDABLE);

  semwait(semid, SEM_MUTEX);
  time_t sleep_time = shared->departure_time - time(NULL);
  semsignal(semid, SEM_MUTEX);

  printf("Bus %s Sleeping until departure\n", argv[1]);
  fflush(stdout);
  sleep(sleep_time);

  semwait(semid, SEM_MUTEX);
  printf("Bus %s: last call for boarding\n", argv[1]);
  fflush(stdout);
  while(1)
  {
	  semwait(semid, SEM_CAN_BOARD);
	  if(shared->tickets_sold == shared->boarded)
	  {
		  semsignal(semid, SEM_CAN_BOARD);
		  break;
	  }
	  semsignal(semid, SEM_CAN_BOARD);
	  // wait another second to give customer
	  // threads a chance to finish boarding
	  sleep(1);
  }

  semwait(semid, SEM_BUS_BOARDABLE);

  // release passengers to the gate that were waiting for the next bus
  printf("Bus %s releasing next bus queue\n", argv[1]);
  fflush(stdout);
  int i;
  for(i=0; i<shared->next_bus_tickets; i++)
  {
	  semsignal(semid, SEM_NEXT_BUS_QUEUE);
  }

  // reset the ticket variables for the next bus
  printf("Bus %s preparing shared variables for next bus\n", argv[1]);
  fflush(stdout);
  // if there were customers waiting for the next, next bus or beyond
  // release some of them
  for(i=0; i<shared->tickets_sold; i++)
  {
	  semsignal(semid, SEM_MAX_CUSTOMERS);
  }
  shared->tickets_sold = shared->next_bus_tickets;
  shared->next_bus_tickets = 0;
  shared->departure_time += BUS_PERIOD;
  shared->boarded = 0;
  semsignal(semid, SEM_MUTEX);

  semsignal(semid, SEM_GATE_EMPTY);

  printf("Bus %s is departing\n", argv[1]);
  fflush(stdout);
  return 0;
}