source: mainline/uspace/lib/c/generic/thread.c@ 42f5860

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

Replace a bunch of direct uses of futex_t.

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