summaryrefslogtreecommitdiff
path: root/src/runtime/os_nacl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/runtime/os_nacl.c')
-rw-r--r--src/runtime/os_nacl.c312
1 files changed, 312 insertions, 0 deletions
diff --git a/src/runtime/os_nacl.c b/src/runtime/os_nacl.c
new file mode 100644
index 000000000..14b558303
--- /dev/null
+++ b/src/runtime/os_nacl.c
@@ -0,0 +1,312 @@
+// Copyright 2010 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+#include "runtime.h"
+#include "defs_GOOS_GOARCH.h"
+#include "os_GOOS.h"
+#include "arch_GOARCH.h"
+#include "textflag.h"
+#include "stack.h"
+
+int8 *goos = "nacl";
+extern SigTab runtime·sigtab[];
+
+void runtime·sigtramp(void);
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the parent thread (main thread in case of bootstrap), can allocate memory.
+void
+runtime·mpreinit(M *mp)
+{
+ mp->gsignal = runtime·malg(32*1024); // OS X wants >=8K, Linux >=2K
+ mp->gsignal->m = mp;
+}
+
+// Called to initialize a new m (including the bootstrap m).
+// Called on the new thread, can not allocate memory.
+void
+runtime·minit(void)
+{
+ int32 ret;
+
+ // Initialize signal handling
+ ret = runtime·nacl_exception_stack((byte*)g->m->gsignal->stack.lo, 32*1024);
+ if(ret < 0)
+ runtime·printf("runtime: nacl_exception_stack: error %d\n", -ret);
+
+ ret = runtime·nacl_exception_handler(runtime·sigtramp, nil);
+ if(ret < 0)
+ runtime·printf("runtime: nacl_exception_handler: error %d\n", -ret);
+}
+
+// Called from dropm to undo the effect of an minit.
+void
+runtime·unminit(void)
+{
+}
+
+int8 runtime·sigtrampf[] = "runtime: signal at PC=%X AX=%X CX=%X DX=%X BX=%X DI=%X R15=%X *SP=%X\n";
+int8 runtime·sigtrampp[] = "runtime: sigtramp";
+
+extern byte runtime·tls0[];
+
+void
+runtime·osinit(void)
+{
+ runtime·ncpu = 1;
+ g->m->procid = 2;
+//runtime·nacl_exception_handler(runtime·sigtramp, nil);
+}
+
+void
+runtime·crash(void)
+{
+ *(int32*)0 = 0;
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·get_random_data(byte **rnd, int32 *rnd_len)
+{
+ *rnd = nil;
+ *rnd_len = 0;
+}
+
+void
+runtime·goenvs(void)
+{
+ runtime·goenvs_unix();
+}
+
+void
+runtime·initsig(void)
+{
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·usleep(uint32 us)
+{
+ Timespec ts;
+
+ ts.tv_sec = us/1000000;
+ ts.tv_nsec = (us%1000000)*1000;
+ runtime·nacl_nanosleep(&ts, nil);
+}
+
+void runtime·mstart_nacl(void);
+
+void
+runtime·newosproc(M *mp, void *stk)
+{
+ int32 ret;
+ void **tls;
+
+ tls = (void**)mp->tls;
+ tls[0] = mp->g0;
+ tls[1] = mp;
+ ret = runtime·nacl_thread_create(runtime·mstart_nacl, stk, tls+2, 0);
+ if(ret < 0) {
+ runtime·printf("nacl_thread_create: error %d\n", -ret);
+ runtime·throw("newosproc");
+ }
+}
+
+static void
+semacreate(void)
+{
+ int32 mu, cond;
+
+ mu = runtime·nacl_mutex_create(0);
+ if(mu < 0) {
+ runtime·printf("nacl_mutex_create: error %d\n", -mu);
+ runtime·throw("semacreate");
+ }
+ cond = runtime·nacl_cond_create(0);
+ if(cond < 0) {
+ runtime·printf("nacl_cond_create: error %d\n", -cond);
+ runtime·throw("semacreate");
+ }
+ g->m->waitsemalock = mu;
+ g->m->scalararg[0] = cond; // assigned to m->waitsema
+}
+
+#pragma textflag NOSPLIT
+uint32
+runtime·semacreate(void)
+{
+ void (*fn)(void);
+ uint32 x;
+
+ fn = semacreate;
+ runtime·onM(&fn);
+ x = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return x;
+}
+
+static void
+semasleep(void)
+{
+ int32 ret;
+ int64 ns;
+
+ ns = (int64)(uint32)g->m->scalararg[0] | (int64)(uint32)g->m->scalararg[1]<<32;
+ g->m->scalararg[0] = 0;
+ g->m->scalararg[1] = 0;
+
+ ret = runtime·nacl_mutex_lock(g->m->waitsemalock);
+ if(ret < 0) {
+ //runtime·printf("nacl_mutex_lock: error %d\n", -ret);
+ runtime·throw("semasleep");
+ }
+ if(g->m->waitsemacount > 0) {
+ g->m->waitsemacount = 0;
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = 0;
+ return;
+ }
+
+ while(g->m->waitsemacount == 0) {
+ if(ns < 0) {
+ ret = runtime·nacl_cond_wait(g->m->waitsema, g->m->waitsemalock);
+ if(ret < 0) {
+ //runtime·printf("nacl_cond_wait: error %d\n", -ret);
+ runtime·throw("semasleep");
+ }
+ } else {
+ Timespec ts;
+
+ ns += runtime·nanotime();
+ ts.tv_sec = runtime·timediv(ns, 1000000000, (int32*)&ts.tv_nsec);
+ ret = runtime·nacl_cond_timed_wait_abs(g->m->waitsema, g->m->waitsemalock, &ts);
+ if(ret == -ETIMEDOUT) {
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = -1;
+ return;
+ }
+ if(ret < 0) {
+ //runtime·printf("nacl_cond_timed_wait_abs: error %d\n", -ret);
+ runtime·throw("semasleep");
+ }
+ }
+ }
+
+ g->m->waitsemacount = 0;
+ runtime·nacl_mutex_unlock(g->m->waitsemalock);
+ g->m->scalararg[0] = 0;
+}
+
+#pragma textflag NOSPLIT
+int32
+runtime·semasleep(int64 ns)
+{
+ int32 r;
+ void (*fn)(void);
+
+ g->m->scalararg[0] = (uint32)ns;
+ g->m->scalararg[1] = (uint32)(ns>>32);
+ fn = semasleep;
+ runtime·onM(&fn);
+ r = g->m->scalararg[0];
+ g->m->scalararg[0] = 0;
+ return r;
+}
+
+static void
+semawakeup(void)
+{
+ int32 ret;
+ M *mp;
+
+ mp = g->m->ptrarg[0];
+ g->m->ptrarg[0] = nil;
+
+ ret = runtime·nacl_mutex_lock(mp->waitsemalock);
+ if(ret < 0) {
+ //runtime·printf("nacl_mutex_lock: error %d\n", -ret);
+ runtime·throw("semawakeup");
+ }
+ if(mp->waitsemacount != 0) {
+ //runtime·printf("semawakeup: double wakeup\n");
+ runtime·throw("semawakeup");
+ }
+ mp->waitsemacount = 1;
+ runtime·nacl_cond_signal(mp->waitsema);
+ runtime·nacl_mutex_unlock(mp->waitsemalock);
+}
+
+#pragma textflag NOSPLIT
+void
+runtime·semawakeup(M *mp)
+{
+ void (*fn)(void);
+
+ g->m->ptrarg[0] = mp;
+ fn = semawakeup;
+ runtime·onM(&fn);
+}
+
+uintptr
+runtime·memlimit(void)
+{
+ runtime·printf("memlimit\n");
+ return 0;
+}
+
+#pragma dataflag NOPTR
+static int8 badsignal[] = "runtime: signal received on thread not created by Go.\n";
+
+// This runs on a foreign stack, without an m or a g. No stack split.
+#pragma textflag NOSPLIT
+void
+runtime·badsignal2(void)
+{
+ runtime·write(2, badsignal, sizeof badsignal - 1);
+ runtime·exit(2);
+}
+
+void runtime·madvise(byte*, uintptr, int32) { }
+void runtime·munmap(byte*, uintptr) {}
+
+void
+runtime·resetcpuprofiler(int32 hz)
+{
+ USED(hz);
+}
+
+void
+runtime·sigdisable(uint32)
+{
+}
+
+void
+runtime·sigenable(uint32)
+{
+}
+
+void
+runtime·closeonexec(int32)
+{
+}
+
+uint32 runtime·writelock; // test-and-set spin lock for runtime.write
+
+/*
+An attempt at IRT. Doesn't work. See end of sys_nacl_amd64.s.
+
+void (*runtime·nacl_irt_query)(void);
+
+int8 runtime·nacl_irt_basic_v0_1_str[] = "nacl-irt-basic-0.1";
+void *runtime·nacl_irt_basic_v0_1[6]; // exit, gettod, clock, nanosleep, sched_yield, sysconf
+int32 runtime·nacl_irt_basic_v0_1_size = sizeof(runtime·nacl_irt_basic_v0_1);
+
+int8 runtime·nacl_irt_memory_v0_3_str[] = "nacl-irt-memory-0.3";
+void *runtime·nacl_irt_memory_v0_3[3]; // mmap, munmap, mprotect
+int32 runtime·nacl_irt_memory_v0_3_size = sizeof(runtime·nacl_irt_memory_v0_3);
+
+int8 runtime·nacl_irt_thread_v0_1_str[] = "nacl-irt-thread-0.1";
+void *runtime·nacl_irt_thread_v0_1[3]; // thread_create, thread_exit, thread_nice
+int32 runtime·nacl_irt_thread_v0_1_size = sizeof(runtime·nacl_irt_thread_v0_1);
+*/