|  | /* 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) |