コード例 #1
0
/*free given mailbox*/
void free_mb(mailbox* mb){
	if (mb == NULL)	return;
	free_mb(mb->next);
	free_mail(mb->msg);
	if (mb != NULL) {
		kmem_cache_free(mbCache, mb);
	}
}
コード例 #2
0
/* free hashtable */
void free_ht(void){
	int i;
	for (i = 0; i < HASHTABLE_SIZE; i++){
		free_mb(all[i]);
	}
}
コード例 #3
0
ファイル: dgsh-conc.c プロジェクト: dspinellis/sgsh
int
main(int argc, char *argv[])
{
	int ch;
	int exit;
	char *debug_level = NULL;
	char *timeout;

	program_name = argv[0];
	pid = getpid();
	noinput = false;

	while ((ch = getopt(argc, argv, "ion")) != -1) {
		switch (ch) {
		case 'i':
			multiple_inputs = true;
			break;
		case 'o':
			multiple_inputs = false;
			break;
		case 'n':	// special output conc that takes no input
			if (!multiple_inputs)
				noinput = true;
			else
				usage();
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 1)
		usage();

	debug_level = getenv("DGSH_DEBUG_LEVEL");
	if (debug_level != NULL)
		dgsh_debug_level = atoi(debug_level);

	signal(SIGALRM, dgsh_alarm_handler);
	if ((timeout = getenv("DGSH_TIMEOUT")) != NULL)
		alarm(atoi(timeout));
	else
		alarm(DGSH_TIMEOUT);

	/* +1 for stdin when scatter/stdout when gather
	 * +1 for stderr which is not used
	 */
	if (atoi(argv[0]) == 1)
		nfd = 2;
	else
		nfd = atoi(argv[0]) + 2;
	pi = (struct portinfo *)calloc(nfd, sizeof(struct portinfo));

	chosen_mb = NULL;
	exit = pass_message_blocks();
	if (exit == PS_RUN) {
		if (noinput)
			DPRINTF(1, "%s(): Special (no-input) conc communicated the solution", __func__);
		if (multiple_inputs)
			gather_input_fds(chosen_mb);
		else if (!noinput)	// Output noinput conc has no job here
			scatter_input_fds(chosen_mb);
		exit = PS_COMPLETE;
	}
	free_mb(chosen_mb);
	free(pi);
	DPRINTF(3, "conc with pid %d terminates %s",
		pid, exit == PS_COMPLETE ? "normally" : "with error");
#ifdef DEBUG
	fflush(stderr);
#endif
#ifdef TIME
	if (noinput) {
		clock_gettime(CLOCK_MONOTONIC, &tend);
		fprintf(stderr, "The dgsh negotiation procedure took about %.5f seconds\n",
			((double)tend.tv_sec + 1.0e-9*tend.tv_nsec) -
			((double)tstart.tv_sec + 1.0e-9*tstart.tv_nsec));
		fflush(stderr);

	}
#endif
	set_negotiation_complete();
	alarm(0);			// Cancel alarm
	signal(SIGALRM, SIG_IGN);	// Do not handle the signal
	return exit;
}
コード例 #4
0
ファイル: dgsh-conc.c プロジェクト: dspinellis/sgsh
/*
 * Pass around the message blocks so that they reach all processes
 * connected through the concentrator.
 */
STATIC int
pass_message_blocks(void)
{
	fd_set readfds, writefds;
	int nfds = 0;
	int i;
	int oi = -1;		/* scatter/gather block's origin index */
	int ofd = -1;		/* ... origin fd direction */
	bool ro = false;	/* Whether the read block's origin should
				 * be restored
				 */
	bool iswrite = false;

	if (noinput) {
#ifdef TIME
		clock_gettime(CLOCK_MONOTONIC, &tstart);
#endif
		construct_message_block("dgsh-conc", pid);
		chosen_mb->origin_fd_direction = STDOUT_FILENO;
		chosen_mb->is_origin_conc = true;
		chosen_mb->conc_pid = pid;
		pi[STDOUT_FILENO].to_write = chosen_mb;
	}

	for (;;) {
		// Create select(2) masks
		FD_ZERO(&readfds);
		FD_ZERO(&writefds);
		for (i = 0; i < nfd; i++) {
			if (noinput && i == STDIN_FILENO)
				continue;
			if (i == STDERR_FILENO)
				continue;
			if (!pi[i].seen) {
				FD_SET(i, &readfds);
				nfds = max(i + 1, nfds);
			}
			if (pi[i].to_write && !pi[i].written) {
				FD_SET(i, &writefds);
				nfds = max(i + 1, nfds);
				pi[i].to_write->is_origin_conc = true;
				pi[i].to_write->conc_pid = pid;
				DPRINTF(4, "Actual origin: conc with pid %d", pid);
			}
		}

	again:
		if (select(nfds, &readfds, &writefds, NULL, NULL) < 0) {
			if (errno == EINTR)
				goto again;
			/* All other cases are internal errors. */
			err(1, "select");
		}

		// Read/write what we can
		for (i = 0; i < nfd; i++) {
			if (FD_ISSET(i, &writefds)) {
				iswrite = true;
				assert(pi[i].to_write);
				chosen_mb = pi[i].to_write;
				DPRINTF(4, "**fd i: %d set for writing to tool with pid %d", i, pi[i].pid);
				write_message_block(i); // XXX check return

				if (pi[i].to_write->state == PS_RUN ||
					pi[i].to_write->state == PS_DRAW_EXIT ||
					(pi[i].to_write->state == PS_ERROR &&
						pi[i].to_write->is_error_confirmed))
					pi[i].written = true;

				// Write side exit
				if (is_ready(i, pi[i].to_write)) {
					pi[i].run_ready = true;
					DPRINTF(4, "**%s(): pi[%d] is run ready",
							__func__, i);
				}
				pi[i].to_write = NULL;
			}
			if (FD_ISSET(i, &readfds)) {
				struct dgsh_negotiation *rb;
				ro = false;
				int next = next_fd(i, &ro);

				assert(!pi[i].run_ready);
				assert(pi[next].to_write == NULL);
				if (read_message_block(i, &pi[next].to_write) ==
								OP_ERROR) {
					chosen_mb->state = PS_ERROR;
					if (noinput)
						chosen_mb->is_error_confirmed = true;
					pi[next].to_write = chosen_mb;
					continue;
				}
				rb = pi[next].to_write;

				DPRINTF(4, "%s(): next write via fd %d to pid %d",
						__func__, next, pi[next].pid);

				if (oi == -1) {
					if ((multiple_inputs && i == 1) ||
							(!multiple_inputs &&
							 i == 0)) {
						oi = rb->origin_index;
						ofd = rb->origin_fd_direction;
						DPRINTF(4, "**Store origin: %d, fd: %s",
							oi, ofd ? "stdout" : "stdin");
					}
				}

				/* If conc talks to conc, set conc's pid
				 * Required in order to allocate fds correctly
				 * in the end
				 */
				if (rb->is_origin_conc)
					pi[i].pid = rb->conc_pid;
				else
					pi[i].pid = get_origin_pid(rb);

				/* If needed, re-set origin.
				 * Don't move this block before get_origin_pid()
				 */
				if (ro) {
					DPRINTF(4, "**Restore origin: %d, fd: %s",
							oi, ofd ? "stdout" : "stdin");
					pi[next].to_write->origin_index = oi;
					pi[next].to_write->origin_fd_direction = ofd;
				} else if (noinput) {
					pi[next].to_write->origin_index = -1;
					pi[next].to_write->origin_fd_direction = STDOUT_FILENO;
				}

				/* Set a conc's required/provided IO in mb */
				if (!noinput)
					set_io_channels(pi[next].to_write);

				if (rb->state == PS_NEGOTIATION &&
						noinput) {
					int j, seen = 0;
					pi[i].seen = true;
					for (j = 1; j < nfd; j++)
						if (pi[j].seen)
							seen++;
					if ((nfd > 2 && seen == nfd - 2) ||
							seen == nfd - 1) {
						chosen_mb = rb;
						DPRINTF(1, "%s(): Gathered I/O requirements.", __func__);
						int state = solve_graph();
						if (state == OP_ERROR) {
							pi[next].to_write->state = PS_ERROR;
							pi[next].to_write->is_error_confirmed = true;
						} else if (state == OP_DRAW_EXIT)
							pi[next].to_write->state = PS_DRAW_EXIT;
						else {
							DPRINTF(1, "%s(): Computed solution", __func__);
							pi[next].to_write->state = PS_RUN;
						}
						for (j = 1; j < nfd; j++)
							pi[j].seen = false;
						// Don't free
						chosen_mb = NULL;
					}
				} else if (rb->state == PS_RUN ||
						rb->state == PS_DRAW_EXIT ||
						(rb->state == PS_ERROR &&
						rb->is_error_confirmed))
					pi[i].seen = true;
				else if (rb->state == PS_ERROR)
					rb->is_error_confirmed = true;

				print_state(i, (int)rb->initiator_pid, 1);
				if (pi[i].seen && pi[i].written) {
					chosen_mb = pi[next].to_write;
					pi[i].run_ready = true;
					DPRINTF(4, "**%s(): pi[%d] is run ready",
							__func__, i);
				}
			}
		}

		// See if all processes are run-ready
		nfds = 0;
		for (i = 0; i < nfd; i++) {
			if (pi[i].run_ready)
				nfds++;
			print_state(i, nfds, 2);
		}
		if ((nfd > 2 && (nfds == nfd - 1 ||
					(noinput && nfds == nfd - 2))) ||
		    (nfds == nfd || (noinput && nfds == nfd - 1))) {
			assert(chosen_mb != NULL);
			DPRINTF(4, "%s(): conc leaves negotiation", __func__);
			return chosen_mb->state;
		} else if (chosen_mb != NULL &&	iswrite) { // Free if we have written
			DPRINTF(4, "chosen_mb: %lx, i: %d, next: %d, pi[next].to_write: %lx\n",
				(long)chosen_mb, i, next_fd(i, &ro), (long)pi[next_fd(i, &ro)].to_write);
			free_mb(chosen_mb);
			chosen_mb = NULL;
			iswrite = false;
		}
	}
}