Use weak __thread declarations in parlib-compat (XCC)
[akaros.git] / tools / compilers / gcc-glibc / glibc-2.19-akaros / sysdeps / akaros / parlib-compat.c
1 /* Copyright (c) 2015 Google Inc.
2  * Kevin Klues <klueska@cs.berkeley.edu>
3  * See LICENSE for details.
4  */
5
6 #include <libc-symbols.h>
7 #include <ros/common.h>
8 #include <ros/trapframe.h>
9 #include <ros/syscall.h>
10 #include <parlib/stdio.h>
11 #include <parlib/assert.h>
12 #include <parlib/spinlock.h>
13 #include <parlib/timing.h>
14 #include <stdbool.h>
15
16 /* Here we define functions and variables that are really defined in parlib, but
17  * we need them in libc in order to link it. We weak alias them here so that the
18  * parlib definitions will override them later.
19  *
20  * Unfortunately, this trick only works so long as we leave parlib as a static
21  * library. If we ever decide to make parlib a .so, then we will have to revisit
22  * this and use function pointers at runtime or something similar.
23  *
24  * This also doesn't work for ld.so, which doesn't link against parlib.  That's
25  * probably a good thing (uthread constructors would be a mess for ld, I bet).
26  * But that does mean that these stubs need to actually do something for
27  * functions that ld.so calls.  See the notes below for more info. */
28
29 __thread int __weak_vcoreid = 0;
30 extern __thread int __vcoreid __attribute__ ((weak, alias ("__weak_vcoreid")));
31
32 __thread bool __weak_vcore_context = FALSE;
33 extern __thread bool __vcore_context
34        __attribute__ ((weak, alias ("__weak_vcore_context")));
35
36 int __akaros_printf(const char *format, ...)
37 {
38         assert(0);
39         return -1;
40 }
41 weak_alias(__akaros_printf, akaros_printf)
42
43 void __print_user_context(struct user_context *ctx)
44 {
45         assert(0);
46 }
47 weak_alias(__print_user_context, print_user_context)
48
49 void ___assert_failed(const char *file, int line, const char *msg)
50 {
51         assert(0);
52 }
53 weak_alias(___assert_failed, _assert_failed)
54
55 uint64_t __nsec2tsc(uint64_t nsec)
56 {
57         assert(0);
58 }
59 weak_alias(__nsec2tsc, nsec2tsc)
60
61 uint64_t __tsc2nsec(uint64_t tsc_time)
62 {
63         assert(0);
64 }
65 weak_alias(__tsc2nsec, tsc2nsec)
66
67 /* ld.so calls these, so we need them to work.  We don't need them to be
68  * thread-safe, since we're single-threaded, but we do need them to use the
69  * right values for 'locked' and 'unlocked'.
70  *
71  * Note that for this change I needed to recompile the binaries that link with
72  * libc - even if they link dynamically.  Otherwise, when they linked with
73  * libc.so, *libc itself* (not the actual program) would not find the parlib
74  * functions - it would still use these functions.  Lots of glibc functions
75  * (printf, fflush, etc) call some version of spin_pdr_lock (lll_lock).
76  *
77  * For an example, if you write(2, "foo\n", 4) on ever lock acquisition, you'll
78  * see one foo per process, which I think comes from ld.  Later functions that
79  * call spin_pdr_lock, whether from the app, parlib, or libc, do not output foo.
80  * This is not the case if the application was not rebuilt before this change
81  * (e.g. bash, ssh, etc). */
82 bool __spin_pdr_trylock(struct spin_pdr_lock *pdr_lock)
83 {
84         if (pdr_lock->lock != SPINPDR_UNLOCKED)
85                 return FALSE;
86         pdr_lock->lock = 0;
87         return TRUE;
88 }
89 weak_alias(__spin_pdr_trylock, spin_pdr_trylock)
90
91 void __spin_pdr_lock(struct spin_pdr_lock *pdr_lock)
92 {
93         assert(pdr_lock->lock == SPINPDR_UNLOCKED);
94         /* assume we're vcore 0 */
95         pdr_lock->lock = 0;
96 }
97 weak_alias(__spin_pdr_lock, spin_pdr_lock)
98
99 void __spin_pdr_unlock(struct spin_pdr_lock *pdr_lock)
100 {
101         pdr_lock->lock = SPINPDR_UNLOCKED;
102 }
103 weak_alias(__spin_pdr_unlock, spin_pdr_unlock)
104
105 void __cpu_relax_vc(uint32_t vcoreid)
106 {
107         cpu_relax();
108 }
109 weak_alias(__cpu_relax_vc, cpu_relax_vc)
110
111 void __uthread_sched_yield(void)
112 {
113         /* In the off-chance we're called before parlib is available, we'll do the
114          * single-threaded, SCP yield. */
115         ros_syscall(SYS_proc_yield, TRUE, 0, 0, 0, 0, 0);
116 }
117 weak_alias(__uthread_sched_yield, uthread_sched_yield)