
#include <stdint.h>
#include <stdlib.h>
#include <libspe2.h>
#include <pthread.h>

extern spe_program_handle_t spe_hello_world;

struct spe_thread {
	spe_context_ptr_t ctx;
	pthread_t pthread;
};

void *spethread_fn(void *data)
{
	struct spe_thread *spethread = data;
	uint32_t entry = SPE_DEFAULT_ENTRY;

	/* run the context */
	spe_context_run(spethread->ctx, &entry, 0, NULL, NULL, NULL);

	return NULL;
}

int main(int argc, char **argv)
{
	struct spe_thread *threads;
	int n_threads, i;
	char *endp;

	if (argc != 2) {
		fprintf(stderr, "usage: %s <n_threads>\n", argv[0]);
		return -1;
	}

	/* parse the first argument into n_threads */
	n_threads = strtoul(argv[1], &endp, 0);
	if (endp == argv[1] || *endp != '\0') {
		fprintf(stderr, "invalid n_threads value: %s\n", argv[1]);
		return -1;
	}

	threads = calloc(n_threads, sizeof(*threads));

	for (i = 0; i < n_threads; i++) {

		threads[i].ctx = spe_context_create(0, NULL);

		spe_program_load(threads[i].ctx, &spe_hello_world);

		/* run the context in a new thread, passing the spe_thread
		 * struct as the first argument of spethread_fn */
		pthread_create(&threads[i].pthread, NULL,
				spethread_fn, &threads[i]);
	}

	/* wait for all of the threads to finish */
	for (i = 0; i < n_threads; i++)
		pthread_join(threads[i].pthread, NULL);

	return 0;
}
