:"m" (idle_thread->thr_ip));
#endif
}
+
+void arch__switch(unsigned long *, unsigned long *);
+void
+arch_switch_threads(struct thread *prev, struct thread *next)
+{
+
+/* XXX: TLS is available only on x86_64 currently */
+#if defined(__x86_64__)
+ wrmsrl(0xc0000100, next->thr_tp);
+#endif
+
+ arch__switch(&prev->thr_sp, &next->thr_sp);
+}
struct thread_md {
unsigned long thrmd_sp;
unsigned long thrmd_ip;
+ unsigned long thrmd_tp;
+ unsigned long thrmd_tl;
};
#define thr_sp md.thrmd_sp
#define thr_ip md.thrmd_ip
+#define thr_tp md.thrmd_tp
+#define thr_tl md.thrmd_tl
-extern void _minios_entry_arch_switch_threads(unsigned long *prevctx, unsigned long *nextctx);
+extern void _minios_entry_arch_switch_threads(struct thread *prevctx, struct thread *nextctx);
-#define arch_switch_threads(prev,next) _minios_entry_arch_switch_threads(&(prev)->thr_sp, &(next)->thr_sp)
+#define arch_switch_threads(prev,next) _minios_entry_arch_switch_threads(prev, next)
#endif /* __ARCH_SCHED_H__ */
#include <sys/queue.h>
+#include <string.h> /* XXX: for mem{cpy,set}() */
+
TAILQ_HEAD(thread_list, thread);
struct thread *idle_thread = NULL;
}
}
+/*
+ * Allocate tls and initialize it.
+ *
+ * XXX: this needs to change in the future so that
+ * we put the tcb in the same space instead of having multiple
+ * random copies flying around.
+ */
+extern const char _tdata_start[], _tdata_end[];
+extern const char _tbss_start[], _tbss_end[];
+static int
+allocothertls(struct thread *thread)
+{
+ const size_t tdatasize = _tdata_end - _tdata_start;
+ const size_t tbsssize = _tbss_end - _tbss_start;
+ uint8_t *tlsmem;
+
+ tlsmem = memalloc(tdatasize + tbsssize, 0);
+
+ memcpy(tlsmem, _tdata_start, tdatasize);
+ memset(tlsmem + tdatasize, 0, tbsssize);
+
+ thread->thr_tp = (uintptr_t)(tlsmem + tdatasize + tbsssize);
+ thread->thr_tl = tdatasize + tbsssize;
+
+ return 0;
+}
+
+static void
+freeothertls(struct thread *thread)
+{
+ void *mem;
+
+ mem = (void *)(thread->thr_tp);
+ memfree(mem);
+}
+
struct thread *
minios_create_thread(const char *name, void *cookie,
void (*function)(void *), void *data, void *stack)
thread->lwp = NULL;
thread->cookie = cookie;
set_runnable(thread);
+ allocothertls(thread);
local_irq_save(flags);
TAILQ_INSERT_TAIL(&thread_list, thread, thread_list);
local_irq_restore(flags);
TAILQ_INSERT_HEAD(&exited_threads, thread, thread_list);
local_irq_restore(flags);
+ freeothertls(thread);
+
/* Schedule will free the resources */
while(1)
{
{
current->cookie = cookie;
+ allocothertls(current);
return current;
}