source: mainline/uspace/lib/c/generic/libc.c@ 05208d9

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

Fibril/async implementation overhaul.

This commit marks the move towards treating the fibril library as a mere
implementation of a generic threading interface. Understood as a layer that
wraps the kernel threads, we not only have to wrap threading itself, but also
every syscall that blocks the kernel thread (by blocking, we mean thread not
doing useful work until an external event happens — e.g. locking a kernel
mutex or thread sleep is understood as blocking, but an as_area_create() is not,
despite potentially taking a long time to complete).

Consequently, we implement fibril_ipc_wait() as a fibril-native wrapper for
kernel's ipc_wait(), and also implement timer functionality like timeouts
as part of the fibril library. This removes the interdependency between fibril
implementation and the async framework — in theory, the fibril API could be
reimplemented as a simple 1:1 shim, and the async framework would continue
working normally (note that the current implementation of loader complicates
this).

To better isolate the fibril internals from the implementation of high-level
synchronization, a fibril_event_t is added. This object conceptually acts
like a single slot wait queue. All other synchronization is implemented in
terms of this primitive.

  • Property mode set to 100644
File size: 4.3 KB
Line 
1/*
2 * Copyright (c) 2005 Martin Decky
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 lc Libc
30 * @brief HelenOS C library
31 * @{
32 * @}
33 */
34
35/** @addtogroup libc generic
36 * @ingroup lc
37 * @{
38 */
39
40/** @file
41 */
42
43#include <errno.h>
44#include <libc.h>
45#include <stdbool.h>
46#include <stdlib.h>
47#include <tls.h>
48#include <fibril.h>
49#include <task.h>
50#include <loader/pcb.h>
51#include <vfs/vfs.h>
52#include <vfs/inbox.h>
53#include "private/libc.h"
54#include "private/async.h"
55#include "private/malloc.h"
56#include "private/io.h"
57#include "private/fibril.h"
58
59#ifdef CONFIG_RTLD
60#include <rtld/rtld.h>
61#endif
62
63progsymbols_t __progsymbols;
64
65static bool env_setup;
66static fibril_t main_fibril;
67
68void __libc_main(void *pcb_ptr)
69{
70 assert(!__tcb_is_set());
71
72 __pcb = (pcb_t *) pcb_ptr;
73
74 if (__pcb) {
75 main_fibril.tcb = __pcb->tcb;
76 } else {
77 /*
78 * Loaded by kernel, not the loader.
79 * Kernel only supports loading fully static binaries,
80 * so we can do basic initialization without worrying about
81 * dynamic libraries.
82 */
83
84 main_fibril.tcb = tls_make_initial(__progsymbols.elfstart);
85 }
86
87 assert(main_fibril.tcb);
88
89 __fibrils_init();
90
91 /* Initialize the fibril. */
92 main_fibril.tcb->fibril_data = &main_fibril;
93 __tcb_set(main_fibril.tcb);
94 fibril_setup(&main_fibril);
95
96 /* Initialize user task run-time environment */
97 __malloc_init();
98
99#ifdef CONFIG_RTLD
100 if (__pcb != NULL && __pcb->rtld_runtime != NULL) {
101 runtime_env = (rtld_t *) __pcb->rtld_runtime;
102 } else {
103 if (rtld_init_static() != EOK)
104 abort();
105 }
106#endif
107
108 __async_server_init();
109 __async_client_init();
110 __async_ports_init();
111
112 /* The basic run-time environment is setup */
113 env_setup = true;
114
115 int argc;
116 char **argv;
117
118 /*
119 * Get command line arguments and initialize
120 * standard input and output
121 */
122 if (__pcb == NULL) {
123 argc = 0;
124 argv = NULL;
125 __stdio_init();
126 } else {
127 argc = __pcb->argc;
128 argv = __pcb->argv;
129 __inbox_init(__pcb->inbox, __pcb->inbox_entries);
130 __stdio_init();
131 vfs_root_set(inbox_get("root"));
132 (void) vfs_cwd_set(__pcb->cwd);
133 }
134
135 /*
136 * C++ Static constructor calls.
137 */
138
139 if (__progsymbols.preinit_array) {
140 for (int i = __progsymbols.preinit_array_len - 1; i >= 0; --i)
141 __progsymbols.preinit_array[i]();
142 }
143
144 if (__progsymbols.init_array) {
145 for (int i = __progsymbols.init_array_len - 1; i >= 0; --i)
146 __progsymbols.init_array[i]();
147 }
148
149 /*
150 * Run main() and set task return value
151 * according the result
152 */
153 int retval = __progsymbols.main(argc, argv);
154 exit(retval);
155}
156
157void __libc_exit(int status)
158{
159 /*
160 * GCC extension __attribute__((destructor)),
161 * C++ destructors are added to __cxa_finalize call
162 * when the respective constructor is called.
163 */
164
165 for (int i = 0; i < __progsymbols.fini_array_len; ++i)
166 __progsymbols.fini_array[i]();
167
168 if (env_setup) {
169 __stdio_done();
170 task_retval(status);
171 }
172
173 __SYSCALL1(SYS_TASK_EXIT, false);
174 __builtin_unreachable();
175}
176
177void __libc_abort(void)
178{
179 __SYSCALL1(SYS_TASK_EXIT, true);
180 __builtin_unreachable();
181}
182
183/** @}
184 */
Note: See TracBrowser for help on using the repository browser.