summaryrefslogtreecommitdiffstats
path: root/main.c
blob: 3c0919b8ad453c6e4c096bd39e27bc329ec67ae8 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#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));
		int možen = nit.možen;
		switch (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;
}