#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;
}