/uspace/trunk/init/init.c |
---|
39,6 → 39,8 |
int a; |
atomic_t ftx; |
int __thread tls_prom; |
extern void utest(void *arg); |
void utest(void *arg) |
{ |
255,11 → 257,14 |
static int ptest(void *arg) |
{ |
printf("Pseudo thread stage1.\n"); |
tls_prom = -1; |
printf("Pseudo thread stage%d.\n", -tls_prom); |
tls_prom = -2; |
psthread_schedule_next(); |
printf("Pseudo thread stage2.\n"); |
printf("Pseudo thread stage%d.\n", -tls_prom); |
tls_prom = -3; |
psthread_schedule_next(); |
printf("Pseudo thread stage3.\n"); |
printf("Pseudo thread stage%d\n", -tls_prom); |
psthread_schedule_next(); |
printf("Pseudo thread stage4.\n"); |
psthread_schedule_next(); |
290,7 → 295,7 |
if (futex_down(&ftx) < 0) |
printf("Futex failed.\n"); |
/* |
if ((tid = thread_create(utest, NULL, "utest")) != -1) { |
printf("Created thread tid=%d\n", tid); |
} |
298,7 → 303,7 |
if ((tid = thread_create(utest, NULL, "utest")) != -1) { |
printf("Created thread tid=%d\n", tid); |
} |
*/ |
int i; |
for (i = 0; i < 50000000; i++) |
307,12 → 312,17 |
if (futex_up(&ftx) < 0) |
printf("Futex failed.\n"); |
printf("Creating pathread\n"); |
tls_prom = 1; |
ptid = psthread_create(ptest, NULL); |
printf("Main thread stage1.\n"); |
printf("Main thread stage%d\n",tls_prom); |
tls_prom = 2; |
psthread_schedule_next();; |
printf("Main thread stage2.\n"); |
printf("Main thread stage%d\n", tls_prom); |
tls_prom = 3; |
psthread_schedule_next();; |
printf("Main thread stage3.\n"); |
printf("Main thread stage%d\n", tls_prom); |
psthread_join(ptid); |
/uspace/trunk/libc/include/thread.h |
---|
31,6 → 31,7 |
#include <kernel/proc/uarg.h> |
#include <libarch/thread.h> |
#include <types.h> |
extern void __thread_entry(void); |
extern void __thread_main(uspace_arg_t *uarg); |
37,7 → 38,9 |
extern int thread_create(void (* function)(void *arg), void *arg, char *name); |
extern void thread_exit(int status); |
void * __make_tls(void); |
void __free_tls(void *); |
tcb_t * __make_tls(void); |
tcb_t * __alloc_tls(void **data, size_t size); |
void __free_tls(tcb_t *); |
void __free_tls_arch(tcb_t *, size_t size); |
#endif |
/uspace/trunk/libc/include/psthread.h |
---|
31,6 → 31,7 |
#include <libarch/psthread.h> |
#include <libadt/list.h> |
#include <libarch/thread.h> |
#ifndef context_set |
#define context_set(c, _pc, stack, size, ptls) \ |
42,13 → 43,12 |
typedef sysarg_t pstid_t; |
struct psthread_data { |
struct psthread_data *self; /* ia32, amd64 needs to get self address */ |
link_t link; |
context_t ctx; |
void *stack; |
void *arg; |
int (*func)(void *); |
tcb_t *tcb; |
struct psthread_data *waiter; |
int finished; |
63,5 → 63,8 |
pstid_t psthread_create(int (*func)(void *), void *arg); |
int psthread_schedule_next(void); |
int psthread_join(pstid_t psthrid); |
psthread_data_t * psthread_setup(tcb_t *tcb); |
void psthread_teardown(psthread_data_t *pt); |
#endif |
/uspace/trunk/libc/generic/thread.c |
---|
32,21 → 32,38 |
#include <arch/faddr.h> |
#include <kernel/proc/uarg.h> |
#include <psthread.h> |
#include <string.h> |
#include <stdio.h> |
void * __make_tls(void) |
extern char _tdata_start; |
extern char _tdata_end; |
extern char _tbss_start; |
extern char _tbss_end; |
/** Create Thread Local storage area, return pointer to TCB(ThreadControlBlock) |
* |
* !! The code requires, that sections .tdata and .tbss are adjacent. |
* It may be changed in the future. |
*/ |
tcb_t * __make_tls(void) |
{ |
psthread_data_t *pt; |
void *data; |
tcb_t *tcb; |
size_t tls_size = &_tbss_end - &_tdata_start; |
pt = malloc(sizeof(psthread_data_t)); |
pt->self = pt; |
tcb = __alloc_tls(&data, tls_size); |
return pt; |
memcpy(data, &_tdata_start, &_tdata_end - &_tdata_start); |
memset(data + (&_tbss_start-&_tdata_start), &_tbss_end-&_tbss_start, 0); |
return tcb; |
} |
void __free_tls(void *tls) |
void __free_tls(tcb_t *tcb) |
{ |
free(tls); |
size_t tls_size = &_tbss_end - &_tdata_start; |
__free_tls_arch(tcb, tls_size); |
} |
/** Main thread function. |
60,14 → 77,18 |
*/ |
void __thread_main(uspace_arg_t *uarg) |
{ |
tcb_t *tcb; |
/* This should initialize the area according to TLS specicification */ |
__tls_set(__make_tls()); |
tcb = __make_tls(); |
__tcb_set(tcb); |
psthread_setup(tcb); |
uarg->uspace_thread_function(uarg->uspace_thread_arg); |
free(uarg->uspace_stack); |
free(uarg); |
__free_tls(__tls_get()); |
psthread_teardown(tcb->pst_data); |
__free_tls(tcb); |
thread_exit(0); |
} |
/uspace/trunk/libc/generic/libc.c |
---|
36,12 → 36,20 |
thread_exit(status); |
} |
#include <stdio.h> |
void __main(void) { |
__tls_set(__make_tls()); |
tcb_t *tcb; |
tcb = __make_tls(); |
__tcb_set(tcb); |
psthread_setup(tcb); |
} |
void __exit(void) { |
free(__tls_get()); |
tcb_t *tcb; |
tcb = __tcb_get(); |
psthread_teardown(tcb->pst_data); |
__free_tls(tcb); |
_exit(0); |
} |
/uspace/trunk/libc/generic/psthread.c |
---|
39,6 → 39,27 |
static void psthread_exit(void) __attribute__ ((noinline)); |
static void psthread_main(void); |
/** Setup PSthread information into TCB structure */ |
psthread_data_t * psthread_setup(tcb_t *tcb) |
{ |
psthread_data_t *pt; |
pt = malloc(sizeof(*pt)); |
if (!pt) { |
return NULL; |
} |
tcb->pst_data = pt; |
pt->tcb = tcb; |
return pt; |
} |
void psthread_teardown(psthread_data_t *pt) |
{ |
free(pt); |
} |
/** Function to preempt to other pseudo thread without adding |
* currently running pseudo thread to ready_list. |
*/ |
59,7 → 80,8 |
/** Function that is called on entry to new uspace thread */ |
void psthread_main(void) |
{ |
psthread_data_t *pt = __tls_get(); |
psthread_data_t *pt = __tcb_get()->pst_data; |
pt->retval = pt->func(pt->arg); |
pt->finished = 1; |
80,7 → 102,7 |
if (list_empty(&ready_list)) |
return 0; |
pt = __tls_get(); |
pt = __tcb_get()->pst_data; |
if (!context_save(&pt->ctx)) |
return 1; |
103,11 → 125,10 |
volatile int retval; |
/* Handle psthrid = Kernel address -> it is wait for call */ |
pt = (psthread_data_t *) psthrid; |
if (!pt->finished) { |
mypt = __tls_get(); |
mypt = __tcb_get()->pst_data; |
if (context_save(&((psthread_data_t *) mypt)->ctx)) { |
pt->waiter = (psthread_data_t *) mypt; |
psthread_exit(); |
116,7 → 137,8 |
retval = pt->retval; |
free(pt->stack); |
__free_tls((psthread_data_t *) pt); |
__free_tls(pt->tcb); |
psthread_teardown((void *)pt); |
return retval; |
} |
132,11 → 154,22 |
pstid_t psthread_create(int (*func)(void *), void *arg) |
{ |
psthread_data_t *pt; |
tcb_t *tcb; |
pt = __make_tls(); |
tcb = __make_tls(); |
if (!tcb) |
return 0; |
pt = psthread_setup(tcb); |
if (!pt) { |
__free_tls(tcb); |
return 0; |
} |
pt->stack = (char *) malloc(getpagesize()); |
if (!pt->stack) { |
__free_tls(tcb); |
psthread_teardown(pt); |
return 0; |
} |
146,7 → 179,8 |
pt->waiter = NULL; |
context_save(&pt->ctx); |
context_set(&pt->ctx, FADDR(psthread_main), pt->stack, getpagesize(), pt); |
context_set(&pt->ctx, FADDR(psthread_main), pt->stack, getpagesize(), |
tcb); |
list_append(&pt->link, &ready_list); |
/uspace/trunk/libc/arch/ia64/_link.ld.in |
---|
26,6 → 26,16 |
*(.data); |
*(.sdata); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
.bss : { |
*(.sbss); |
*(.scommon); |
/uspace/trunk/libc/arch/ia64/include/thread.h |
---|
29,12 → 29,18 |
#ifndef __LIBC__ia64THREAD_H__ |
#define __LIBC__ia64THREAD_H__ |
static inline void __tls_set(void *tls) |
/* This structure must be exactly 16 bytes long */ |
typedef struct { |
void *dtv; /* unused in static linking*/ |
void *pst_data; |
} tcb_t; |
static inline void __tcb_set(tcb_t *tcb) |
{ |
__asm__ volatile ("mov r13 = %0\n" : : "r" (tls) : "r13"); |
__asm__ volatile ("mov r13 = %0\n" : : "r" (tcb) : "r13"); |
} |
static inline void *__tls_get(void) |
static inline tcb_t *__tcb_get(void) |
{ |
void *retval; |
/uspace/trunk/libc/arch/ia64/Makefile.inc |
---|
36,4 → 36,5 |
AFLAGS += |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/psthread.S |
arch/$(ARCH)/src/psthread.S \ |
arch/$(ARCH)/src/thread.c |
/uspace/trunk/libc/arch/ia64/src/thread.c |
---|
0,0 → 1,54 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <thread.h> |
#include <malloc.h> |
/** Allocate TLS & TCB for initial module threads |
* |
* @param data Start of data section |
* @return pointer to tcb_t structure |
*/ |
extern char _tdata_start; |
extern char _tbss_end; |
tcb_t * __alloc_tls(void **data, size_t size) |
{ |
tcb_t *tcb; |
/* ASSERT(sizeof(tcb_t) == 16); */ |
tcb = malloc(sizeof(tcb_t) + size); |
*data = ((void *) tcb) + 16; |
return tcb; |
} |
void __free_tls_arch(tcb_t *tcb, size_t size) |
{ |
free(tcb); |
} |
/uspace/trunk/libc/arch/amd64/_link.ld.in |
---|
20,6 → 20,17 |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
.bss : { |
*(COMMON); |
*(.bss); |
/uspace/trunk/libc/arch/amd64/include/thread.h |
---|
31,12 → 31,17 |
#include <libc.h> |
static inline void __tls_set(void *tls) |
typedef struct { |
void *self; |
void *pst_data; |
} tcb_t; |
static inline void __tcb_set(tcb_t *tcb) |
{ |
__SYSCALL1(SYS_TLS_SET, (sysarg_t) tls); |
__SYSCALL1(SYS_TLS_SET, (sysarg_t) tcb); |
} |
static inline void * __tls_get(void) |
static inline tcb_t * __tcb_get(void) |
{ |
void * retval; |
/uspace/trunk/libc/arch/amd64/Makefile.inc |
---|
33,6 → 33,7 |
TOOLCHAIN_DIR = /usr/local/amd64/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.S \ |
arch/$(ARCH)/src/psthread.S |
arch/$(ARCH)/src/psthread.S \ |
arch/$(ARCH)/src/thread.c |
LFLAGS += -N |
/uspace/trunk/libc/arch/amd64/src/thread.c |
---|
0,0 → 1,53 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <thread.h> |
#include <malloc.h> |
/** Allocate TLS & TCB for initial module threads |
* |
* @param data Start of data section |
* @return pointer to tcb_t structure |
*/ |
tcb_t * __alloc_tls(void **data, size_t size) |
{ |
tcb_t *tcb; |
*data = malloc(sizeof(tcb_t) + size); |
tcb = (tcb_t *) (*data + size); |
tcb->self = tcb; |
return tcb; |
} |
void __free_tls_arch(tcb_t *tcb, size_t size) |
{ |
void *start = ((void *)tcb) - size; |
free(start); |
} |
/uspace/trunk/libc/arch/mips32/_link.ld.in |
---|
21,10 → 21,23 |
*(.data); |
*(.data.rel*); |
} :data |
.got : { |
_gp = .; |
*(.got); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
.sbss : { |
*(.scommon); |
*(.sbss); |
/uspace/trunk/libc/arch/mips32/include/psthread.h |
---|
31,6 → 31,17 |
#include <types.h> |
/* We define our own context_set, because we need to set |
* the TLS pointer to the tcb+0x7000 |
* |
* See tls_set in thread.h |
*/ |
#define context_set(c, _pc, stack, size, ptls) \ |
(c)->pc = (sysarg_t) (_pc); \ |
(c)->sp = ((sysarg_t) (stack)) + (size) - SP_DELTA; \ |
(c)->tls = ((sysarg_t)(ptls)) + 0x7000 + sizeof(tcb_t); |
/* +16 is just for sure that the called function |
* have space to store it's arguments |
*/ |
/uspace/trunk/libc/arch/mips32/include/thread.h |
---|
31,17 → 31,39 |
#ifndef __LIBC__mips32THREAD_H__ |
#define __LIBC__mips32THREAD_H__ |
static inline void __tls_set(void *tls) |
/* I did not find any specification (neither MIPS nor PowerPC), but |
* as I found it |
* - it uses Variant II |
* - TCB is at Address(First TLS Block)+0x7000. |
* - DTV is at Address(First TLS Block)+0x8000 |
* - What would happen if the TLS data was larger then 0x7000? |
* - The linker never accesses DTV directly, has the second definition any |
* sense? |
* We will make it this way: |
* - TCB is at TP-0x7000-sizeof(tcb) |
* - No assumption about DTV etc., but it will not have a fixed address |
*/ |
#define MIPS_TP_OFFSET 0x7000 |
typedef struct { |
void *pst_data; |
} tcb_t; |
static inline void __tcb_set(tcb_t *tcb) |
{ |
__asm__ volatile ("add $27, %0, $0" : : "r"(tls)); /* Move tls to K1 */ |
void *tp = tcb; |
tp += MIPS_TP_OFFSET + sizeof(tcb_t); |
__asm__ volatile ("add $27, %0, $0" : : "r"(tp)); /* Move tls to K1 */ |
} |
static inline void * __tls_get(void) |
static inline tcb_t * __tcb_get(void) |
{ |
void * retval; |
__asm__ volatile("add %0, $27, $0" : "=r"(retval)); |
return retval; |
return (tcb_t *)(retval - MIPS_TP_OFFSET - sizeof(tcb_t)); |
} |
#endif |
/uspace/trunk/libc/arch/mips32/Makefile.inc |
---|
34,6 → 34,7 |
CFLAGS += -mips3 |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/psthread.S |
arch/$(ARCH)/src/psthread.S \ |
arch/$(ARCH)/src/thread.c |
/uspace/trunk/libc/arch/mips32/src/thread.c |
---|
0,0 → 1,50 |
/* |
* Copyright (C) 2006 Ondrej Palkovsky |
* All rights reserved. |
* |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions |
* are met: |
* |
* - Redistributions of source code must retain the above copyright |
* notice, this list of conditions and the following disclaimer. |
* - Redistributions in binary form must reproduce the above copyright |
* notice, this list of conditions and the following disclaimer in the |
* documentation and/or other materials provided with the distribution. |
* - The name of the author may not be used to endorse or promote products |
* derived from this software without specific prior written permission. |
* |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
*/ |
#include <thread.h> |
#include <malloc.h> |
/** Allocate TLS & TCB for initial module threads |
* |
* @param data (out) Start of TLS section |
* @param size Size of tdata+tbss section |
* @return pointer to tcb_t structure |
*/ |
tcb_t * __alloc_tls(void **data, size_t size) |
{ |
tcb_t *result; |
result = malloc(sizeof(tcb_t) + size); |
*data = ((void *)result) + sizeof(tcb_t); |
return result; |
} |
void __free_tls_arch(tcb_t *tcb, size_t size) |
{ |
free(tcb); |
} |
/uspace/trunk/libc/arch/ia32/_link.ld.in |
---|
20,6 → 20,16 |
.data ALIGN(0x1000) : SUBALIGN(0x1000) { |
*(.data); |
} :data |
.tdata : { |
_tdata_start = .; |
*(.tdata); |
_tdata_end = .; |
} :data |
.tbss : { |
_tbss_start = .; |
*(.tbss); |
_tbss_end = .; |
} :data |
.bss : { |
*(COMMON); |
*(.bss); |
/uspace/trunk/libc/arch/ia32/include/thread.h |
---|
31,12 → 31,17 |
#include <libc.h> |
static inline void __tls_set(void *tls) |
typedef struct { |
void *self; |
void *pst_data; |
} tcb_t; |
static inline void __tcb_set(tcb_t *tcb) |
{ |
__SYSCALL1(SYS_TLS_SET, (sysarg_t) tls); |
__SYSCALL1(SYS_TLS_SET, (sysarg_t) tcb); |
} |
static inline void * __tls_get(void) |
static inline tcb_t * __tcb_get(void) |
{ |
void * retval; |
/uspace/trunk/libc/arch/ia32/Makefile.inc |
---|
33,6 → 33,7 |
TOOLCHAIN_DIR = /usr/local/i686/bin |
ARCH_SOURCES += arch/$(ARCH)/src/syscall.c \ |
arch/$(ARCH)/src/psthread.S |
arch/$(ARCH)/src/psthread.S \ |
arch/$(ARCH)/src/thread.c |
LFLAGS += -N |
/uspace/trunk/libc/arch/ia32/src/thread.c |
---|
0,0 → 1,0 |
link ../../amd64/src/thread.c |
Property changes: |
Added: svn:special |
+* |
\ No newline at end of property |