summaryrefslogblamecommitdiffstats
path: root/main.c
blob: 53ca54b4a369773177026ab1b265c13b876550cc (plain) (tree)








































































































































                                                                                                                           
#include <ebs.c>
#include <sys/mman.h>
#include <error.h>
#include <errno.h>
#include <poll.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <pthread.h>
#include <stdatomic.h>
#include <time.h>
#define S0(x) ((x) ? (x) : "")
static unsigned long long micros (void) {
	struct timespec tp;
	clock_gettime(CLOCK_MONOTONIC, &tp);
	return tp.tv_sec*1000000+tp.tv_nsec/1000;
}
struct nit {
	atomic_int možen;
	int pipe;
};
static void * pričakuj (void * ptr) {
	struct nit * nit = (struct nit *) ptr;
	struct pollfd pollfd[] = {
		{
			.fd = STDIN_FILENO,
			.events = POLLIN
		},
		{
			.fd = nit->pipe,
			.events = POLLIN
		}
	};
	while (1) {
		int ret = poll(pollfd, 2, -1);
		if (ret == -1) {
			error_at_line(0, errno, __FILE__, __LINE__, "poll");
			nit->možen = 2;
			return NULL;
		}
		if (pollfd[1].revents & POLLIN)
			return NULL;
		if (pollfd[0].revents & POLLIN)
			nit->možen = 1;
	}
}
int main (int argc, char ** argv) {
	if (argc != 1+1)
		error_at_line(1, 0, __FILE__, __LINE__, "%s program.ebs", S0(argv[0]));
	int r = 0;
	struct ebs ebs;
	ebs_init(&ebs);
	pthread_t vhod;
	int pipefd[2];
	int threadret = -1;
	int pfd = -1;
	if (pipe(pipefd) == -1)
		error_at_line(2, errno, __FILE__, __LINE__, "pipe");
	struct nit nit = {
		.možen = 0,
		.pipe = pipefd[0]
	};
	if ((threadret = pthread_create(&vhod, NULL, pričakuj, &nit))) {
		error_at_line(0, threadret, __FILE__, __LINE__, "pthread_create");
		r = 3;
		goto r;
	}
	if ((pfd = open(argv[1], O_RDONLY | O_CLOEXEC)) == -1) {
		error_at_line(0, errno, __FILE__, __LINE__, "open(%s)", argv[1]);
		r = 4;
		goto r;
	}
	struct stat statbuf;
	if (fstat(pfd, &statbuf) == -1) {
		error_at_line(0, errno, __FILE__, __LINE__, "fstat(pfd, &statbuf)");
		r = 5;
		goto r;
	}
	if (!(ebs.pm_velikost = statbuf.st_size)) {
		error_at_line(0, errno, __FILE__, __LINE__, "!(ebs.pm_velikost = statbuf.st_size)");
		r = 6;
		goto r;
	}
	if (!(ebs.pm = mmap(NULL, ebs.pm_velikost, PROT_READ, MAP_SHARED, pfd, 0))) {
		error_at_line(0, errno, __FILE__, __LINE__, "!mmap(NULL, ebs.pm_velikost, PROT_READ, MAP_SHARED, pfd, 0)");
		r = 7;
		goto r;
	}
	unsigned long long int začetek = micros();
	unsigned long long inštrukcij = 0;
	while (ebs_delo(&ebs) == nadaljuj) {
		inštrukcij++;
		if (!(inštrukcij % 100000000))
			fprintf(stderr, "hitrost izvajanja: %llu op/us (MHz)\r", inštrukcij/(micros()-začetek));
		switch (nit.možen) {
			case 0: // ni vhoda, ni napake
				break;
			case 1: // imamo vsaj en bajt
				if (ebs.vhod_medp_indeks > 7) {
					char buf;
					int got = read(STDIN_FILENO, &buf, 1);
					if (got == -1) {
						error_at_line(0, errno, __FILE__, __LINE__, "read");
						r = 8;
						goto r;
					}
					ebs.vhod_medp_indeks = 0;
					ebs.vhod_medp = buf;
					nit.možen = 0;
				}
				break;
			case 2: // napaka
				error_at_line(0, 0, __FILE__, __LINE__, "napaka v vhodni niti");
				r = 8;
				goto r;
				break;
		}
	}
	fprintf(stderr, "konec izvajanja");
	r:
	if (!threadret) {
		if (write(pipefd[1], "", 1) == -1)
			error_at_line(0, errno, __FILE__, __LINE__, "write");
		threadret = pthread_join(vhod, NULL);
		if (threadret)
			error_at_line(0, threadret, __FILE__, __LINE__, "pthread_join");
	}
	if (close(pipefd[0]) == -1)
		error_at_line(0, errno, __FILE__, __LINE__, "close(pipefd[0])");
	if (close(pipefd[1]) == -1)
		error_at_line(0, errno, __FILE__, __LINE__, "close(pipefd[1])");
	if (ebs.pm && munmap(ebs.pm, ebs.pm_velikost) == -1)
		error_at_line(0, errno, __FILE__, __LINE__, "munmap(ebs.pm, ebs.pm_velikost)");
	close(pfd);
	pfd = -1;
	return r;
}