int parallelize_with_pipes(int numProcesses, int** A, int color) { // manages the critical section (printing) using pipes // see report for algorithm/reasoning pid_t this_pid; int turn_pipe[2]; // first pipe parent -> children int confirm_pipe[2]; // second pipe children -> parent int current_turn; // for turn_pipe int confirm_message; // for confirm_pipe int i; pipe(turn_pipe); pipe(confirm_pipe); switch (this_pid = fork()) { case -1: perror("fork() failure"); break; case 0: // children processes close(confirm_pipe[0]); // only need to write to this do_pipes(numProcesses, 0, 0, A, color, turn_pipe, confirm_pipe); exit(0); break; default: close(confirm_pipe[1]); // only reads close(turn_pipe[0]); // only writes (children do both) // parent process handles the turns current_turn = 0; while (current_turn < numProcesses) { // tell children whose turn it is to print write(turn_pipe[1], ¤t_turn, sizeof(current_turn)); // wait for confirmation that that child has printed read(confirm_pipe[0], &confirm_message, sizeof(confirm_message)); if (confirm_message == current_turn) { current_turn++; // advance turn } // continue } // now all N processes have printed, exit break; } return 0; }
pid_t execute_and_distrib(t_shell *sh, t_command *c) { pid_t child; pid_t child2; int pip[2][2]; int pip_sh[2][2]; do_pipes(pip, pip_sh); child = my_fork(); if (!child) { execute_all(sh, c, pip_sh, pip); handle_error_messages(sh); return (quit(sh, sh->last_status)); } else { prepa_exec(sh, c, pip_sh, pip); child2 = distrib_and_send(sh, c, pip[0][0], pip[1][0]); wait_exec(child2, pip); return (child); } }
int do_pipes(int numProcesses, int level, int childNum, int** A, int color, int turn_pipe[2], int confirm_pipe[2]) { // child processes for pipe implementation // see report for pseudocode algorithm and reasoning // as this is a full binary tree, there are 2^level children int totalChildren = 1 << level; if (numProcesses <= totalChildren) { // compute filter int xStart = childNum * X / numProcesses; // start row int xEnd = (childNum + 1) * (X - 1) / numProcesses; // end row // run filter on just these rows colorFilter(A, xStart, xEnd, 0, Y-1, color); // rows // now this process waits until its turn to print is sent via turn_pipe int current_turn, confirm_message; while(1){ // loop indefinitely until its turn is over read(turn_pipe[0], ¤t_turn, sizeof(current_turn)); if (current_turn == childNum){ // it is this child's turn to print printf("Doing process %0.2d of %d.\n", childNum, numProcesses-1); printImage(A, xStart, xEnd, 0, Y-1); // send confirmation message to tell parent that it's done printing confirm_message = current_turn; write(confirm_pipe[1], &confirm_message, sizeof(confirm_message)); // now stop waiting to process/print as we are done break; } // write back turn for the next process to read write(turn_pipe[1], ¤t_turn, sizeof(current_turn)); } } else { // have not forked enough to create the necessary number of children // in our binary tree, so fork this process and recurse pid_t this_pid; int result; switch (this_pid = fork()) { case -1: perror("fork() failure"); exit(-1); break; case 0: // this is the child do_pipes(numProcesses, level + 1, childNum * 2, A, color, turn_pipe, confirm_pipe); break; default: // parent do_pipes(numProcesses, level + 1, childNum * 2 + 1, A, color, turn_pipe, confirm_pipe); break; } } wait(NULL); // reliquish control until all children have printed and have died return 0; }