extern void mon_wait(Mon *m, int ms) { int res = 0; if (ms < 0) { res = pthread_cond_wait(m->cond, m->mutex); } else { long long end = sys_millis() + ms; struct timespec timeout = { .tv_sec = end / 1000LL, .tv_nsec = (end % 1000LL) * 1000000LL }; res = pthread_cond_timedwait(m->cond, m->mutex, &timeout); } if (res != 0 && res != ETIMEDOUT) { errno = res; sys_die("monitor: wait failed\n"); } } extern void mon_signal(Mon *m) { int res = pthread_cond_signal(m->cond); if (res != 0) { errno = res; sys_die("monitor: signal failed\n"); } }
extern void sys_thread(void *(*fn)(void *arg), void *arg) { pthread_t t; if (pthread_create(&t, NULL, fn, arg) != 0) sys_die("sys: cannot create a thread\n"); if (pthread_detach(t) != 0) sys_die("sys: cannot detach from a thread\n"); }
int main() { pid_t pid; struct sys_hwcreat_cfg cfg; printf("Hello!\n"); cfg.nameid = squoze("platform"); cfg.nirqsegs = 1; cfg.npiosegs = 0; cfg.nmemsegs = 0; cfg.segs[0].base = 1; /* IRQ 1 */ cfg.segs[0].len = 1; printf("creat[%llx]: %d\n", cfg.nameid, sys_hwcreat(&cfg, 0111)); if (sys_fork() == 0) goto child; inthandler(INTR_CHILD, do_child, NULL); lwt_sleep(); child: if (sys_fork()) sys_die(-3); /* Child of Child */ printf("Opening platform [%llx]\n", squoze("platform")); printf("open[%llx]: %d\n", squoze("platform"), sys_open(squoze("platform"))); printf("irqmap[%llx]: %d\n", squoze("platform"), sys_mapirq(0, 1, 5)); lwt_sleep(); printf("Goodbye!"); sys_die(5); #if 0 int j; size_t len; struct diodevice *dc; struct iovec iov[11]; uint64_t val; do { dc = dirtio_pipe_open(500); } while(dc == NULL); dirtio_mmio_inw(&dc->desc, PORT_DIRTIO_MAGIC, 0, &val); printf("PORT_DIRTIO_MAGIC is %"PRIx64"\n", val); dirtio_mmio_inw(&dc->desc, PORT_DIRTIO_MAGIC, 0, &val); printf("PORT_DIRTIO_MAGIC is %"PRIx64"\n", val); len = dirtio_allocv(dc, iov, 11, 11 * 128 * 1024 - 1); for (j = 0; j < 11; j++) printf("\t%p -> %d\n", iov[j].iov_base, iov[j].iov_len); dioqueue_addv(&dc->dqueues[0], 1, 10, iov); #endif }
extern void net_close(IO *io) { int res = shutdown(io->fd, SHUT_RDWR); if (res < 0 && errno != ENOTCONN) sys_die("sys: cannot shutdown socket\n"); res = close(io->fd); if (res < 0) sys_die("sys: cannot close socket\n"); }
extern int sys_exec(char *const argv[]) { pid_t pid; if ((pid = fork()) == 0) { execvp(argv[0], argv); sys_die("sys: execv of %s failed\n", argv[0]); } else if (pid < 0) sys_die("sys: cannot create a child process\n"); return pid; }
extern void mon_wait(Mon *m, int ms) { DWORD timeout = INFINITE; if (ms >= 0) timeout = ms; if (!ResetEvent(m->cond)) sys_die("monitor: reset failed\n"); LeaveCriticalSection(m->mutex); int res = WaitForSingleObject(m->cond, timeout); if (res != WAIT_OBJECT_0 && res != WAIT_TIMEOUT) sys_die("monitor: wait failed\n"); EnterCriticalSection(m->mutex); }
extern Mon *mon_new() { Mon *res = mem_alloc(sizeof(Mon)); res->value = 0; res->mutex = mem_alloc(sizeof(CRITICAL_SECTION)); if (!InitializeCriticalSectionAndSpinCount(res->mutex, 0)) sys_die("monitor: initialize critical section failed\n"); res->cond = CreateEvent(NULL, 1, 0, NULL); if (res->cond == NULL) sys_die("monitor: create event failed\n"); return res; }
extern void mon_free(Mon *m) { int res = pthread_mutex_destroy(m->mutex); if (res != 0) { errno = res; sys_die("monitor: mutex destroy failed\n"); } res = pthread_cond_destroy(m->cond); if (res != 0) { errno = res; sys_die("monitor: cond destroy failed\n"); } mem_free(m); }
extern void mon_unlock(Mon *m) { int res = pthread_mutex_unlock(m->mutex); if (res != 0) { errno = res; sys_die("monitor: unlock failed\n"); } }
extern void sys_thread(void *(*fn)(void *arg), void *arg) { DWORD id; HANDLE h = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fn, arg, 0, &id); if (h == NULL) sys_die("sys: cannot create a thread\n"); }
static int parse_port(char *p) { int port = 0, e = -1; port = str_int(p, &e); if (e || port < 1 || port > 65535) sys_die("invalid port '%s'\n", p); return port; }
extern int net_port(int fd) { struct sockaddr_in addr; unsigned int size = sizeof(addr); if (getsockname(fd, (struct sockaddr*) &addr, &size) < 0) sys_die("sys: cannot lookup the socket details\n"); return ntohs(addr.sin_port); }
extern void sys_init(int log) { SetLastError(0); str_init(); glog = log; WSADATA wsa_data; if (WSAStartup(MAKEWORD(2, 2), &wsa_data)) sys_die("sys: cannot initialise winsock2\n"); }
extern char sys_wait(int pid) { int res, status; do { res = waitpid(pid, &status, WUNTRACED | WCONTINUED); } while (res < 0 && errno == EINTR); if (res < 0) sys_die("sys: wait for child pid %d failed\n", pid); return WIFEXITED(status) ? WEXITSTATUS(status) : PROC_FAIL; }
extern IO *sys_accept(IO *sock, int chunked) { int fd = -1; do { fd = accept(sock->fd, NULL, NULL); } while ((fd < 0) && (errno == ECONNABORTED)); if (fd < 0) sys_die("sys: cannot accept incoming connection\n"); return new_net_io(fd, chunked); }
extern char sys_wait(int pid) { HANDLE ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); if (ph == NULL) return -1; WaitForSingleObject(ph, INFINITE); DWORD result = -1; if (!GetExitCodeProcess(ph, &result)) sys_die("sys: cannot get process %d exit code\n", pid); CloseHandle(ph); return result; }
extern int sys_exec(char *const a[]) { STARTUPINFO si; PROCESS_INFORMATION pi; ZeroMemory(&pi, sizeof(pi)); ZeroMemory(&si, sizeof(si)); si.cb = sizeof(si); char c[1024] = ""; str_print(c, "\"%s\" ", a[0]); for (int i = 1; a[i] != NULL; ++i) str_print(c, "%s %s", c, a[i]); if (!CreateProcess(NULL, c, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) sys_die("sys: cannot create process\n"); CloseHandle(pi.hProcess); CloseHandle(pi.hThread); return pi.dwProcessId; }
static void usage(char *p) { sys_print("usage: %s <command> <args>\n\n", p); sys_print("standalone commands:\n"); sys_print(" start -p <port> -d <data.dir> -c <source.file>" " -s <state.file>\n\n"); sys_print("distributed commands:\n"); sys_print(" tx -p <port> -c <source.file> -s <state.file>\n"); sys_print(" vol -p <port> -d <data.dir> -t <tx.host:port>\n"); sys_print(" exec -p <port> -t <tx.host:port>\n\n"); sys_print("program converter (v5 syntax):\n"); sys_print( " convert - transforms v4 programs to the v5 syntax. the source program is\n"); sys_print( " read from stdin and the result is printed to stdout. all identifiers\n"); sys_print( " which clash with the new keywords will be prefixed with '___'. please\n"); sys_print( " ensure that you review the resulting program.\n\n"); sys_die(VERSION); }
extern void net_close(IO *io) { if (closesocket(io->fd) != 0) sys_die("sys: cannot close socket\n"); }
extern void mon_signal(Mon *m) { if (!SetEvent(m->cond)) sys_die("monitor: signal failed\n"); }
int main(int argc, char *argv[]) { int port = 0; char *data = NULL; char *state = NULL; char *source = NULL; char *tx_addr = NULL; sys_init(1); if (argc < 2) usage(argv[0]); for (int i = 2; (i + 1) < argc; i += 2) if (str_cmp(argv[i], "-d") == 0) data = argv[i + 1]; else if (str_cmp(argv[i], "-c") == 0) source = argv[i + 1]; else if (str_cmp(argv[i], "-s") == 0) state = argv[i + 1]; else if (str_cmp(argv[i], "-p") == 0) port = parse_port(argv[i + 1]); else if (str_cmp(argv[i], "-t") == 0) { tx_addr = argv[i + 1]; if (str_len(tx_addr) >= MAX_ADDR) sys_die("tx address exceeds the maximum length\n"); } else usage(argv[0]); if (str_cmp(argv[1], "start") == 0 && source != NULL && data != NULL && state != NULL && port != 0 && tx_addr == NULL) { int tx_port = 0; tx_server(source, state, &tx_port); vol_init(0, data); char addr[MAX_ADDR]; str_print(addr, "127.0.0.1:%d", tx_port); multiplex(argv[0], addr, port); tx_free(); } else if (str_cmp(argv[1], "processor") == 0 && source == NULL && data == NULL && state == NULL && port != 0 && tx_addr != NULL) { processor(tx_addr, port); } else if (str_cmp(argv[1], "tx") == 0 && source != NULL && data == NULL && state != NULL && port != 0 && tx_addr == NULL) { tx_server(source, state, &port); } else if (str_cmp(argv[1], "vol") == 0 && source == NULL && data != NULL && state == NULL && port != 0 && tx_addr != NULL) { tx_attach(tx_addr); vol_init(port, data); } else if (str_cmp(argv[1], "exec") == 0 && source == NULL && data == NULL && state == NULL && port != 0 && tx_addr != NULL) { tx_attach(tx_addr); multiplex(argv[0], tx_addr, port); } else if (str_cmp(argv[1], "convert") == 0 && source == NULL && data == NULL && state == NULL && port == 0 && tx_addr == NULL) { conv_parse(); } else usage(argv[0]); return 0; }