Esempio n. 1
0
int
main(int argc, char *argv[])
{
	int			i;
	int			j;
	int			k;
	int			pages = 256; /* 1MB */
	int			buffers = 2;
	int			producers = 2;
	int			consumers = 2;
	int			stages = 2;
	int			*status;
	stage_info_t		*stage_info;
	stage_info_t		*sp;
	worker_info_t		*worker_info;
	worker_info_t		*wp;
	kern_return_t		ret;
	int			c;

	/* Do switch parsing: */
	while ((c = getopt (argc, argv, "ab:i:p:s:twv:")) != -1) {
		switch (c) {
		case 'a':
			affinity = !affinity;
			break;
		case 'b':
			buffers = atoi(optarg);
			break;
		case 'i':
			iterations = atoi(optarg);
			break;
		case 'p':
			pages = atoi(optarg);
			break;
		case 's':
			stages = atoi(optarg);
			if (stages >= WORKERS_MAX)
				usage();
			break;
		case 't':
			halting = TRUE;
			break;
		case 'w':
			consumer_fnp = &reader_writer_fn;
			break;
		case 'v':
			verbosity = atoi(optarg);
			break;
		case 'h':
		case '?':
		default:
			usage();
		}
	}
	argc -= optind; argv += optind;
	if (argc > 0)
		producers = atoi(*argv);
	argc--; argv++;
	if (argc > 0)
		consumers = atoi(*argv);
	
	pthread_mutex_init(&funnel, NULL);
	pthread_cond_init(&barrier, NULL);

	/*
 	 * Fire up the worker threads.
	 */
	threads = consumers * (stages - 1) + producers;
	mutter("Launching %d producer%s with %d stage%s of %d consumer%s\n"
		"  with %saffinity, consumer reads%s data\n",
		producers, s_if_plural(producers),
		stages - 1, s_if_plural(stages - 1),
		consumers, s_if_plural(consumers),
		affinity? "": "no ",
		(consumer_fnp == &reader_writer_fn)? " and writes" : "");
	if (pages < 256)
		mutter("  %dkB bytes per buffer, ", pages * 4);
	else
		mutter("  %dMB bytes per buffer, ", pages / 256);
	mutter("%d buffer%s per producer ",
		buffers, s_if_plural(buffers));
	if (buffers * pages < 256)
		mutter("(total %dkB)\n", buffers * pages * 4);
	else
		mutter("(total %dMB)\n", buffers * pages / 256);
	mutter("  processing %d buffer%s...\n",
		iterations, s_if_plural(iterations));

	stage_info = (stage_info_t *) malloc(stages * sizeof(stage_info_t));
	worker_info = (worker_info_t *) malloc(threads * sizeof(worker_info_t));

	/* Set up the queue for the workers of this thread set: */
	for (i = 0; i < stages; i++) {
		sp = &stage_info[i];
		sp->stagenum = i;
		pthread_mutex_init(&sp->bufq.mtx, NULL);
		pthread_cond_init(&sp->bufq.cnd, NULL);
		TAILQ_INIT(&sp->bufq.queue);
		sp->bufq.waiters = 0;
		if (i == 0) {
			sp->fn = producer_fnp;
			sp->name = "producer";
		} else {
			sp->fn = consumer_fnp;
			sp->name = "consumer";
		}
		sp->input = &sp->bufq;
		sp->output = &stage_info[(i + 1) % stages].bufq;
		stage_info[i].work_todo = iterations;
	}
 
	/* Create the producers */
	for (i = 0; i < producers; i++) {
		work_t	*work_array;
		int	*data;
		int	isize;

		isize = pages * 4096 / sizeof(int);
		data = (int *) malloc(buffers * pages * 4096);

		/* Set up the empty work buffers */
		work_array = (work_t *)  malloc(buffers * sizeof(work_t));
		for (j = 0; j < buffers; j++) {
			work_array[j].data = data + (isize * j);	
			work_array[j].isize = isize;
			work_array[j].tag = 0;
			TAILQ_INSERT_TAIL(&stage_info[0].bufq.queue, &work_array[j], link);
			DBG("  empty work item %p for data %p\n",
				&work_array[j], work_array[j].data);
		}
		wp = &worker_info[i];
		wp->setnum = i + 1;
		wp->stage = &stage_info[0];
		if (ret = pthread_create(&wp->thread,
					 NULL,
					 &manager_fn,
					 (void *) wp))
			err(1, "pthread_create %d,%d", 0, i);
	}

	/* Create consumers */
	for (i = 1; i < stages; i++) {
		for (j = 0; j < consumers; j++) {
			wp = &worker_info[producers + (consumers*(i-1)) + j];
			wp->setnum = j + 1;
			wp->stage = &stage_info[i];
			if (ret = pthread_create(&wp->thread,
						NULL,
						&manager_fn,
						(void *) wp))
				err(1, "pthread_create %d,%d", i, j);
		}
	}

	/*
	 * We sit back anf wait for the slaves to finish.
	 */
	for (k = 0; k < threads; k++) {
		int	i;
		int	j;

		wp = &worker_info[k];
		if (k < producers) {
			i = 0;
			j = k;
		} else {
			i = (k - producers) / consumers;
			j = (k - producers) % consumers;
		}
		if(ret = pthread_join(wp->thread, (void **)&status))
		    err(1, "pthread_join %d,%d", i, j);
		DBG("Thread %d,%d status %d\n", i, j, status);
	}

	/*
	 * See how long the work took.
	 */
	timer = mach_absolute_time() - timer;
	timer = timer / 1000000ULL;
	printf("%d.%03d seconds elapsed.\n",
		(int) (timer/1000ULL), (int) (timer % 1000ULL));

	return 0;
}
Esempio n. 2
0
File: sets.c Progetto: TalAloni/xnu
int
main(int argc, char *argv[])
{
	int			i;
	int			j;
	int			pages = 256; /* 1MB */
	int			buffers = 2;
	int			sets = 2;
	int			stages = 2;
	int			*status;
	line_info_t		*line_info;
	line_info_t		*lp;
	stage_info_t		*stage_info;
	stage_info_t		*sp;
	kern_return_t		ret;
	int			c;

	/* Do switch parsing: */
	while ((c = getopt (argc, argv, "ab:chi:p:s:twv:")) != -1) {
		switch (c) {
		case 'a':
#ifdef AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER
			affinity = !affinity;
			break;
#else
			usage();
#endif
		case 'b':
			buffers = atoi(optarg);
			break;
		case 'c':
			cache_config = TRUE;
			break;
		case 'i':
			iterations = atoi(optarg);
			break;
		case 'p':
			pages = atoi(optarg);
			break;
		case 's':
			stages = atoi(optarg);
			if (stages >= WORKERS_MAX)
				usage();
			break;
		case 't':
			halting = TRUE;
			break;
		case 'w':
			consumer_fnp = &reader_writer_fn;
			break;
		case 'v':
			verbosity = atoi(optarg);
			break;
		case '?':
		case 'h':
		default:
			usage();
		}
	}
	argc -= optind; argv += optind;
	if (argc > 0)
		sets = atoi(*argv);

	if (cache_config)
		auto_config(pages, &buffers, &sets);

	pthread_mutex_init(&funnel, NULL);
	pthread_cond_init(&barrier, NULL);

	/*
 	 * Fire up the worker threads.
	 */
	threads = sets * stages;
	mutter("Launching %d set%s of %d threads with %saffinity, "
			"consumer reads%s data\n",
		sets, s_if_plural(sets), stages, affinity? "": "no ",
		(consumer_fnp == &reader_writer_fn)? " and writes" : "");
	if (pages < 256)
		mutter("  %dkB bytes per buffer, ", pages * 4);
	else
		mutter("  %dMB bytes per buffer, ", pages / 256);
	mutter("%d buffer%s per set ",
		buffers, s_if_plural(buffers));
	if (buffers * pages < 256)
		mutter("(total %dkB)\n", buffers * pages * 4);
	else
		mutter("(total %dMB)\n", buffers * pages / 256);
	mutter("  processing %d buffer%s...\n",
		iterations, s_if_plural(iterations));
	line_info = (line_info_t *) malloc(sets * sizeof(line_info_t));
	stage_info = (stage_info_t *) malloc(sets * stages * sizeof(stage_info_t));
	for (i = 0; i < sets; i++) {
		work_t	*work_array;

		lp = &line_info[i];

		lp->setnum = i + 1;
		lp->isize = pages * 4096 / sizeof(int);
		lp->data = (int *) malloc(buffers * pages * 4096);

		/* Set up the queue for the workers of this thread set: */
		for (j = 0; j < stages; j++) {
			sp = &stage_info[(i*stages) + j];
			sp->stagenum = j;
			sp->set = lp;
			lp->stage[j] = sp;
			pthread_mutex_init(&sp->bufq.mtx, NULL);
			pthread_cond_init(&sp->bufq.cnd, NULL);
			TAILQ_INIT(&sp->bufq.queue);
			sp->bufq.waiters = FALSE;
		}

		/*
		 * Take a second pass through the stages
		 * to define what the workers are and to interconnect their input/outputs
		 */
		for (j = 0; j < stages; j++) {
			sp = lp->stage[j];
			if (j == 0) {
				sp->fn = producer_fnp;
				sp->name = "producer";
			} else {
				sp->fn = consumer_fnp;
				sp->name = "consumer";
			}
			sp->input = &lp->stage[j]->bufq;
			sp->output = &lp->stage[(j + 1) % stages]->bufq;
		}

		/* Set up the buffers on the first worker of the set. */
		work_array = (work_t *)  malloc(buffers * sizeof(work_t));
		for (j = 0; j < buffers; j++) {
			work_array[j].data = lp->data + (lp->isize * j);	
			TAILQ_INSERT_TAIL(&lp->stage[0]->bufq.queue, &work_array[j], link);
			DBG("  empty work item %p for set %d data %p\n",
				&work_array[j], i, work_array[j].data);
		}

		/* Create this set of threads */
		for (j = 0; j < stages; j++) {
			if (ret = pthread_create(&lp->stage[j]->thread, NULL,
					&manager_fn,
					(void *) lp->stage[j]))
			err(1, "pthread_create %d,%d", i, j);
		}
	}

	/*
	 * We sit back anf wait for the slave to finish.
	 */
	for (i = 0; i < sets; i++) {
		lp = &line_info[i];
		for (j = 0; j < stages; j++) {
			if(ret = pthread_join(lp->stage[j]->thread, (void **)&status))
			    err(1, "pthread_join %d,%d", i, j);
			DBG("Thread %d,%d status %d\n", i, j, status);
		}
	}

	/*
	 * See how long the work took.
	 */
	timer = mach_absolute_time() - timer;
	timer = timer / 1000000ULL;
	printf("%d.%03d seconds elapsed.\n",
		(int) (timer/1000ULL), (int) (timer % 1000ULL));

	return 0;
}