<commit_before>//
//  riscv-device-uart.h
//

#ifndef riscv_device_uart_h
#define riscv_device_uart_h

namespace riscv {

	/* Console Thread */

	template <typename P>
	struct console_thread
	{
		P &proc;
		struct termios old_tio, new_tio;
		int pipefds[2];
		struct pollfd pollfds[2];
		queue_atomic<char> queue;
		volatile bool running;
		volatile bool suspended;
		std::thread thread;

		console_thread(P &proc) :
			proc(proc),
			pipefds{0},
			pollfds(),
			queue(1024),
			running(true),
			suspended(false),
			thread(&console_thread::mainloop, this)
		{}

		void mainloop()
		{
			setup();
			open_pipe();
			while (running) {
				pollfds[0].fd = pipefds[0];
				pollfds[0].events = POLLIN;
				pollfds[0].revents = 0;
				pollfds[1].fd = STDIN_FILENO;
				pollfds[1].events = POLLIN;
				pollfds[1].revents = 0;
				if (poll(pollfds, 2, -1) < 0 && errno != EINTR) {
					panic("console poll failed: %s", strerror(errno));
				}
				if (!running) break;
				if (pollfds[0].revents & POLLIN) {
					unsigned char c;
					if (read(pipefds[0], &c, 1) < 0) {
						debug("console: socket: read: %s", strerror(errno));
					} else if (write(STDIN_FILENO, &c, 1) < 0) {
						debug("console: socket: write: %s", strerror(errno));
					}
				}
				if (suspended) continue;
				if (pollfds[1].revents & POLLIN) {
					unsigned char c;
					if (read(STDIN_FILENO, &c, 1) < 0) {
						debug("console: stdin: read: %s", strerror(errno));
					} else {
						queue.push_back(c);
					}
				}
			}
			close_pipe();
			teardown();
		}

		void open_pipe()
		{
			/* create socketpair */
			if (pipe(pipefds) < 0) {
				panic("pipe failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[0], F_SETFD, FD_CLOEXEC) < 0) {
				panic("console fcntl(F_SETFD, FD_CLOEXEC) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) < 0) {
				panic("console fcntl(F_SETFL, O_NONBLOCK) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[1], F_SETFD, FD_CLOEXEC) < 0) {
				panic("console fcntl(F_SETFD, FD_CLOEXEC) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[1], F_SETFL, O_NONBLOCK) < 0) {
				panic("console fcntl(F_SETFL, O_NONBLOCK) failed: %s", strerror(errno));
			}
		}

		void close_pipe() {
			close(pipefds[0]);
			close(pipefds[1]);
		}

		/* setup console */
		void setup()
		{
			tcgetattr(STDIN_FILENO, &old_tio);
			new_tio = old_tio;
			new_tio.c_lflag &=(~ICANON & ~ECHO);
			tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
		}

		/* teardown console */
		void teardown()
		{
			/* restore settings */
			tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
		}

		/* suspend console input */
		void suspend()
		{
			teardown();
			suspended = true;
		}

		/* resume console input */
		void resume()
		{
			setup();
			suspended = false;
		}

		/* shutdown console thread */
		void shutdown()
		{
			/* set running flag to false and write a null byte to the FIFO */
			running = false;
			unsigned char c = 0;
			if (write(pipefds[1], &c, 1) < 0) {
				debug("console: socket: write: %s", strerror(errno));
			}
			thread.join();
		}

		/* check if data is available */
		bool has_char()
		{<commit_msg>Temporarlily disable console thread join (Linux Bug)<commit_after>//
//  riscv-device-uart.h
//

#ifndef riscv_device_uart_h
#define riscv_device_uart_h

namespace riscv {

	/* Console Thread */

	template <typename P>
	struct console_thread
	{
		P &proc;
		struct termios old_tio, new_tio;
		int pipefds[2];
		struct pollfd pollfds[2];
		queue_atomic<char> queue;
		volatile bool running;
		volatile bool suspended;
		std::thread thread;

		console_thread(P &proc) :
			proc(proc),
			pipefds{0},
			pollfds(),
			queue(1024),
			running(true),
			suspended(false),
			thread(&console_thread::mainloop, this)
		{}

		void mainloop()
		{
			setup();
			open_pipe();
			while (running) {
				pollfds[0].fd = pipefds[0];
				pollfds[0].events = POLLIN;
				pollfds[0].revents = 0;
				pollfds[1].fd = STDIN_FILENO;
				pollfds[1].events = POLLIN;
				pollfds[1].revents = 0;
				if (poll(pollfds, 2, -1) < 0 && errno != EINTR) {
					panic("console poll failed: %s", strerror(errno));
				}
				if (!running) break;
				if (pollfds[0].revents & POLLIN) {
					unsigned char c;
					if (read(pipefds[0], &c, 1) < 0) {
						debug("console: socket: read: %s", strerror(errno));
					} else if (write(STDIN_FILENO, &c, 1) < 0) {
						debug("console: socket: write: %s", strerror(errno));
					}
				}
				if (suspended) continue;
				if (pollfds[1].revents & POLLIN) {
					unsigned char c;
					if (read(STDIN_FILENO, &c, 1) < 0) {
						debug("console: stdin: read: %s", strerror(errno));
					} else {
						queue.push_back(c);
					}
				}
			}
			close_pipe();
			teardown();
		}

		void open_pipe()
		{
			/* create socketpair */
			if (pipe(pipefds) < 0) {
				panic("pipe failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[0], F_SETFD, FD_CLOEXEC) < 0) {
				panic("console fcntl(F_SETFD, FD_CLOEXEC) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[0], F_SETFL, O_NONBLOCK) < 0) {
				panic("console fcntl(F_SETFL, O_NONBLOCK) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[1], F_SETFD, FD_CLOEXEC) < 0) {
				panic("console fcntl(F_SETFD, FD_CLOEXEC) failed: %s", strerror(errno));
			}
			if (fcntl(pipefds[1], F_SETFL, O_NONBLOCK) < 0) {
				panic("console fcntl(F_SETFL, O_NONBLOCK) failed: %s", strerror(errno));
			}
		}

		void close_pipe() {
			close(pipefds[0]);
			close(pipefds[1]);
		}

		/* setup console */
		void setup()
		{
			tcgetattr(STDIN_FILENO, &old_tio);
			new_tio = old_tio;
			new_tio.c_lflag &=(~ICANON & ~ECHO);
			tcsetattr(STDIN_FILENO,TCSANOW,&new_tio);
		}

		/* teardown console */
		void teardown()
		{
			/* restore settings */
			tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
		}

		/* suspend console input */
		void suspend()
		{
			teardown();
			suspended = true;
		}

		/* resume console input */
		void resume()
		{
			setup();
			suspended = false;
		}

		/* shutdown console thread */
		void shutdown()
		{
			/* set running flag to false and write a null byte to the FIFO */
			running = false;
			unsigned char c = 0;
			if (write(pipefds[1], &c, 1) < 0) {
				debug("console: socket: write: %s", strerror(errno));
			}
			/*thread.join();*/
		}

		/* check if data is available */
		bool has_char()
		{
{'fraction_non_alphanumeric': 0.16103978443493422, 'fraction_numerical': 0.013631320336027897, 'mean_word_length': 3.021669853409815, 'pattern_counts': {'":': 0, '<': 27, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6483070', 'n_tokens_mistral': 3073, 'n_tokens_neox': 2498, 'n_words': 540}