aboutsummaryrefslogtreecommitdiff
path: root/src/common.c
blob: 3653252408ff7cba4818db0ad12f7e5f06bbce4e (plain)
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
#include <assert.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <unistd.h>
#include "types.h"
#include "instset.h"
#include "common.h"

static boolean g_is_init;
static int g_file_desc;

void _sal_comm_init(string pipe)
{
	/* Initialize the common pipe. This module is the only one on Salis that
	makes use of Linux specific headers and types. If you want, feel free to
	port this code into other platforms (should be easy). If you do so, let me
	know and we can incorporate it into the Salis repository.
	*/
	assert(!g_is_init);
	mkfifo(pipe, 0666);
	g_is_init = TRUE;

	/* It's important to open the FIFO file in non-blocking mode, or else the
	simulators might halt if the pipe becomes empty.
	*/
	g_file_desc = open(pipe, O_RDWR | O_NONBLOCK);
	assert(g_file_desc != -1);
}

void _sal_comm_quit(void)
{
	/* Close the common pipe FIFO file from within this instance. An empty pipe
	file will remain unless it gets manually deleted.
	*/
	assert(g_is_init);
	close(g_file_desc);
	g_is_init = FALSE;
	g_file_desc = 0;
}

void _sal_comm_send(uint8 inst)
{
	/* Send a single byte (instruction) to the common pipe. This function is
	called by processes that execute the SEND instruction. Hopefully, some of
	them 'learn' to use this as an advantage.

	In the future, I want to make the common pipe able to communicate across
	local networks (LANs) and over the Internet.
	*/
	assert(g_is_init);
	assert(sal_is_inst(inst));
	write(g_file_desc, &inst, 1);
}

uint8 _sal_comm_receive(void)
{
	/* Receive a single byte (instruction) from the common pipe. This function
	is called by processes that execute the RCVE instruction. If the pipe is
	empty, this function returns the NOP0 instruction.
	*/
	uint8 inst;
	ssize_t res;
	assert(g_is_init);
	res = read(g_file_desc, &inst, 1);

	if (res) {
		assert(sal_is_inst(inst));
		return inst;
	} else {
		return NOP0;
	}
}