void *run_thread(void *args) { arg_t *run_args = (arg_t *)args; while(1) { if (queue_size(run_args->ready_r) == 0 && queue_size(run_args->rest_r) == 0) { return NULL; } sem_wait(run_args->ready_sem); while(queue_size(run_args->ready_r) == 0) { if (queue_size(run_args->ready_r) == 0 && queue_size(run_args->rest_r) == 0) { sem_post(run_args->ready_sem); return NULL; } sem_wait(run_args->ready_sem); } rule_t *rule; pthread_mutex_lock(run_args->m); rule = queue_dequeue(run_args->ready_r); pthread_mutex_unlock(run_args->m); while(queue_size(rule->commands)) { char *command = queue_dequeue(rule->commands); if (system(command) != 0) { exit(1); } free(command); } char *temp = rule->target; while(queue_size(rule->deps)) { char *dep = queue_dequeue(rule->deps); free(dep); } rule_destroy(rule); free(rule); pthread_mutex_lock(run_args->m); int pSize = queue_size(run_args->ready_r); queue_enqueue(run_args->complete_t, temp); process_queues(run_args->rest_r, run_args->ready_r, run_args->complete_t); int cSize = queue_size(run_args->ready_r); pthread_mutex_unlock(run_args->m); int i; for(i = 0; i < cSize - pSize; i++) { sem_post(run_args->ready_sem); } sem_post(run_args->ready_sem); } }
/** * Connects queue_iterate interface to free with rule_destroy call. * * @param arg Address to be freed. * @param trash do NOT use. * @return Void. */ static void rule_free_adapter(void *arg, void *trash){ rule_t *rule = arg; queue_iterate(rule->deps, free_adapter, 0); queue_iterate(rule->commands, free_adapter, 0); free(rule->target); rule_destroy(arg); free(arg); }
/** * Entry point to parmake. */ int main(int argc, char **argv) { int threads=1; //working threads, additional to main thread char *fname=0; //makefile name char temp=0; //used for whatever char **targets=NULL; //targets array int targetsGiven=0; //targets count queue_init(rules); //queue initialized queue_init(nextRule); //queue initialized queue_init(rulesDup); //queue initialized pthread_t *tid=NULL; //array of thread IDs int i; //loop iterator variable result_t *dummy=NULL; //dummy variable, just in case sem_init(&ruleAvailable, 0, 0); //semaphore initialized lock=PTHREAD_MUTEX_INITIALIZER; //mutex initialized /*threadAvailable*/ //semaphore initialized (later) //part1 while ((temp = getopt(argc, argv, "f:j:")) != -1) { if(temp=='f') { fname=optarg; } else if(temp=='j') { if(optarg!=0) threads=atoi(optarg); } else //Use of option other than f and j { return -1; //unspecified, so I just did same thing as no make file } //I hate having multiple returns, but its faster for now } if(fname==0) { if(access("./makefile", F_OK)==0) fname="./makefile"; else if(access("./Makefile", F_OK)==0) fname="./Makefile"; else return -1; //I hate having multiple returns, but its faster for now } targetsGiven=argc-optind; if(targetsGiven) { targets=malloc((targetsGiven+1)*sizeof(char*)); for(i=0; i<targetsGiven; i++) { targets[i]=argv[optind+i]; } targets[targetsGiven]=NULL; } //part 2 parser_parse_makefile(fname, targets, parsed_new_target, parsed_new_dependency, parsed_new_command); //part 3 and 4 tid=malloc(threads*sizeof(pthread_t)); sem_init(&threadAvailable, 0, threads); for(i=0; i<threads; i++) pthread_create(&tid[i], NULL, runRule, NULL); while(queue_size(rules)) { i=-1; int found=0; rule_t *temp=NULL; while(i<numRules && !found)//numRules is a formality, should always be found { i++; temp=queue_at(q, i); found=1; if(queue_size(temp->deps)!=0) { int j; int k; for(j=0; j<queue_size(rulesDup); j++) { for(k=0; k<queue_size(temp->deps); k++) { if(strcmp(queue_at(temp->deps, k), queue_at(rulesDup, j)->target)==0) { found=0; } } } } } sem_wait(&threadAvailable); pthread_mutex_lock(&lock); //CRITICAL SECTION queue_remove_at(rules, i); queue_enqueue(nextRule, temp); //END CRITICAL SECTION pthread_mutex_unlock(&lock); sem_post(&ruleAvailable); } //set up kickers for threads stuck in wait. Won't always be needed for(i=0; i<threads; i++) { pthread_mutex_lock(&lock); //CRITICAL SECTION queue_enqueue(nextRule, NULL); //END CRITICAL SECTION pthread_mutex_unlock(&lock); sem_post(&ruleAvailable);//waking up waiting threads to kick them } //wait for threads to finish for(i=0; i<threads; i++) { pthread_join(tid[i], (void**)&dummy); } while(queue_size(rulesDup)) { rule_t *temp=queue_dequeue(rulesDup); rule_destroy(temp); free(temp); } queue_destroy(rules); queue_destroy(nextRule); sem_destroy(&threadAvailable); sem_destroy(&ruleAvailable); pthread_mutex_destroy(&lock); if(targetsGiven) { free(targets); } free(tid); return 0; }
void process_queues(queue_t *rest_r, queue_t *ready_r, queue_t *complete_t) { int i = 0; while(i < queue_size(rest_r)) { int satify = 1; int dependR = 0; rule_t *rule = queue_at(rest_r, i); int j; for (j = 0; j < queue_size(rule->deps); j++) { char *dep = queue_at(rule->deps, j); int complete = 0; if (isRule(dep)) { int k; for (k = 0; k < queue_size(complete_t); k++) { char *target = queue_at(complete_t, k); if (strcmp(dep, target) == 0) { dependR = 1; complete = 1; break; } } } else { if (access(dep, R_OK) == 0) { complete = 1; } else { fprintf(stderr,"dependency file does not exist!"); exit(1); } } if (!complete) { satify = 0; break; } } if (satify) { if (dependR) { queue_enqueue(ready_r, rule); queue_remove_at(rest_r, i); } else { if (access(rule->target, R_OK) == -1) { queue_enqueue(ready_r, rule); queue_remove_at(rest_r, i); } else { struct stat statbuf; stat(rule->target, &statbuf); time_t rule_time = statbuf.st_mtime; int run = 0; int j; for (j = 0; j < queue_size(rule->deps); j++) { char *dep = queue_at(rule->deps, j); stat(dep, &statbuf); time_t dep_time = statbuf.st_mtime; if (dep_time > rule_time) { run = 1; queue_enqueue(ready_r, rule); queue_remove_at(rest_r, i); break; } } if (!run) { queue_remove_at(rest_r, i); queue_enqueue(complete_t, rule->target); while(queue_size(rule->deps)) { char *dep = queue_dequeue(rule->deps); free(dep); } while(queue_size(rule->commands)) { char *command = queue_dequeue(rule->commands); free(command); } rule_destroy(rule); free(rule); } } } } else { i++; } } }
int main(int argc, char **argv) { remain_size =0; /** PART 1 STARTS **/ int opt; char *makefile= NULL; int num_threads=1; while ((opt = getopt(argc, argv, "f:j:")) != -1) { switch(opt){ case 'f' : makefile = optarg; break; case 'j' : num_threads = atoi( optarg ); break; default : return 0; } } int i ; int ind; int num = 0; char ** targets = malloc( (argc - optind +1 ) * sizeof( char* ) ); //not argc - optind + 1 if ( optind <= argc ){ for( i = 0,ind = optind ; i< argc -optind; i++ , ind++ ){ targets[i] = malloc( 100 ) ; strcpy ( targets[i] , argv[ind] ); num++; } targets[num] = NULL; } char * buffer = NULL; if( makefile == NULL ){ if (access("./makefile",F_OK) == 0 ){ strcpy(buffer, "./makefile"); makefile = buffer; } else if ( access("./Makefile",F_OK) == 0) { strcpy(buffer, "./Makefile"); makefile = buffer; } else return -1; } else{ if(access(makefile,F_OK) == -1) return -1; } /** PART 1 ENDS **/ /** PART 2 STARTS **/ queue_init(&q); parser_parse_makefile( makefile , targets , parsed_new_target, parsed_new_dependency, parsed_new_command ); /** PART 2 ENDS **/ /** PART 3 STARTS **/ /* int m,n; rule_t * hold3; char * hold4,hold5; printf("printing the queue of rules\n"); for(m=0;m<queue_size(&q);m++){ hold3 = queue_at (&q,m); printf("target %s : deps ",hold3->target); for(n=0;n<queue_size(hold3->deps);n++){ hold4 = queue_at(hold3->deps,n); printf ("%s ",hold4); } printf("commands "); for(n=0;n<queue_size(hold3->commands);n++){ hold4 = queue_at(hold3->commands,n); printf ("%s ",hold4); } printf("\n"); } exit(1);*/ queue_init(&has_ran); queue_init(&depend); add_deps(); int no_dep=0; for(i=0;i<queue_size(&q);i++) if(has_deps((rule_t*)queue_at(&q,i))==0) no_dep++; //printf("NUMBER of rules with no deps, initialy %d\n",no_dep); /** PARALELLIZATION **/ pthread_t* threads = malloc(sizeof(pthread_t)*num_threads); sem_init(&sem_mutex1, 0, no_dep); for(i=0;i<num_threads;i++) { pthread_create(&threads[i],NULL,start_run,NULL); } for(i=0;i<num_threads;i++) { pthread_join(threads[i],NULL); } sem_destroy(&sem_mutex1); /** FREEING STUFF **/ free(threads); // start_run(NULL); rule_t * rule_hold = NULL; int k; char * hold2 = NULL; for(i=0;i<queue_size(&q);i++){ rule_hold = queue_at(&q,i); for(k=0;k<queue_size(rule_hold->deps);k++) { hold2 = queue_at(rule_hold->deps,k); if(in_depend(hold2)==0) free(hold2); } for(k=0;k<queue_size(rule_hold->commands);k++) { hold2 = queue_at(rule_hold->commands,k); free(hold2); } free(rule_hold->target); rule_destroy(rule_hold); free(rule_hold) ; } queue_destroy(&q); for(i=0;i<queue_size(&depend);i++) { hold2 = queue_at(&depend,i); free(hold2); } queue_destroy(&depend); queue_destroy(&has_ran); for( i = 0; i< argc - optind; i++ ){ free(targets[i]); } free(targets); return 0; }