void add_item_to_correct_queue(queue_element_t * element, queue_t * glb_file_queue, queue_t * glb_dir_queue)
{
	int status;
	//Find out if this is a file or a directory
	struct stat file_stats;
	// Obtain information about the file pointed to by path_name
	status = lstat(element->path_name, &file_stats); 
	if(status == -1){
			printf("Error obtaining stats for %s \n", element->path_name);
			free((void *)element);
			return;
	}
	// Check if the file is a symbolic link; if so ignore it
	if(S_ISLNK(file_stats.st_mode))
	{
	}
	//Is a dir?
	else if(S_ISDIR(file_stats.st_mode))
	{
		//Add this element to dir queue
		insert_in_queue(glb_dir_queue,element);
	}
	//Reg file?
	else if(S_ISREG(file_stats.st_mode))
	{ 
		insert_in_queue(glb_file_queue,element);
	}
	else
	{
		printf("Unsure what to do with: %s \n", element->path_name);
	}
}
Пример #2
0
//|| defined (POK_NEEDS_PORTS_QUEUEING) || defined (POK_NEEDS_PORTS_SAMPLING)
void pok_sched_unlock_thread (const uint32_t thread_id)
{
 #ifdef POK_NEEDS_SCHED_O1
	uint32_t thread_pos = thread_id;
	if (pok_threads[thread_pos].state != POK_STATE_LOCK)
	{
#ifdef POK_NEEDS_DEBUG
		printf("WARNING: Invoked UNLOCK on non-locked thread\n");
#endif
	}
	pok_threads[thread_pos].state = POK_STATE_RUNNABLE;
	POK_CURRENT_PARTITION.runnables |= (1 << (thread_pos - POK_CURRENT_PARTITION.thread_index_low));
  #ifdef POK_NEEDS_DEBUG_O1
	printf("[DEBUG_O1]\t Invoked UNLOCK on thread %u in position %u\n", 
		pok_threads[thread_id].id,
		thread_pos);
  #endif
 #else /* ! POK_NEEDS_SCHED_O1 */
	pok_threads[thread_id].state = POK_STATE_RUNNABLE;
  #ifdef POK_NEEDS_SCHED_FPPS	
	// We just insert it in the ready queue
	insert_in_queue(POK_SCHED_CURRENT_PARTITION,&pok_threads[thread_id]);
  #endif
 #endif
}
Пример #3
0
int Resource::seize(Arrival* arrival, int amount) {
  int status;
  // serve now
  if (room_in_server(amount, arrival->order.get_priority())) {
    if (arrival->is_monitored()) {
      arrival->set_start(this->name, sim->now());
      arrival->set_activity(this->name, sim->now());
    }
    insert_in_server(sim->verbose, sim->now(), arrival, amount);
    status = SUCCESS;
  }
  // enqueue
  else if (room_in_queue(amount, arrival->order.get_priority())) {
    if (arrival->is_monitored()) {
      arrival->set_start(this->name, sim->now());
      arrival->set_activity(this->name, 0);
    }
    insert_in_queue(sim->verbose, sim->now(), arrival, amount);
    status = ENQUEUED;
  }
  // reject
  else {
    if (sim->verbose) verbose_print(sim->now(), arrival->name, "REJECT");
    return REJECTED;
  }
  
  if (is_monitored()) observe(sim->now());
  return status;
}
//Given a queue try to pull some items off
//Let's abuse the things we were given
//Use the queue as a list, order doesn't matter. Why rewrite code;
//Return queue of strings, and the number of items in there
queue_t * get_items(queue_t * queue, unsigned int num_items, unsigned int * num_returned)
{
	//Allocate a queue
	queue_t * ret_queue = create_queue();
	
	//Remove elements until reaching null or the number requested
	*num_returned = 0;
	#pragma omp critical
	{
		while(1)
		{
			//Try to remove an item
			queue_element_t * item = remove_from_queue(queue);
			if(item == NULL)
			{
				break;
			}
			
			//Add this item to the queue
			insert_in_queue(ret_queue, item);
			*num_returned = *num_returned +1;
			
			if(*num_returned >=num_items)
			{
				break;
			}
		}
	}
	
	
	//printf("Got %u/%u from queue\n", *num_returned, num_items);
	
	return ret_queue;
}
//Another layer of help for putting strings on the queue
void place_in_queue(queue_t *queue, char * str)
{
	  queue_element_t * element = (queue_element_t *)malloc(sizeof(queue_element_t));
	  if(element == NULL){
				 printf("Error allocating memory. Exiting. \n");
				 exit(-1);
	  }
	  strcpy(element->path_name, str);
	  element->next = NULL;
	  insert_in_queue(queue, element);
}
Пример #6
0
int Resource::seize(Arrival* arrival, int amount) {
  int status;
  // serve now
  if (room_in_server(amount, arrival->order.get_priority())) {
    insert_in_server(sim->verbose, sim->now(), arrival, amount);
    status = SUCCESS;
  }
  // enqueue
  else if (room_in_queue(amount, arrival->order.get_priority())) {
    insert_in_queue(sim->verbose, sim->now(), arrival, amount);
    status = ENQUEUE;
  }
  // reject
  else {
    if (sim->verbose) verbose_print(sim->now(), arrival->name, "REJECT");
    return REJECT;
  }

  arrival->register_entity(this);
  if (is_monitored())
    sim->record_resource(name, server_count, queue_count, capacity, queue_size);
  return status;
}
Пример #7
0
uint32_t pok_elect_thread (pok_partition_t* current_partition, uint64_t now)
{
	// We elect the thread to be executed 
	// initialized to 0 to avoid warnings
	uint32_t 	elected = 0;
#ifdef POK_NEEDS_SCHED_O1
	uint32_t 	moment;
#else
	uint8_t		i;
#endif
   
	// Update of thread state only when the partition is in NORMAL mode
	switch (current_partition->mode)
	{
		case POK_PARTITION_MODE_INIT_COLD:
		case POK_PARTITION_MODE_INIT_WARM:
 #ifdef POK_NEEDS_ERROR_HANDLING
			if ((current_partition->thread_error != 0) &&
				 (pok_threads[current_partition->thread_error].state != POK_STATE_STOPPED))
			{
				elected = current_partition->thread_error;
			}
			else
			{
				elected = current_partition->thread_main;
			}
 #else
			elected = current_partition->thread_main;
 #endif
			break;
		case POK_PARTITION_MODE_NORMAL:
 #ifdef POK_NEEDS_ERROR_HANDLING
			if ((POK_SCHED_CURRENT_THREAD == POK_CURRENT_PARTITION.thread_error) && 
					(POK_CURRENT_THREAD.state == POK_STATE_RUNNABLE))
			{
					elected = POK_CURRENT_PARTITION.thread_error;
					POK_CURRENT_PARTITION.current_thread = elected;
					break;
			}
 #endif
// ********************* O1 SCHEDULER ***********************************************
 #ifdef POK_NEEDS_SCHED_O1
			moment = now - start_of_MAF + 1;
			start_of_MAF_stub = 0;
  #ifdef POK_NEEDS_DEBUG_O1
			printf("[DEBUG_O1]\t Thread switch!\n");
			printf("[DEBUG_O1]\t Now: "); print_long(now); printf("\n");
			printf("[DEBUG_O1]\t Time since start of MAF: %d\n",moment);
  #endif
			pok_partitions[pok_current_partition].runnables |= masks[moment][POK_STATE_RUNNABLE]; 

// *********************************************************************************
 #else /* ! POK_NEEDS SCHED_O1 */
			// Update of thread state only when the partition is in NORMAL mode
			for (i = 0; i < pok_partitions[pok_current_partition].nthreads; i++)
			{
				pok_thread_t* thread = &(pok_threads[current_partition->thread_index_low + i]);
				// No timed_wait or timeout implemented so far
  #if defined (POK_NEEDS_LOCKOBJECTS)
// || defined (POK_NEEDS_PORTS_QUEUEING) || defined (POK_NEEDS_PORTS_SAMPLING)
				if ((thread->state == POK_STATE_WAITING) && (thread->wakeup_time <= now))
				{
					thread->state = POK_STATE_RUNNABLE;
   #ifdef POK_NEEDS_SCHED_FPPS
					insert_in_queue(POK_SCHED_CURRENT_PARTITION,thread);
   #endif
				}
  #endif /* defined (POK_NEEDS_LOCKOBJECTS) */

				if ((thread->next_activation <= now) && (thread->state == POK_STATE_WAIT_NEXT_ACTIVATION))
				{
					thread->state = POK_STATE_RUNNABLE;
					thread->remaining_time_capacity =  thread->time_capacity;
  #ifdef POK_NEEDS_SCHED_FPPS
					insert_in_queue(POK_SCHED_CURRENT_PARTITION,thread);
  #endif
				}
			} // end update loop
 #endif /* POK_NEEDS_SCHED_O1 */
         		elected = POK_CURRENT_PARTITION.sched_func (current_partition->thread_index_low,
                                                     current_partition->thread_index_high);

			/** Update information on partition to be consistent */
			if (elected == IDLE_THREAD)
			{
				pok_threads[IDLE_THREAD].partition = POK_SCHED_CURRENT_PARTITION;
			}

			POK_CURRENT_PARTITION.current_thread = elected;

			// Compute the thread next dealine only if the elected thread is not the main thread or the idle thread
			if ( (elected != IDLE_THREAD) && (elected != POK_CURRENT_PARTITION.thread_main))
			{
				// compute next thread's deadline
				pok_threads[elected].end_time = now + pok_threads[elected].remaining_time_capacity;
   			}
			break;

		default:
			break;
	} // switch on partition mode

	return (elected);
}
Пример #8
0
pok_ret_t pok_partition_set_mode (const uint8_t pid, const pok_partition_mode_t mode)
{
	pok_ret_t ret = POK_ERRNO_OK;
	uint32_t thread_id;
  uint32_t indexLow, indexHigh;

	switch (mode)
	{
		case POK_PARTITION_MODE_NORMAL:
#ifdef POK_NEEDS_DEBUG
   printf ("SET_PARTITON_MODE : partition[%d] MODE = NORMAL  \n", pid );
#endif

			indexLow  = pok_partitions[pid].thread_index_low;
			indexHigh = pok_partitions[pid].thread_index_high;
			// Update the thread states pok_threads in indexLow - indexHigh (excluded)
			for (thread_id = indexLow ; thread_id < indexHigh ; thread_id++)
			{
 #ifdef POK_NEEDS_SCHED_O1_SPLIT
				/* idle thread is always ready in the periodic threads queue */
				pok_partitions[pid].runnables |= (1 << (IDLE_THREAD - pok_partitions[pid].thread_index_low));  
 #endif
				// Check thread is not idle, kernel or (partition main) current thread and each thread belongs to the current partition
				if ((thread_id != IDLE_THREAD) && (thread_id != KERNEL_THREAD) && (thread_id != POK_CURRENT_PARTITION.current_thread)
					&& !pok_thread_is_suspended(pok_threads[thread_id])
					&& pok_threads[thread_id].state == POK_STATE_WAITING) { // the thread has been started

 #ifdef POK_NEEDS_SCHED_O1_SPLIT
					/* if the thread is a successor set its bit in the successor bitmask and 
	 				 * reset its bit in the executed_predecessors bitmask
	 				 */
					if ( ((bool_t[])POK_CONFIG_SUCCESSOR_THREADS)[pok_threads[thread_id].id] == TRUE)
					{
						pok_partitions[pid].successors |= (1 << (pok_threads[thread_id].pos - pok_partitions[pid].thread_index_low));
						pok_partitions[pid].executed_predecessors &= 
									~(1 << (pok_threads[thread_id].pos - pok_partitions[pid].thread_index_low));
					}
					/* if the thread is a predecessor set the bitmask corresponding to its successor in the successors_bitmasks */
					if (((bool_t[])POK_CONFIG_PREDECESSOR_THREADS)[pok_threads[thread_id].id] == TRUE)
					{
						int successor_id = ((int[])POK_CONFIG_SUCCESSORS_ID)[pok_threads[thread_id].id] + pok_partitions[pid].thread_index_low;
						successors_bitmasks[pok_threads[thread_id].id] =
									(1 << (pok_thread_ids_to_pos_map[successor_id] - pok_partitions[pid].thread_index_low));
					}
 #endif /* end ifdef POK_NEEDS_SCHED_O1_SPLIT */

					if (pok_thread_aperiodic(pok_threads[thread_id])){
 #ifdef POK_NEEDS_SCHED_O1
  #ifdef POK_NEEDS_SCHED_O1_SPLIT
						/* set the thread bit in the sporadic_mask bitmask */
						pok_partitions[pid].sporadic_bitmask |= (1 << (pok_threads[thread_id].pos - pok_partitions[pid].thread_index_low));
  #endif
						if(pok_threads[thread_id].timeout != NULL)
							// initiate a time counter with duration DELAY_TIME;
							pok_sched_set_asynch_event(thread_id,
										pok_threads[thread_id].timeout->timer,
										POK_EVENT_DELAYED_START);						
						else
						{
  #ifdef POK_NEEDS_SCHED_O1_SPLIT
							/* insert the thread bitmask in the ready (FIFO) queue;
							 * this because at the beginning all sporadic threads are ready */
							pok_sched_insert_sporadic_in_queue(1 << (pok_threads[thread_id].pos - pok_partitions[pid].thread_index_low));
  #else /* POK_NEEDS_SCHED_O1_SPLIT is not defined */
							// set to READY all previously started (not delayed) aperiodic processes (unless the process was suspended);
							pok_partitions[pid].runnables |= (1 << (pok_threads[thread_id].pos -
												pok_partitions[pok_threads[thread_id].partition].thread_index_low));
  #endif /* end ifdef POK_NEEDS_SCHED_O1_SPLIT */
 #endif /* end ifdef POK_NEEDS_SCHED_O1 */
							pok_threads[thread_id].state = POK_STATE_RUNNABLE;
 #ifdef POK_NEEDS_SCHED_FPPS
							insert_in_queue(POK_SCHED_CURRENT_PARTITION,&pok_threads[thread_id]);
 #endif
 
 #ifdef POK_NEEDS_SCHED_O1
						}
 #endif
					}else{
						// periodic thread
						// set first release points of all previously started (not delayed) periodic processes to 
						// their next partition period;
						// The partition period is unused
						// check if  the next activation is set to the beginning of the next time slot of the partition
						pok_threads[thread_id].next_activation = pok_partitions[pok_threads[thread_id].partition].activation 
								+ get_partition_period(pok_threads[thread_id].partition);
 #ifdef POK_NEEDS_SCHED_O1

						if(pok_threads[thread_id].timeout != NULL)
						{
							pok_threads[thread_id].next_activation += pok_threads[thread_id].timeout->timer;
							pok_sched_set_asynch_event(thread_id,pok_threads[thread_id].next_activation,POK_EVENT_DELAYED_START);
						}
						else
						{
 #endif
							pok_threads[thread_id].state = POK_STATE_WAIT_NEXT_ACTIVATION;
 #ifdef POK_NEEDS_SCHED_O1
							uint32_t the_mask = (1 << (pok_threads[thread_id].pos - pok_partitions[pok_threads[thread_id].partition].thread_index_low));

							uint32_t time, limit, period;
							limit = ((uint32_t)pok_partitions[pok_threads[thread_id].partition].activation) + POK_CONFIG_SCHEDULING_MAJOR_FRAME;
							period = get_partition_period(pok_threads[thread_id].partition);
							for (time =pok_threads[thread_id].next_activation; time <= limit; time += period)
							{
								int position = time % POK_CONFIG_SCHEDULING_MAJOR_FRAME;
								masks[position][POK_STATE_RUNNABLE] |= the_mask;
  #ifdef POK_NEEDS_DEBUG_O1
								printf ("Thread %d will be next activated at %d (= %d + %d * k)\n",
									thread_id, time,
									(int)pok_partitions[pok_threads[thread_id].partition].activation,
									period);
								printf("Adding to mask %d.. %u\n",position,the_mask);
  #endif
							}
						}
 #endif
					}
					// calculate the deadline time of all no dormant processe in the partition
					if (pok_threads[thread_id].state != POK_STATE_STOPPED){
						pok_threads[thread_id].end_time = pok_threads[thread_id].next_activation + pok_threads[thread_id].time_capacity;
					}
				}
			}// end for
	
			// set the partition lock level to 0
			pok_partitions[pid].lock_level = 0;

			// setting the partition mode		
			pok_partitions[pid].mode = mode;

			// stop the calling thread 
			pok_sched_stop_thread(pok_partitions[pid].thread_main);

			// activate the process scheduling
#ifdef POK_NEEDS_SCHED_O1
			pok_sched_end_period();
#else
			pok_sched();
#endif
		
		break;

		default:
			return POK_ERRNO_PARTITION_MODE;
			break;
	} // case

	return ret;
}
Пример #9
0
/**
 * round_robin_algorithm
 *
 * Dado un PLANNER_INPUT, devolvemos un
 * PLANNER_RESULT resultado de aplicar el algoritmo
 * round robin sobre él. Tiene 2 fases:
 *
 * 1f) Introducimos procesos a la cola hasta
 *	que hemos iterado una vez todos los procesos
 * 	y expropiamos debidamente
 *
 * 2f) Dejamos de introducir en la cola elementos
 *	y segumis expropiando
 *
 */
PLANNER_RESULT round_robin_algorithm(PLANNER_INPUT data)
{
	int i=0, j=0;
	PLANNER_RESULT rtemp;

	rtemp.num = data.num;

	float av_return = 0;
	float av_wait = 0;

	PLANNER_INPUT datacopy = data;

	// cuanto actual, obtenido del PLANNER_INPUT
	int current_quantum=data.quant;

	// proceso actual, -1 si no hemos empezamod a introducir
	// procesos en el algoritmo
	int current_process=-1;

	// variable que nos indica si estamos en la segunda
	// fase o no
	int second_phase=0;

	// suma de los servicios, iteraremos sobre este número
	int sum_servicio = sum_planner_data_stime(data);

	// creamos la cola con un número de elementos igual
	// al numero de procesos en total
	int queue[data.num];

	// hay 0 elementos en la cola
	int tot_current = 0;

	for(i; i<=sum_servicio; i++)
	{
		// el algoritmo empieza, planificamos el
		// primer proceso inmediatamente
		if(current_process == -1)
		{
			current_process = 0;
		}
		else
		{
			// en la segunda interación, podemos ya procesar
			data.times[current_process].t_servicio--;

			// restamos una unidad al cuanto
			current_quantum--;

			// si hemos acabado el proceso...
			if(data.times[current_process].t_servicio == 0)
			{
				rtemp.processes[current_process].TF = i+datacopy.idle;

				// ponemos el cuanto a 0 para comprobar a continuación que
				// proceso debemos planificar
				current_quantum = 0;
			}
		}

		// si no estamos en segunda fase, añadimos procesos
		// a la cola
		if(!second_phase)
		{
			if(current_process != i)
			{
				// add to the queue
				insert_in_queue(queue, &tot_current, i);
			}
		}

		// una vez los hemos añadido todos, entramos
		// en segunda fase
		if(i == datacopy.num-1)
		{
			second_phase = 1;
		}

		// expropiamos el proceso si ha terminado su cuanto
		// y si no es la última iteración
		if(current_quantum == 0 && i != sum_servicio)
		{
			// si hay 0 elementos en la cola, no hacemos nada
			if(tot_current != 0)
			{
				// guardamos el proceso actual
				int current_process_temp = current_process;

				// cogemos el primer elemento de la cola
				current_process = get_first_queue(queue, &tot_current);

				// añadimos el proceso a la cola, sólo si su tiempo de servicio
				// aún es mayor de 0
				if(data.times[current_process_temp].t_servicio  != 0)
					insert_in_queue(queue, &tot_current, current_process_temp);
			}

			// reseteamos el cuanto
			current_quantum = data.quant;
		}
	}

	// calculamos TR y TE
	for(i=0; i<data.num; i++)
	{
		rtemp.processes[i].TR = rtemp.processes[i].TF-datacopy.times[i].t_llegada;
		rtemp.processes[i].TE = rtemp.processes[i].TR-datacopy.times[i].t_servicio+datacopy.idle;

		av_return += rtemp.processes[i].TR;
		av_wait += rtemp.processes[i].TE;
	}

	// calculamos las medias
	rtemp.average_return = av_return / rtemp.num;
	rtemp.average_wait = av_wait / rtemp.num;

	return rtemp;
}
/* Given a search string, the function performs a single-threaded or serial search of the file system starting from the specified path name. */
void search_for_string_serial(char **argv)
{
	  printf("SERIAL Execution Started.\n");
		  
	  int num_occurences = 0;
	  queue_element_t *element, *new_element;
	  struct stat file_stats;
	  int status; 
	  DIR *directory = NULL;
	  struct dirent *result = NULL;
	  struct dirent *entry = (struct dirent *)malloc(sizeof(struct dirent) + MAX_LENGTH); // Allocate memory for the directory structure

	  /* Create and initialize the queue data structure. */
	  queue_t *queue = create_queue();
	  element = (queue_element_t *)malloc(sizeof(queue_element_t));
	  if(element == NULL){
				 printf("Error allocating memory. Exiting. \n");
				 exit(-1);
	  }
	  strcpy(element->path_name, argv[2]);
	  element->next = NULL;
	  insert_in_queue(queue, element); // Insert the initial path name into the queue

	  /* Start the timer here. */
	  struct timeval start;	
	  gettimeofday(&start, NULL);

	  /* While there is work in the queue, process it. */
	  while(queue->head != NULL){
				 queue_element_t *element = remove_from_queue(queue);
				 status = lstat(element->path_name, &file_stats); // Obtain information about the file pointed to by path_name
				 if(status == -1){
							printf("Error obtaining stats for %s \n", element->path_name);
							free((void *)element);
							continue;
				 }
				 if(S_ISLNK(file_stats.st_mode)){ // Check if the file is a symbolic link; if so ignore it
				 } 
				 else if(S_ISDIR(file_stats.st_mode)){ // Check if file is a directory; if so descend into it and post work to the queue
							//printf("%s is a directory. \n", element->path_name);
							directory = opendir(element->path_name);
							if(directory == NULL){
									  //printf("Unable to open directory %s \n", element->path_name);
									  continue;
							}
							while(1){
									  status = readdir_r(directory, entry, &result); // Store the directory item in the entry data structure; if result == NULL, we have reached the end of the directory
									  if(status != 0){
												 //printf("Unable to read directory %s \n", element->path_name);
												 break;
									  }
									  if(result == NULL)
												 break; // End of directory
									  /* Ignore the "." and ".." entries. */
									  if(strcmp(entry->d_name, ".") == 0)
												 continue;
									  if(strcmp(entry->d_name, "..") == 0)
												 continue;

									  /* Insert this directory entry in the queue. */
									  new_element = (queue_element_t *)malloc(sizeof(queue_element_t));
									  if(new_element == NULL){
												 printf("Error allocating memory. Exiting. \n");
												 exit(-1);
									  }
									  /* Construct the full path name for the directory item stored in entry. */
									  strcpy(new_element->path_name, element->path_name);
									  strcat(new_element->path_name, "/");
									  strcat(new_element->path_name, entry->d_name);
									  insert_in_queue(queue, new_element);
							}
							closedir(directory);
				 } 
				 else if(S_ISREG(file_stats.st_mode)){ // Check if file is a regular file
							//printf("%s is a regular file. \n", element->path_name);
							FILE *file_to_search;
							char buffer[MAX_LENGTH];
							char *bufptr, *searchptr;
							
							/* Search the file for the search string provided as the command-line argument. */ 
							file_to_search = fopen(element->path_name, "r");
							if(file_to_search == NULL){
									  //printf("Unable to open file %s \n", element->path_name);
									  continue;
							} 
							else{
									  while(1){
												 bufptr = fgets(buffer, sizeof(buffer), file_to_search);
												 if(bufptr == NULL){
															if(feof(file_to_search)) break;
															if(ferror(file_to_search)){
																	  printf("Error reading file %s \n", element->path_name);
																	  break;
															}
												 }
												 searchptr = strstr(buffer, argv[1]);
												 if(searchptr != NULL){
															//printf("Found string %s within file %s. \n", argv[1], element->path_name);
															num_occurences ++;
															// getchar();
												 }
									  }
							}
							fclose(file_to_search);
				 }
				 else{
							//printf("%s is of type other. \n", element->path_name);
				 }
				 free((void *)element);
	  }

	  /* Stop timer here and determine the elapsed time. */
	  struct timeval stop;	
	  gettimeofday(&stop, NULL);
	  printf("SERIAL Overall execution time = %fs. \n", (float)(stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/(float)1000000));
	  printf("SERIAL The string %s was found %d times within the file system. \n\n", argv[1], num_occurences);
}
/* worker pthread function */
void *pthread_func(void *args) {

	/* threadID*/
	int tID = (int)args;
	
	int stringCount = 0;
	queue_element_t *element, *new_element;
	struct stat file_stats;
	int status; 
	DIR *directory = NULL;
	struct dirent *result = NULL;
	struct dirent *entry = (struct dirent *)malloc(sizeof(struct dirent) + MAX_LENGTH); // Allocate memory for the directory structure
	char temp[MAX_LENGTH];

	while(1) {

		/* increase threadWaiting count, set DONE flag if all threads waiting*/
		sem_wait(&wait_lock);
		threadsWaiting++;
		if (threadsWaiting == numThreads){
			searchDone = 1;

			/* add count to global count */
			sem_wait(&count_lock);
			num_occurences = num_occurences + stringCount;
			sem_post(&count_lock);
			
			/* wake up other threads */
			int i;
			for(i = 0; i < numThreads; i++){
				sem_post(&queue_work);
			}
			printf("Thread #%d finished.\n", tID);
			pthread_exit(0);
		}
		sem_post(&wait_lock);


		/* wait for work in queue */
		sem_wait(&queue_work);

		
		if (searchDone) {
			
			/* add count to global count */
			sem_wait(&count_lock);
			num_occurences = num_occurences + stringCount;
			sem_post(&count_lock);
			
			printf("Thread #%d finished.\n", tID);
			pthread_exit(0);
		}

		/* decrease thread waiting count */
		sem_wait(&wait_lock);
		threadsWaiting--;
		sem_post(&wait_lock);

		/* acquire queue lock and retrieve directory from queue */
		sem_wait(&queue_lock);
		element = remove_from_queue(queue);
		sem_post(&queue_lock);

		/* Open directory */
		directory = opendir(element->path_name);
		if(directory == NULL){
			//printf("Unable to open directory %s \n", element->path_name);
			free( (void *) element); //added
			continue;
		}

		/* Go through directory file-by-file */
		while(1){
			
			/* store file in entry  --> if result == NULL, end of directory */
			status = readdir_r(directory, entry, &result); 
			if(status != 0){
					 printf("Unable to read directory %s \n", element->path_name);
					 break;
			}
			if(result == NULL)
					 break; // End of directory

			/* Ignore the "." and ".." entries. */
			if(strcmp(entry->d_name, ".") == 0)
					 continue;
			if(strcmp(entry->d_name, "..") == 0)
					 continue;
			
			/* Construct full path name */
			strcpy(temp, element->path_name);
			strcat(temp, "/");
			strcat(temp, entry->d_name);

			/* Get information about file */
			status = lstat(temp, &file_stats); // Obtain information about the file pointed to by path_name
			if(status == -1){
				printf("Error obtaining stats for %s \n", temp);
				continue;
	 		}

			/* if symlink, ignore */
			if(S_ISLNK(file_stats.st_mode)){ 
			
			/* if directory, add back to queue */
			}else if(S_ISDIR(file_stats.st_mode)){
				//printf("%s is a directory. \n", element->path_name);

				/* Malloc space for new queue element */
				new_element = (queue_element_t *)malloc(sizeof(queue_element_t));
				if(new_element == NULL){
						 printf("Error allocating memory. Exiting. \n");
						 exit(-1);
				}

				/* Construct full path name */
				strcpy(new_element->path_name, element->path_name);
				strcat(new_element->path_name, "/");
				strcat(new_element->path_name, entry->d_name);

				/* Acquire queue lock, add to queue, signal work sem */
				sem_wait(&queue_lock);
				insert_in_queue(queue, new_element);
				sem_post(&queue_work);
				sem_post(&queue_lock);
			
			/* if file, count # of occurences */
			}else if(S_ISREG(file_stats.st_mode)){ 
				//printf("%s is a regular file. \n", temp);

				FILE *file_to_search;
				char buffer[MAX_LENGTH];
				char *bufptr, *searchptr;

				/* Search the file for the search string provided as the command-line argument. */ 
				file_to_search = fopen(temp, "r");
				if(file_to_search == NULL){
						  //printf("Unable to open file %s \n", temp);
						  continue;
				} 
				else{
				  	while(1){
						 bufptr = fgets(buffer, sizeof(buffer), file_to_search);
						 if(bufptr == NULL){
							if(feof(file_to_search)) break;
							if(ferror(file_to_search)){
								printf("Error reading file %s \n", temp);
								break;
							}
						 }

						 searchptr = strstr(buffer, g_searchString);
						 if(searchptr != NULL){
							//printf("Found string %s within file %s. \n", g_searchString, temp);
							stringCount++;
							// getchar();
						 }
					}
				}
				fclose(file_to_search);

			/* if file is of some other type */
			} else{
							printf("%s is of type other. \n", element->path_name);
			}
	 		
		}
		closedir(directory);
		free( (void *) element);
	}	
}
void search_for_string_pthreads(char **argv){
	printf("PTHREAD Execution Started.\n");
	
	/* set numThreads and string to search */
	numThreads = atoi(argv[3]);
	strcpy(g_searchString,argv[1]);
	threadsWaiting = 0;
	searchDone = 0;
	
	/* declare pthread array and initialize semaphores */
	pthread_t threads[numThreads];
	if ( sem_init(&queue_work,0,0) < 0 ){
		perror("sem_init error");
		exit(0);
	}
	if ( sem_init(&queue_lock,0,1) < 0 ){
		perror("sem_init error");
		exit(0);
	}
	if ( sem_init(&wait_lock,0,1) < 0 ){
		perror("sem_init error");
		exit(0);
	}
	if ( sem_init(&count_lock,0,1) < 0 ){
		perror("sem_init error");
		exit(0);
	}

	/* Create and initialize the queue data structure. */
	queue = create_queue();
	queue_element_t *firstElement;
	firstElement = (queue_element_t *)malloc(sizeof(queue_element_t));
	if(firstElement == NULL){
		printf("Error allocating memory. Exiting. \n");
		exit(-1);
	}
	strcpy(firstElement->path_name, argv[2]);
	firstElement->next = NULL;
	insert_in_queue(queue, firstElement); // Insert the initial path name into the queue
	sem_post(&queue_work);   // b/c adding first element

	/* Start the timer here. */
	struct timeval start;	
	gettimeofday(&start, NULL);

	/* Spawn threads*/
	int i;
	for (i = 0; i < numThreads; i++) {
		pthread_create(&threads[i],NULL,pthread_func,(void *) i);
	}

	/* wait for threads to join */
	for (i = 0; i < numThreads; i++) {
		pthread_join(threads[i],NULL);
	}

	/* Stop timer here and determine the elapsed time. */
	struct timeval stop;	
	gettimeofday(&stop, NULL);
	printf("PTHREAD Overall execution time = %fs. \n", (float)(stop.tv_sec - start.tv_sec + (stop.tv_usec - start.tv_usec)/(float)1000000));
	printf("PTHREAD The string %s was found %d times within the file system. \n\n", argv[1], num_occurences);
}