| /* Copyright (c) 2015 Google Inc. |
| * Kevin Klues <klueska@cs.berkeley.edu> |
| * See LICENSE for details. |
| */ |
| |
| #include <libc-symbols.h> |
| #include <ros/common.h> |
| #include <ros/trapframe.h> |
| #include <ros/syscall.h> |
| #include <parlib/stdio.h> |
| #include <parlib/assert.h> |
| #include <parlib/spinlock.h> |
| #include <parlib/timing.h> |
| #include <parlib/uthread.h> |
| #include <parlib/dtls.h> |
| #include <stdbool.h> |
| |
| /* Here we define functions and variables that are really defined in parlib, but |
| * we need them in libc in order to link it. We weak alias them here so that the |
| * parlib definitions will override them later. |
| * |
| * Unfortunately, this trick only works so long as we leave parlib as a static |
| * library. If we ever decide to make parlib a .so, then we will have to revisit |
| * this and use function pointers at runtime or something similar. |
| * |
| * This also doesn't work for ld.so, which doesn't link against parlib. That's |
| * probably a good thing (uthread constructors would be a mess for ld, I bet). |
| * But that does mean that these stubs need to actually do something for |
| * functions that ld.so calls. |
| * |
| * Also, be careful and paranoid. If you change or add functions in here, |
| * recompile apps that link against libc - even if they link dynamically. |
| * Otherwise, when they linked with libc.so, *libc itself* (not the actual |
| * program) would not find the parlib functions - it would still use these |
| * functions. I don't have a good explanation for it, but that's what seemed to |
| * happen. |
| * |
| * For an example, if you write(2, "foo\n", 4) on every lock acquisition, you'll |
| * see one foo per process, which I think comes from ld (back when it used |
| * spin_pdr locks for the rtld lock). Later functions that call spin_pdr_lock, |
| * whether from the app, parlib, or libc, do not output foo. This is not the |
| * case if the application was not rebuilt before this change (e.g. bash, ssh, |
| * etc). */ |
| |
| __thread int __weak_vcoreid = 0; |
| extern __thread int __vcoreid __attribute__ ((weak, alias ("__weak_vcoreid"))); |
| |
| __thread bool __weak_vcore_context = FALSE; |
| extern __thread bool __vcore_context |
| __attribute__ ((weak, alias ("__weak_vcore_context"))); |
| |
| int __akaros_printf(const char *format, ...) |
| { |
| assert(0); |
| return -1; |
| } |
| weak_alias(__akaros_printf, akaros_printf) |
| |
| int __trace_printf(const char *format, ...) |
| { |
| assert(0); |
| return -1; |
| } |
| weak_alias(__trace_printf, trace_printf) |
| |
| void __print_user_context(struct user_context *ctx) |
| { |
| assert(0); |
| } |
| weak_alias(__print_user_context, print_user_context) |
| |
| void ___assert_failed(const char *file, int line, const char *msg) |
| { |
| breakpoint(); |
| abort(); |
| } |
| weak_alias(___assert_failed, _assert_failed) |
| |
| uint64_t __nsec2tsc(uint64_t nsec) |
| { |
| assert(0); |
| } |
| weak_alias(__nsec2tsc, nsec2tsc) |
| |
| uint64_t __tsc2nsec(uint64_t tsc_time) |
| { |
| assert(0); |
| } |
| weak_alias(__tsc2nsec, tsc2nsec) |
| |
| void __spin_pdr_init(struct spin_pdr_lock *pdr_lock) |
| { |
| assert(0); |
| } |
| weak_alias(__spin_pdr_init, spin_pdr_init) |
| |
| bool __spin_pdr_trylock(struct spin_pdr_lock *pdr_lock) |
| { |
| assert(0); |
| } |
| weak_alias(__spin_pdr_trylock, spin_pdr_trylock) |
| |
| void __spin_pdr_lock(struct spin_pdr_lock *pdr_lock) |
| { |
| assert(0); |
| } |
| weak_alias(__spin_pdr_lock, spin_pdr_lock) |
| |
| void __spin_pdr_unlock(struct spin_pdr_lock *pdr_lock) |
| { |
| assert(0); |
| } |
| weak_alias(__spin_pdr_unlock, spin_pdr_unlock) |
| |
| void __cpu_relax_vc(uint32_t vcoreid) |
| { |
| cpu_relax(); |
| } |
| weak_alias(__cpu_relax_vc, cpu_relax_vc) |
| |
| void __uthread_sched_yield(void) |
| { |
| /* In the off-chance we're called before parlib is available, we'll do |
| * the single-threaded, SCP yield. */ |
| ros_syscall(SYS_proc_yield, TRUE, 0, 0, 0, 0, 0); |
| } |
| weak_alias(__uthread_sched_yield, uthread_sched_yield) |
| |
| void __uth_mutex_init(uth_mutex_t *m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_mutex_init, uth_mutex_init) |
| |
| void __uth_mutex_destroy(uth_mutex_t *m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_mutex_destroy, uth_mutex_destroy) |
| |
| void __uth_mutex_lock(uth_mutex_t *m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_mutex_lock, uth_mutex_lock) |
| |
| bool __uth_mutex_trylock(uth_mutex_t *m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_mutex_trylock, uth_mutex_trylock) |
| |
| void __uth_mutex_unlock(uth_mutex_t *m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_mutex_unlock, uth_mutex_unlock) |
| |
| void __uth_recurse_mutex_init(uth_recurse_mutex_t *r_m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_recurse_mutex_init, uth_recurse_mutex_init) |
| |
| void __uth_recurse_mutex_destroy(uth_recurse_mutex_t *r_m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_recurse_mutex_destroy, uth_recurse_mutex_destroy) |
| |
| void __uth_recurse_mutex_lock(uth_recurse_mutex_t *r_m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_recurse_mutex_lock, uth_recurse_mutex_lock) |
| |
| bool __uth_recurse_mutex_trylock(uth_recurse_mutex_t *r_m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_recurse_mutex_trylock, uth_recurse_mutex_trylock) |
| |
| void __uth_recurse_mutex_unlock(uth_recurse_mutex_t *r_m) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_recurse_mutex_unlock, uth_recurse_mutex_unlock) |
| |
| void __uth_rwlock_init(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_init, uth_rwlock_init) |
| |
| void __uth_rwlock_destroy(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_destroy, uth_rwlock_destroy) |
| |
| void __uth_rwlock_rdlock(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_rdlock, uth_rwlock_rdlock) |
| |
| bool __uth_rwlock_try_rdlock(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_try_rdlock, uth_rwlock_try_rdlock) |
| |
| void __uth_rwlock_wrlock(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_wrlock, uth_rwlock_wrlock) |
| |
| bool __uth_rwlock_try_wrlock(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_try_wrlock, uth_rwlock_try_wrlock) |
| |
| void __uth_rwlock_unlock(uth_rwlock_t *rwl) |
| { |
| assert(0); |
| } |
| weak_alias(__uth_rwlock_unlock, uth_rwlock_unlock) |
| |
| dtls_key_t __dtls_key_create(dtls_dtor_t dtor) |
| { |
| assert(0); |
| } |
| weak_alias(__dtls_key_create, dtls_key_create) |
| |
| void __set_dtls(dtls_key_t key, const void *dtls) |
| { |
| assert(0); |
| } |
| weak_alias(__set_dtls, set_dtls) |
| |
| void *__get_dtls(dtls_key_t key) |
| { |
| assert(0); |
| } |
| weak_alias(__get_dtls, get_dtls) |