Improve comments and fix formatting in (sparc64) TLS implementation.
[helenos.git] / uspace / libc / generic / thread.c
blob12deed4bd25134b411b339ba6afb57d1cff5ca60
1 /*
2 * Copyright (C) 2006 Jakub Jermar
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 /** @addtogroup libc
30 * @{
32 /** @file
33 */
35 #include <thread.h>
36 #include <libc.h>
37 #include <stdlib.h>
38 #include <libarch/faddr.h>
39 #include <kernel/proc/uarg.h>
40 #include <psthread.h>
41 #include <string.h>
42 #include <async.h>
44 #include <stdio.h>
47 #ifndef THREAD_INITIAL_STACK_PAGES_NO
48 #define THREAD_INITIAL_STACK_PAGES_NO 1
49 #endif
51 static LIST_INITIALIZE(thread_garbage);
53 extern char _tdata_start;
54 extern char _tdata_end;
55 extern char _tbss_start;
56 extern char _tbss_end;
58 /** Create TLS (Thread Local Storage) data structures.
60 * The code requires, that sections .tdata and .tbss are adjacent. It may be
61 * changed in the future.
63 * @return Pointer to TCB.
65 tcb_t *__make_tls(void)
67 void *data;
68 tcb_t *tcb;
69 size_t tls_size = &_tbss_end - &_tdata_start;
71 tcb = __alloc_tls(&data, tls_size);
74 * Copy thread local data from the initialization image.
76 memcpy(data, &_tdata_start, &_tdata_end - &_tdata_start);
78 * Zero out the thread local uninitialized data.
80 memset(data + (&_tbss_start - &_tdata_start), 0, &_tbss_end -
81 &_tbss_start);
83 return tcb;
86 void __free_tls(tcb_t *tcb)
88 size_t tls_size = &_tbss_end - &_tdata_start;
89 __free_tls_arch(tcb, tls_size);
92 /** Main thread function.
94 * This function is called from __thread_entry() and is used
95 * to call the thread's implementing function and perform cleanup
96 * and exit when thread returns back. Do not call this function
97 * directly.
99 * @param uarg Pointer to userspace argument structure.
101 void __thread_main(uspace_arg_t *uarg)
103 psthread_data_t *pt;
105 pt = psthread_setup();
106 __tcb_set(pt->tcb);
108 uarg->uspace_thread_function(uarg->uspace_thread_arg);
109 free(uarg->uspace_stack);
110 free(uarg);
112 /* If there is a manager, destroy it */
113 async_destroy_manager();
114 psthread_teardown(pt);
116 thread_exit(0);
119 /** Create userspace thread.
121 * This function creates new userspace thread and allocates userspace
122 * stack and userspace argument structure for it.
124 * @param function Function implementing the thread.
125 * @param arg Argument to be passed to thread.
126 * @param name Symbolic name of the thread.
128 * @return TID of the new thread on success or -1 on failure.
130 int thread_create(void (* function)(void *), void *arg, char *name)
132 char *stack;
133 uspace_arg_t *uarg;
135 stack = (char *) malloc(getpagesize() * THREAD_INITIAL_STACK_PAGES_NO);
136 if (!stack)
137 return -1;
139 uarg = (uspace_arg_t *) malloc(sizeof(uspace_arg_t));
140 if (!uarg) {
141 free(stack);
142 return -1;
145 uarg->uspace_entry = (void *) FADDR(__thread_entry);
146 uarg->uspace_stack = (void *) stack;
147 uarg->uspace_thread_function = function;
148 uarg->uspace_thread_arg = arg;
149 uarg->uspace_uarg = uarg;
151 return __SYSCALL2(SYS_THREAD_CREATE, (sysarg_t) uarg, (sysarg_t) name);
154 /** Terminate current thread.
156 * @param status Exit status. Currently not used.
158 void thread_exit(int status)
160 __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
163 /** @}