static void* threadentry(void*);
static void (*setg_gcc)(void*);
-// TCB_SIZE is sizeof(struct thread_control_block),
-// as defined in /usr/src/lib/librthread/tcb.h
+// TCB_SIZE is sizeof(struct thread_control_block), as defined in
+// /usr/src/lib/librthread/tcb.h on OpenBSD 5.9 and earlier.
#define TCB_SIZE (4 * sizeof(void *))
+
+// TIB_SIZE is sizeof(struct tib), as defined in
+// /usr/include/tib.h on OpenBSD 6.0 and later.
+#define TIB_SIZE (4 * sizeof(void *) + 6 * sizeof(int))
+
+// TLS_SIZE is the size of TLS needed for Go.
#define TLS_SIZE (2 * sizeof(void *))
void *__get_tcb(void);
void *arg;
};
+static int has_tib = 0;
+
static void
tcb_fixup(int mainthread)
{
- void *newtcb, *oldtcb;
+ void *tls, *newtcb, *oldtcb;
+ size_t tls_size, tcb_size;
+
+ // TODO(jsing): Remove once OpenBSD 6.1 is released and OpenBSD 5.9 is
+ // no longer supported.
// The OpenBSD ld.so(1) does not currently support PT_TLS. As a result,
// we need to allocate our own TLS space while preserving the existing
- // TCB that has been setup via librthread.
+ // TCB or TIB that has been setup via librthread.
- newtcb = malloc(TCB_SIZE + TLS_SIZE);
- if(newtcb == NULL)
+ tcb_size = has_tib ? TIB_SIZE : TCB_SIZE;
+ tls_size = TLS_SIZE + tcb_size;
+ tls = malloc(tls_size);
+ if(tls == NULL)
abort();
// The signal trampoline expects the TLS slots to be zeroed.
- bzero(newtcb, TLS_SIZE);
+ bzero(tls, TLS_SIZE);
oldtcb = __get_tcb();
- bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
- __set_tcb(newtcb + TLS_SIZE);
+ newtcb = tls + TLS_SIZE;
+ bcopy(oldtcb, newtcb, tcb_size);
+ if(has_tib) {
+ // Fix up self pointer.
+ *(uintptr_t *)(newtcb) = (uintptr_t)newtcb;
+ }
+ __set_tcb(newtcb);
// NOTE(jsing, minux): we can't free oldtcb without causing double-free
// problem. so newtcb will be memory leaks. Get rid of this when OpenBSD
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
+ // _rthread_init is hidden in OpenBSD librthread that has TIB.
+ if(dlsym(handle, "_rthread_init") == NULL) {
+ has_tib = 1;
+ }
dlclose(handle);
}
pthread_attr_init(&attr);
pthread_attr_getstacksize(&attr, &size);
+
// Leave stacklo=0 and set stackhi=size; mstack will do the rest.
ts->g->stackhi = size;
err = sys_pthread_create(&p, &attr, threadentry, ts);
static void* threadentry(void*);
static void (*setg_gcc)(void*);
-// TCB_SIZE is sizeof(struct thread_control_block),
-// as defined in /usr/src/lib/librthread/tcb.h
+// TCB_SIZE is sizeof(struct thread_control_block), as defined in
+// /usr/src/lib/librthread/tcb.h on OpenBSD 5.9 and earlier.
#define TCB_SIZE (4 * sizeof(void *))
+
+// TIB_SIZE is sizeof(struct tib), as defined in
+// /usr/include/tib.h on OpenBSD 6.0 and later.
+#define TIB_SIZE (4 * sizeof(void *) + 6 * sizeof(int))
+
+// TLS_SIZE is the size of TLS needed for Go.
#define TLS_SIZE (2 * sizeof(void *))
void *__get_tcb(void);
void *arg;
};
+static int has_tib = 0;
+
static void
tcb_fixup(int mainthread)
{
- void *newtcb, *oldtcb;
+ void *tls, *newtcb, *oldtcb;
+ size_t tls_size, tcb_size;
+
+ // TODO(jsing): Remove once OpenBSD 6.1 is released and OpenBSD 5.9 is
+ // no longer supported.
// The OpenBSD ld.so(1) does not currently support PT_TLS. As a result,
// we need to allocate our own TLS space while preserving the existing
- // TCB that has been setup via librthread.
+ // TCB or TIB that has been setup via librthread.
- newtcb = malloc(TCB_SIZE + TLS_SIZE);
- if(newtcb == NULL)
+ tcb_size = has_tib ? TIB_SIZE : TCB_SIZE;
+ tls_size = TLS_SIZE + tcb_size;
+ tls = malloc(tls_size);
+ if(tls == NULL)
abort();
// The signal trampoline expects the TLS slots to be zeroed.
- bzero(newtcb, TLS_SIZE);
+ bzero(tls, TLS_SIZE);
oldtcb = __get_tcb();
- bcopy(oldtcb, newtcb + TLS_SIZE, TCB_SIZE);
- __set_tcb(newtcb + TLS_SIZE);
+ newtcb = tls + TLS_SIZE;
+ bcopy(oldtcb, newtcb, tcb_size);
+ if(has_tib) {
+ // Fix up self pointer.
+ *(uintptr_t *)(newtcb) = (uintptr_t)newtcb;
+ }
+ __set_tcb(newtcb);
// NOTE(jsing, minux): we can't free oldtcb without causing double-free
// problem. so newtcb will be memory leaks. Get rid of this when OpenBSD
fprintf(stderr, "runtime/cgo: dlsym failed to find pthread_create: %s\n", dlerror());
abort();
}
+ // _rthread_init is hidden in OpenBSD librthread that has TIB.
+ if(dlsym(handle, "_rthread_init") == NULL) {
+ has_tib = 1;
+ }
dlclose(handle);
}