/* Copyright (c) 2010-14 The Regents of the University of California
 * Barret Rhoden <brho@cs.berkeley.edu>
 * See LICENSE for details.
 *
 * Basic test for pthreading.  Spawns a bunch of threads that yield.
 *
 * To build on linux, cd into tests and run:
 * $ gcc -O2 -std=gnu99 -fno-stack-protector -g pthread_test.c -lpthread
 *
 * Make sure you run it with taskset to fix the number of vcores/cpus. */

#define _GNU_SOURCE /* for pth_yield on linux */

#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "misc-compat.h" /* OS dependent #incs */

/* These are here just to have the compiler test the _INITIALIZERS */
pthread_cond_t dummy_cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t dummy_mutex = PTHREAD_MUTEX_INITIALIZER;

pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
#define printf_safe(...) {}
//#define printf_safe(...) \
	pthread_mutex_lock(&lock); \
	printf(__VA_ARGS__); \
	pthread_mutex_unlock(&lock);

#define MAX_NR_TEST_THREADS 100000
int nr_yield_threads = 100;
int nr_yield_loops = 100;
int nr_vcores = 0;
int amt_fake_work = 0;

pthread_t my_threads[MAX_NR_TEST_THREADS];
void *my_retvals[MAX_NR_TEST_THREADS];

pthread_barrier_t barrier;

void *yield_thread(void* arg)
{	
	/* Wait til all threads are created */
	pthread_barrier_wait(&barrier);
	for (int i = 0; i < nr_yield_loops; i++) {
		printf_safe("[A] pthread %d %p on vcore %d, itr: %d\n",
			    pthread_id(), pthread_self(), vcore_id(), i);
		/* Fakes some work by spinning a bit.  Amount varies per
		 * uth/vcore, scaled by fake_work */
		if (amt_fake_work)
			udelay(amt_fake_work * (pthread_id() * (vcore_id() +
								2)));
		pthread_yield();
		printf_safe("[A] pthread %p returned from yield on vcore %d, itr: %d\n",
		            pthread_self(), vcore_id(), i);
	}
	return (void*)(pthread_self());
}

int main(int argc, char** argv) 
{
	struct timeval start_tv = {0};
	struct timeval end_tv = {0};
	long usec_diff;
	long nr_ctx_switches;

	if (argc > 1)
		nr_yield_threads = strtol(argv[1], 0, 10);
	if (argc > 2)
		nr_yield_loops = strtol(argv[2], 0, 10);
	if (argc > 3)
		nr_vcores = strtol(argv[3], 0, 10);
	if (argc > 4)
		amt_fake_work = strtol(argv[4], 0, 10);
	nr_yield_threads = MIN(nr_yield_threads, MAX_NR_TEST_THREADS);
	printf("Making %d threads of %d loops each, on %d vcore(s), %d work\n",
	       nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);

	/* OS dependent prep work */
#ifdef __ros__
	if (nr_vcores) {
		/* Only do the vcore trickery if requested */
		parlib_never_yield = TRUE;
		pthread_need_tls(FALSE);
		pthread_mcp_init();		/* gives us one vcore */
		vcore_request_total(nr_vcores);
		parlib_never_vc_request = TRUE;
		for (int i = 0; i < nr_vcores; i++) {
			printf_safe("Vcore %d mapped to pcore %d\n", i,
			            __procinfo.vcoremap[i].pcoreid);
		}
	}
	struct uth_join_request *join_reqs;

	join_reqs = malloc(nr_yield_threads * sizeof(struct uth_join_request));
	for (int i = 0; i < nr_yield_threads; i++)
		join_reqs[i].retval_loc = &my_retvals[i];
	assert(join_reqs);
#endif /* __ros__ */

	pthread_barrier_init(&barrier, NULL, nr_yield_threads);
	/* create and join on yield */
	for (int i = 0; i < nr_yield_threads; i++) {
		printf_safe("[A] About to create thread %d\n", i);
		if (pthread_create(&my_threads[i], NULL, &yield_thread, NULL))
			perror("pth_create failed");
	}
	if (gettimeofday(&start_tv, 0))
		perror("Start time error...");
	/* Akaros supports parallel join */
#ifdef __ros__
	for (int i = 0; i < nr_yield_threads; i++)
		join_reqs[i].uth = (struct uthread*)my_threads[i];
	uthread_join_arr(join_reqs, nr_yield_threads);
#else
	for (int i = 0; i < nr_yield_threads; i++) {
		printf_safe("[A] About to join on thread %d(%p)\n",
			    i, my_threads[i]);
		pthread_join(my_threads[i], &my_retvals[i]);
		printf_safe("[A] Successful join on thread %d (retval: %p)\n",
			    i, my_retvals[i]);
	}
#endif
	if (gettimeofday(&end_tv, 0))
		perror("End time error...");
	nr_ctx_switches = nr_yield_threads * nr_yield_loops;
	usec_diff = (end_tv.tv_sec - start_tv.tv_sec) * 1000000 +
	            (end_tv.tv_usec - start_tv.tv_usec);
	printf("Done: %d uthreads, %d loops, %d vcores, %d work\n",
	       nr_yield_threads, nr_yield_loops, nr_vcores, amt_fake_work);
	printf("Nr context switches: %ld\n", nr_ctx_switches);
	printf("Time to run: %ld usec\n", usec_diff);
	if (nr_vcores == 1)
		printf("Context switch latency: %d nsec\n",
		       (int)(1000LL*usec_diff / nr_ctx_switches));
	printf("Context switches / sec: %d\n\n",
	       (int)(1000000LL*nr_ctx_switches / usec_diff));
} 
