/* Run command CMD and return statistics on it.
   Put the statistics in *RESP.  */
static void run_command(char *const *cmd, resource_t *resp)
{
	pid_t pid;			/* Pid of child.  */
	void (*interrupt_signal)(int);
	void (*quit_signal)(int);

	resp->elapsed_ms = monotonic_ms();
	pid = vfork();		/* Run CMD as child process.  */
	if (pid < 0)
		bb_perror_msg_and_die("fork");
	if (pid == 0) {	/* If child.  */
		/* Don't cast execvp arguments; that causes errors on some systems,
		   versus merely warnings if the cast is left off.  */
		BB_EXECVP(cmd[0], cmd);
		xfunc_error_retval = (errno == ENOENT ? 127 : 126);
		bb_error_msg_and_die("can't run %s", cmd[0]);
	}

	/* Have signals kill the child but not self (if possible).  */
//TODO: just block all sigs? and reenable them in the very end in main?
	interrupt_signal = signal(SIGINT, SIG_IGN);
	quit_signal = signal(SIGQUIT, SIG_IGN);

	resuse_end(pid, resp);

	/* Re-enable signals.  */
	signal(SIGINT, interrupt_signal);
	signal(SIGQUIT, quit_signal);
}
Exemple #2
0
/* Run command CMD and return statistics on it.
   Put the statistics in *RESP.  */
static void run_command(char *const *cmd, resource_t * resp)
{
	pid_t pid;			/* Pid of child.  */
	__sighandler_t interrupt_signal, quit_signal;

	gettimeofday(&resp->start, (struct timezone *) 0);
	pid = vfork();		/* Run CMD as child process.  */
	if (pid < 0)
		bb_error_msg_and_die("cannot fork");
	else if (pid == 0) {	/* If child.  */
		/* Don't cast execvp arguments; that causes errors on some systems,
		   versus merely warnings if the cast is left off.  */
		execvp(cmd[0], cmd);
		bb_error_msg("cannot run %s", cmd[0]);
		_exit(errno == ENOENT ? 127 : 126);
	}

	/* Have signals kill the child but not self (if possible).  */
	interrupt_signal = signal(SIGINT, SIG_IGN);
	quit_signal = signal(SIGQUIT, SIG_IGN);

	if (resuse_end(pid, resp) == 0)
		bb_error_msg("error waiting for child process");

	/* Re-enable signals.  */
	signal(SIGINT, interrupt_signal);
	signal(SIGQUIT, quit_signal);
}
Exemple #3
0
/* Run command CMD and return statistics on it.
   Put the statistics in *RESP.  */
static void run_command(char *const *cmd, resource_t *resp)
{
	pid_t pid;
	void (*interrupt_signal)(int);
	void (*quit_signal)(int);

	resp->elapsed_ms = monotonic_ms();
	pid = xvfork();
	if (pid == 0) {
		/* Child */
		BB_EXECVP_or_die((char**)cmd);
	}

	/* Have signals kill the child but not self (if possible).  */
//TODO: just block all sigs? and reenable them in the very end in main?
	interrupt_signal = signal(SIGINT, SIG_IGN);
	quit_signal = signal(SIGQUIT, SIG_IGN);

	resuse_end(pid, resp);

	/* Re-enable signals.  */
	signal(SIGINT, interrupt_signal);
	signal(SIGQUIT, quit_signal);
}
Exemple #4
0
int main(int argc, char* argv[])
{
	int i;
	int c;
	int solution_count = 0;
	int num_threads;
	struct thread_param * params;
	struct resuse resuse;
	pthread_t * thread_handles;
	
	// Star collecting resource information about the entire proccess
	resuse_start(&resuse, RESUSE_SCOPE_PROC);
	
	// parse the command line arguments
	while((c = getopt(argc, argv, "n:t:vd")) != -1)
	{
		// for each argument
		switch(c)
		{
			// n = The number of queens
			case 'n':
				num_queens = atoi(optarg);
				break;
			// t = The number of threads
			case 't':
				threaded_flag = 1;
				num_threads = atoi(optarg);
				break;
			// v = Turn on verbose output
			case 'v':
				verbose_flag = 1;
				break;
			// d = Display the chess boards
			case 'd':
				display_flag = 1;
				break;
			case '?':
				if (optopt == 'c')
					fprintf(stderr, "Option -%c requires an argument.\n", optopt);
				else if (isprint (optopt))
					fprintf(stderr, "Unknown option `-%c'.\n", optopt);
				else
					fprintf(stderr, "Unknown option character `\\x%x'.\n", optopt);
				return -1;
			default:
				abort();
		}
	}

	// print out information about the program
	printf("# Queens = %d, # Threads = %d, Threaded = %s, Verbose = %s, Display = %s\n", 
			num_queens, 
			threaded_flag ? num_threads : 1,
			threaded_flag ? "TRUE" : "FALSE",
			verbose_flag ? "TRUE" : "FALSE",
			display_flag ? "TRUE" : "FALSE");

	// If the threaded option is true
	if(threaded_flag) {
		// Dynamically allocate the the thread parameter objects	
		params = calloc(num_queens, sizeof(struct thread_param));
		if (params == NULL) {
			perror("calloc");
			exit(1);
		}
		thread_handles = calloc(num_queens, sizeof(pthread_t));
		if (thread_handles == NULL) {
			perror("calloc");
			exit(1);
		}
	}


	// for each column of the chess board
	if(!threaded_flag) {
		for(i=0;i<num_queens;i++) {
			int rows[num_queens];
			int tmp_solution_count = 0;
			rows[0] = i;
			queens_helper(rows, 1, &tmp_solution_count);
			solution_count += tmp_solution_count;
		}
	} else {
		/* Count down from highest column to lowest.
		 * This allows for the longest threads to run
		 * first, and causes the threads to finish more
		 * at the same time, which increases CPU usage
		 * for better run time
		 */
		next_column = num_queens - 1;
		for(i = 0; i < num_threads; i++) {
			params[i].thread_num = i;
			int err = pthread_create(&(thread_handles[i]), NULL, thread, &(params[i]));
			if (err) {
				fprintf(stderr, "ERR: pthread_create returned %d\n", err);
				exit(1);
			}
		}

		solution_count = 0;
		for (i = 0; i < num_threads; i++) {
			int err = pthread_join(thread_handles[i], NULL);

			if (err) {
				fprintf(stderr, "ERR: pthread_join returned %d\n", err);
			}
			solution_count += params[i].solution_count;
		}
	}


	// Stop collecting resource usage information
	resuse_end(&resuse);
	// Print out the collected information
	resuse_fprint(stdout, resuse_fmt, &resuse);

	// Print out the final number of solutions that were found
	printf("Solution Count = %d\n", solution_count);

	if (threaded_flag) {
		free(params);
		free(thread_handles);
	}
	return 0;
}
Exemple #5
0
/**
 * The thread created by the student.
 * @param     p
 *                 A struct thread_param object cast to void *
 * @return    A pointer to an int containing the number of solutions found
 *            cast to a void *.
 */
void* thread(void* p)
{
	struct thread_param * param = (struct thread_param *) p;
	struct resuse resuse;
	int rows[num_queens];
	int column;

	// star collecting resource information about this thread
	resuse_start(&resuse, RESUSE_SCOPE_THREAD);

	// print debug information
	dprintf("Thread %d Starting\n", param->thread_num);

	while(1) {
		/* Obtain the mutex for the next column */
		int err = pthread_mutex_lock(&nc_mutex);
		if (err) {
			fprintf(stderr, "ERR: pthread_mutex_lock returned %d\n", err);
			exit(1);
		}

		/* Take the next column */
		column = next_column; 

		/* Decrement the next column */
		next_column--;

		/* NOTE: Even though it *looks* atomic,
		 * local = global++ is anything but.
		 * Without the mutex, two threads
		 * could end up grabbing
		 * the same column, then
		 * both incrementing it and
		 * skipping a column, or any
		 * other sort of weirdness.
		 */

		/* Release mutex */
		err = pthread_mutex_unlock(&nc_mutex);
		if (err) {
			fprintf(stderr, "ERR: pthread_mutex_lock returned %d\n", err);
			exit(1);
		}

		if (column < 0) {
			break;
		}

		dprintf("Thread %d kicking off column %d\n", param->thread_num, column);

		rows[0] = param->thread_num;
		queens_helper(rows, 1, &(param->solution_count));

		dprintf("Thread %d finished column %d, looking for new work...\n", param->thread_num, column);

	}
	// print debug information
	dprintf("Thread %d Finished, found %d solutions\n", param->thread_num, 
					param->solution_count);

	// finish collecting resource information about this thread
	resuse_end(&resuse);

	// print the resource information to stdout
	flockfile(stdout);
	fprintf(stdout, "Thread %02d: ", param->thread_num);
	resuse_fprint(stdout, resuse_fmt, &resuse);
	fflush(stdout);
	funlockfile(stdout);

	// return the number of solutions this thread found
	return (void*) &param->solution_count;
}