#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
+#include <fcntl.h>
#include <string.h>
#include <pthread.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <termios.h>
#ifdef CONFIG_MODULE_SCHEDULER
#include <scheduler.h>
#endif
+#ifdef CONFIG_MODULE_UART
+#include <uart_host.h>
+#endif
-pthread_mutex_t mut;
+static pthread_mutex_t mut = PTHREAD_MUTEX_INITIALIZER;
static volatile int cpt = 0;
+static struct termios oldterm;
+/* static */ int old_stdin, old_stdout;
+static int stdin_pipe[2];
+static int stdout_pipe[2];
+
+enum msg_type {
+ SCHED,
+ UART_RCV,
+ UART_SND,
+};
+
+struct message {
+ enum msg_type type;
+ char c;
+};
+static struct message g_msg;
+
#ifdef SA_SIGINFO
static void sigusr1(__attribute__((unused)) int sig,
__attribute__((unused)) siginfo_t *info,
void sigusr1(__attribute__((unused)) int sig)
#endif
{
- pthread_mutex_unlock(&mut);
+ struct message m;
+ m = g_msg;
#ifdef CONFIG_MODULE_SCHEDULER
- scheduler_interrupt();
+ if (m.type == SCHED) {
+ pthread_mutex_unlock(&mut);
+ scheduler_interrupt();
+ }
#endif
+
+#ifdef CONFIG_MODULE_UART
+ if (m.type == UART_RCV) {
+ uart_host_rx_event(m.c);
+ pthread_mutex_unlock(&mut);
+ }
+ if (m.type == UART_SND) {
+ uart_host_tx_event(m.c);
+ pthread_mutex_unlock(&mut);
+ }
+#endif
+}
+
+static int lock_count = 0;
+
+void hostsim_lock(void)
+{
+ if (lock_count++)
+ return;
+ pthread_mutex_lock(&mut);
+}
+
+void hostsim_unlock(void)
+{
+ if (lock_count-- == 1)
+ pthread_mutex_unlock(&mut);
+}
+
+int hostsim_islocked(void)
+{
+ return lock_count;
}
void host_wait_ms(int ms)
/* sends signal to child */
void *parent(void *arg)
{
- pthread_t *thread = arg;
+ pthread_t thread = (pthread_t)arg;
struct timeval cur_tv, prev_tv, tv_millisec;
int n;
n = 0;
}
pthread_mutex_lock(&mut);
- pthread_kill(*thread, SIGUSR1);
+ g_msg.type = SCHED;
+ pthread_kill(thread, SIGUSR1);
/* signal was acked */
tv_millisec.tv_sec = 0;
return NULL;
}
+void *hostsim_uart_stdin(void *arg)
+{
+ pthread_t thread = (pthread_t)arg;
+ int n;
+ char c;
+
+ /* read on old stdin and put it in pipe */
+ while (1) {
+ n = read(old_stdin, &c, 1);
+ if (n <= 0)
+ break;
+
+ pthread_mutex_lock(&mut);
+ g_msg.type = UART_RCV;
+ g_msg.c = c;
+ pthread_kill(thread, SIGUSR1);
+
+ write(stdin_pipe[1], &c, 1);
+ }
+ pthread_exit(NULL);
+ return NULL;
+}
+
+void *hostsim_uart_stdout(void *arg)
+{
+ pthread_t thread = (pthread_t)arg;
+ int n;
+ char c;
+
+ /* read on our pipe, and forward it to the old stdout */
+ while (1) {
+ n = read(stdout_pipe[0], &c, 1);
+ if (n <= 0)
+ break;
+
+ pthread_mutex_lock(&mut);
+ g_msg.type = UART_SND;
+ g_msg.c = c;
+ pthread_kill(thread, SIGUSR1);
+
+ write(old_stdout, &c, 1);
+ }
+ pthread_exit(NULL);
+ return NULL;
+}
+
+int hostsim_uart_init(void)
+{
+ struct termios term;
+
+ tcgetattr(0, &oldterm);
+ memcpy(&term, &oldterm, sizeof(term));
+ term.c_lflag &= ~(ICANON | ECHO | ISIG);
+ tcsetattr(0, TCSANOW, &term);
+
+ /* duplicate stdin */
+ old_stdin = dup(0);
+ if (old_stdin < 0)
+ return 1;
+
+ /* duplicate stdout */
+ old_stdout = dup(1);
+ if (old_stdout < 0)
+ return -1;
+
+ /* create 2 pipes */
+ if (pipe(stdin_pipe) < 0)
+ return -1;
+ if (pipe(stdout_pipe) < 0)
+ return -1;
+
+ /* replace file desc 0 (stdin) by our pipe */
+ if (dup2(stdin_pipe[0], 0) < 0)
+ return -1;
+ close(stdin_pipe[0]);
+
+ /* replace file desc 1 (stdout) by our pipe */
+ if (dup2(stdout_pipe[1], 1) < 0)
+ return -1;
+ close(stdout_pipe[1]);
+ setbuf(stdin, NULL);
+ setbuf(stdout, NULL);
+
+ return 0;
+}
+
int hostsim_init(void)
{
struct sigaction sigact;
- pthread_t parent_id, child_id;
+ pthread_t parent_id, child_id, child2_id, child3_id;
int ret;
- pthread_mutex_init(&mut, NULL);
-
parent_id = pthread_self();
pthread_mutex_lock(&mut);
- ret = pthread_create(&child_id, NULL, parent, (void *)&parent_id);
+ ret = pthread_create(&child_id, NULL, parent, (void *)parent_id);
+ if (ret) {
+ printf("pthread_create() returned %d\n", ret);
+ pthread_mutex_unlock(&mut);
+ return -1;
+ }
+
+#ifdef CONFIG_MODULE_UART
+ if (hostsim_uart_init())
+ return -1;
+
+ ret = pthread_create(&child2_id, NULL, hostsim_uart_stdin, (void *)parent_id);
+ if (ret) {
+ printf("pthread_create() returned %d\n", ret);
+ pthread_mutex_unlock(&mut);
+ return -1;
+ }
+ ret = pthread_create(&child3_id, NULL, hostsim_uart_stdout, (void *)parent_id);
if (ret) {
printf("pthread_create() returned %d\n", ret);
pthread_mutex_unlock(&mut);
return -1;
}
+#endif
/* register a signal handler, which is interruptible */
memset(&sigact, 0, sizeof(sigact));
return 0;
}
+
+int hostsim_exit(void)
+{
+#ifdef CONFIG_MODULE_UART
+ tcsetattr(0, TCSANOW, &oldterm);
+#endif
+ return 0;
+}
#endif /* HOST_VERSION */