source: mainline/uspace/lib/c/generic/thread/thread.c@ e2625b1a

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e2625b1a was 6340b4d2, checked in by Jiří Zárevúcky <jiri.zarevucky@…>, 7 years ago

libc: Put threading-related files into a subdirectory.

  • Property mode set to 100644
File size: 4.9 KB
Line 
1/*
2 * Copyright (c) 2006 Jakub Jermar
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
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.
16 *
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.
27 */
28
29/** @addtogroup libc
30 * @{
31 */
32/** @file
33 */
34
35#include <libc.h>
36#include <stdbool.h>
37#include <stdlib.h>
38#include <libarch/faddr.h>
39#include <abi/proc/uarg.h>
40#include <fibril.h>
41#include <stack.h>
42#include <str.h>
43#include <async.h>
44#include <errno.h>
45#include <as.h>
46
47#include "../private/thread.h"
48#include "../private/fibril.h"
49
50/** Main thread function.
51 *
52 * This function is called from __thread_entry() and is used
53 * to call the thread's implementing function and perform cleanup
54 * and exit when thread returns back.
55 *
56 * @param uarg Pointer to userspace argument structure.
57 *
58 */
59void __thread_main(uspace_arg_t *uarg)
60{
61 assert(!__tcb_is_set());
62
63 fibril_t *fibril = uarg->uspace_thread_arg;
64 assert(fibril);
65
66 __tcb_set(fibril->tcb);
67
68 uarg->uspace_thread_function(fibril->arg);
69 /*
70 * XXX: we cannot free the userspace stack while running on it
71 *
72 * free(uarg->uspace_stack);
73 * free(uarg);
74 */
75
76 fibril_teardown(fibril);
77 thread_exit(0);
78}
79
80/** Create userspace thread.
81 *
82 * This function creates new userspace thread and allocates userspace
83 * stack and userspace argument structure for it.
84 *
85 * @param function Function implementing the thread.
86 * @param arg Argument to be passed to thread.
87 * @param name Symbolic name of the thread.
88 * @param tid Thread ID of the newly created thread.
89 *
90 * @return Zero on success or a code from @ref errno.h on failure.
91 */
92errno_t thread_create(void (*function)(void *), void *arg, const char *name,
93 thread_id_t *tid)
94{
95 uspace_arg_t *uarg = calloc(1, sizeof(uspace_arg_t));
96 if (!uarg)
97 return ENOMEM;
98
99 fibril_t *fibril = fibril_alloc();
100 if (!fibril) {
101 free(uarg);
102 return ENOMEM;
103 }
104
105 size_t stack_size = stack_size_get();
106 void *stack = as_area_create(AS_AREA_ANY, stack_size,
107 AS_AREA_READ | AS_AREA_WRITE | AS_AREA_CACHEABLE | AS_AREA_GUARD |
108 AS_AREA_LATE_RESERVE, AS_AREA_UNPAGED);
109 if (stack == AS_MAP_FAILED) {
110 fibril_teardown(fibril);
111 free(uarg);
112 return ENOMEM;
113 }
114
115 fibril->arg = arg;
116 uarg->uspace_entry = (void *) FADDR(__thread_entry);
117 uarg->uspace_stack = stack;
118 uarg->uspace_stack_size = stack_size;
119 uarg->uspace_thread_function = function;
120 uarg->uspace_thread_arg = fibril;
121 uarg->uspace_uarg = uarg;
122
123 errno_t rc = (errno_t) __SYSCALL4(SYS_THREAD_CREATE, (sysarg_t) uarg,
124 (sysarg_t) name, (sysarg_t) str_size(name), (sysarg_t) tid);
125
126 if (rc != EOK) {
127 /*
128 * Failed to create a new thread.
129 * Free up the allocated data.
130 */
131 as_area_destroy(stack);
132 free(uarg);
133 }
134
135 return rc;
136}
137
138/** Terminate current thread.
139 *
140 * @param status Exit status. Currently not used.
141 *
142 */
143void thread_exit(int status)
144{
145 __SYSCALL1(SYS_THREAD_EXIT, (sysarg_t) status);
146
147 /* Unreachable */
148 while (true)
149 ;
150}
151
152/** Detach thread.
153 *
154 * Currently not implemented.
155 *
156 * @param thread TID.
157 */
158void thread_detach(thread_id_t thread)
159{
160}
161
162/** Get current thread ID.
163 *
164 * @return Current thread ID.
165 */
166thread_id_t thread_get_id(void)
167{
168 thread_id_t thread_id;
169
170 (void) __SYSCALL1(SYS_THREAD_GET_ID, (sysarg_t) &thread_id);
171
172 return thread_id;
173}
174
175/** Wait unconditionally for specified number of microseconds
176 *
177 */
178int thread_usleep(useconds_t usec)
179{
180 (void) __SYSCALL1(SYS_THREAD_USLEEP, usec);
181 return 0;
182}
183
184/** Wait unconditionally for specified number of seconds
185 *
186 */
187unsigned int thread_sleep(unsigned int sec)
188{
189 /*
190 * Sleep in 1000 second steps to support
191 * full argument range
192 */
193
194 while (sec > 0) {
195 unsigned int period = (sec > 1000) ? 1000 : sec;
196
197 thread_usleep(period * 1000000);
198 sec -= period;
199 }
200
201 return 0;
202}
203
204/** @}
205 */
Note: See TracBrowser for help on using the repository browser.