Subversion Repositories HelenOS

Rev

Rev 2568 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2568 Rev 2586
Line 28... Line 28...
28
 
28
 
29
/** @addtogroup libc
29
/** @addtogroup libc
30
 * @{
30
 * @{
31
 */
31
 */
32
/** @file
32
/** @file
-
 
33
 *
-
 
34
 * Support for thread-local storage, as described in:
-
 
35
 *  Drepper U.: ELF Handling For Thread-Local Storage, 2005
-
 
36
 *
-
 
37
 * Only static model is supported.
33
 */
38
 */
34
 
39
 
35
#include <thread.h>
-
 
36
#include <libc.h>
40
#include <tls.h>
37
#include <stdlib.h>
41
#include <malloc.h>
38
#include <libarch/faddr.h>
-
 
39
#include <kernel/proc/uarg.h>
-
 
40
#include <fibril.h>
-
 
41
#include <string.h>
42
#include <string.h>
42
#include <async.h>
43
#include <align.h>
43
 
-
 
44
#include <stdio.h>
-
 
45
 
-
 
46
 
-
 
47
#ifndef THREAD_INITIAL_STACK_PAGES_NO
-
 
48
#define THREAD_INITIAL_STACK_PAGES_NO 1
-
 
49
#endif
-
 
50
 
-
 
51
static LIST_INITIALIZE(thread_garbage);
-
 
52
 
-
 
53
extern char _tdata_start;
-
 
54
extern char _tdata_end;
-
 
55
extern char _tbss_start;
-
 
56
extern char _tbss_end;
-
 
57
 
44
 
58
/** Create TLS (Thread Local Storage) data structures.
45
/** Create TLS (Thread Local Storage) data structures.
59
 *
46
 *
60
 * The code requires, that sections .tdata and .tbss are adjacent. It may be
47
 * The code requires, that sections .tdata and .tbss are adjacent. It may be
61
 * changed in the future.
48
 * changed in the future.
Line 87... Line 74...
87
{
74
{
88
    size_t tls_size = &_tbss_end - &_tdata_start;
75
    size_t tls_size = &_tbss_end - &_tdata_start;
89
    __free_tls_arch(tcb, tls_size);
76
    __free_tls_arch(tcb, tls_size);
90
}
77
}
91
 
78
 
-
 
79
#ifdef CONFIG_TLS_VARIANT_1
92
/** Main thread function.
80
/** Allocate TLS variant 1 data structures.
93
 *
81
 *
94
 * This function is called from __thread_entry() and is used
-
 
95
 * to call the thread's implementing function and perform cleanup
82
 * @param data      Start of TLS section. This is an output argument.
96
 * and exit when thread returns back. Do not call this function
83
 * @param size      Size of tdata + tbss section.
97
 * directly.
-
 
98
 *
-
 
99
 * @param uarg Pointer to userspace argument structure.
84
 * @return      Pointer to tcb_t structure.
100
 */
85
 */
101
void __thread_main(uspace_arg_t *uarg)
86
tcb_t *tls_alloc_variant_1(void **data, size_t size)
102
{
87
{
103
    fibril_t *f;
-
 
104
 
-
 
105
    f = fibril_setup();
-
 
106
    __tcb_set(f->tcb);
88
    tcb_t *result;
107
 
89
 
108
    uarg->uspace_thread_function(uarg->uspace_thread_arg);
90
    result = malloc(sizeof(tcb_t) + size);
109
    /* XXX: we cannot free the userspace stack while running on it */
-
 
110
//  free(uarg->uspace_stack);
-
 
111
//  free(uarg);
-
 
112
 
-
 
113
    /* If there is a manager, destroy it */
91
    *data = ((void *)result) + sizeof(tcb_t);
114
    async_destroy_manager();
-
 
115
    fibril_teardown(f);
-
 
116
 
-
 
117
    thread_exit(0);
92
    return result;
118
}
93
}
119
 
94
 
120
/** Create userspace thread.
-
 
121
 *
-
 
122
 * This function creates new userspace thread and allocates userspace
-
 
123
 * stack and userspace argument structure for it.
95
/** Free TLS variant I data structures.
124
 *
96
 *
125
 * @param function Function implementing the thread.
-
 
126
 * @param arg Argument to be passed to thread.
97
 * @param tcb       Pointer to TCB structure.
127
 * @param name Symbolic name of the thread.
98
 * @param size      This argument is ignored.
128
 * @param tid Thread ID of the newly created thread.
-
 
129
 *
-
 
130
 * @return Zero on success or a code from @ref errno.h on failure.
-
 
131
 */
99
 */
132
int thread_create(void (* function)(void *), void *arg, char *name,
100
void tls_free_variant_1(tcb_t *tcb, size_t size)
133
    thread_id_t *tid)
-
 
134
{
101
{
135
    char *stack;
-
 
136
    uspace_arg_t *uarg;
-
 
137
    int rc;
-
 
138
 
-
 
139
    stack = (char *) malloc(getpagesize() * THREAD_INITIAL_STACK_PAGES_NO);
-
 
140
    if (!stack)
-
 
141
        return -1;
-
 
142
       
-
 
143
    uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t));
-
 
144
    if (!uarg) {
-
 
145
        free(stack);
102
    free(tcb);
146
        return -1;
-
 
147
    }
-
 
148
   
-
 
149
    uarg->uspace_entry = (void *) FADDR(__thread_entry);
-
 
150
    uarg->uspace_stack = (void *) stack;
-
 
151
    uarg->uspace_thread_function = function;
-
 
152
    uarg->uspace_thread_arg = arg;
-
 
153
    uarg->uspace_uarg = uarg;
-
 
154
   
-
 
155
    rc = __SYSCALL3(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name,
-
 
156
        (sysarg_t) tid);
-
 
157
   
-
 
158
    if (rc) {
-
 
159
        /*
-
 
160
         * Failed to create a new thread.
-
 
161
         * Free up the allocated structures.
-
 
162
         */
-
 
163
        free(uarg);
-
 
164
        free(stack);
-
 
165
    }
-
 
166
 
-
 
167
    return rc;
-
 
168
}
103
}
-
 
104
#endif
169
 
105
 
-
 
106
#ifdef CONFIG_TLS_VARIANT_2
170
/** Terminate current thread.
107
/** Allocate TLS variant II data structures.
171
 *
108
 *
-
 
109
 * @param data      Pointer to pointer to thread local data. This is
-
 
110
 *          actually an output argument.
172
 * @param status Exit status. Currently not used.
111
 * @param size      Size of thread local data.
-
 
112
 * @return      Pointer to TCB structure.
173
 */
113
 */
174
void thread_exit(int status)
114
tcb_t * tls_alloc_variant_2(void **data, size_t size)
175
{
115
{
176
    __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
116
    tcb_t *tcb;
177
}
117
   
-
 
118
    size = ALIGN_UP(size, &_tls_alignment);
-
 
119
    *data = memalign(&_tls_alignment, sizeof(tcb_t) + size);
178
 
120
 
179
/** Detach thread.
-
 
180
 *
-
 
181
 * Currently not implemented.
121
    tcb = (tcb_t *) (*data + size);
182
 *
-
 
183
 * @param thread TID.
122
    tcb->self = tcb;
184
 */
-
 
185
void thread_detach(thread_id_t thread)
-
 
186
{
-
 
187
}
-
 
188
 
123
 
189
/** Join thread.
124
    return tcb;
190
 *
-
 
191
 * Currently not implemented.
-
 
192
 *
-
 
193
 * @param thread TID.
-
 
194
 *
-
 
195
 * @return Thread exit status.
-
 
196
 */
-
 
197
int thread_join(thread_id_t thread)
-
 
198
{
-
 
199
}
125
}
200
 
126
 
201
/** Get current thread ID.
127
/** Free TLS variant II data structures.
202
 *
128
 *
-
 
129
 * @param tcb       Pointer to TCB structure.
203
 * @return Current thread ID.
130
 * @param size      Size of thread local data.
204
 */
131
 */
205
thread_id_t thread_get_id(void)
132
void tls_free_variant_2(tcb_t *tcb, size_t size)
206
{
133
{
207
    thread_id_t thread_id;
134
    size = ALIGN_UP(size, &_tls_alignment);
208
 
-
 
209
    (void) __SYSCALL1(SYS_THREAD_GET_ID, (sysarg_t) &thread_id);
135
    void *start = ((void *) tcb) - size;
210
 
-
 
211
    return thread_id;
136
    free(start);
212
}
137
}
-
 
138
#endif
213
 
139
 
214
/** @}
140
/** @}
215
 */
141
 */