diff --git a/libc.map.txt b/libc.map.txt index 430d797968c23a187b0bd54ed42638a9ea773203..3216245c9b44f9a80a1ac9a00e65983b43a7ff95 100644 --- a/libc.map.txt +++ b/libc.map.txt @@ -1968,7 +1968,7 @@ LIBC { __mq_timedsend_time64; shm_open; shm_unlink; - # pthread_cancel; + pthread_cancel; # pthread_setcancelstate; pthread_setcanceltype; pthread_testcancel; diff --git a/musl_src.gni b/musl_src.gni index 4fd62c71a56f00279601df2ce1bafd09f0f6b0aa..a6974247f7ee93882023aa4ae70ae43bd9d3f0d5 100644 --- a/musl_src.gni +++ b/musl_src.gni @@ -2010,6 +2010,7 @@ musl_inc_root_files = [ ] musl_src_porting_file = [ + "arch/aarch64/syscall_arch.h", "arch/arm/bits/fenv.h", "arch/generic/bits/shm.h", "arch/generic/crtbrand.s", @@ -2125,6 +2126,11 @@ musl_src_porting_file = [ "src/ldso/riscv64/dlvsym.s", "src/ldso/x86_64/dlvsym.s", "src/stdio/__fdopen.c", + "src/internal/vdso.c", + "src/time/clock_gettime.c", + "src/time/clock_getres.c", + "src/time/gettimeofday.c", + "src/time/time.c", ] musl_inc_hook_files = [ diff --git a/musl_template.gni b/musl_template.gni index 8838b1153061a1b46421b9cedc300b7ad068b244..5b0d1c9898a750f57aef8455e3e66a307900091b 100644 --- a/musl_template.gni +++ b/musl_template.gni @@ -279,6 +279,7 @@ template("musl_libs") { sources_orig -= [ "src/thread/${musl_arch}/__set_thread_area.s", "src/string/memcpy.c", + "src/string/memmove.c", "src/string/memchr.c", "src/string/memcmp.c", "src/string/strcpy.c", @@ -428,6 +429,7 @@ template("musl_libs") { "$OPTRTDIR/string/aarch64/strrchr.S", ] asmflags = [ + "-D__memmove_aarch64 = memmove", "-D__memcpy_aarch64 = memcpy", "-D__memchr_aarch64 = memchr", "-D__memset_aarch64 = memset", diff --git a/porting/linux/user/arch/aarch64/syscall_arch.h b/porting/linux/user/arch/aarch64/syscall_arch.h new file mode 100644 index 0000000000000000000000000000000000000000..ecc7d75d8ed7944d3359633d16935af29f1534a8 --- /dev/null +++ b/porting/linux/user/arch/aarch64/syscall_arch.h @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +#define __asm_syscall(...) do { \ + __asm__ __volatile__ ( "svc 0" \ + : "=r"(x0) : __VA_ARGS__ : "memory", "cc"); \ + return x0; \ + } while (0) + +static inline long __syscall0(long n) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0"); + __asm_syscall("r"(x8)); +} + +static inline long __syscall1(long n, long a) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + __asm_syscall("r"(x8), "0"(x0)); +} + +static inline long __syscall2(long n, long a, long b) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + __asm_syscall("r"(x8), "0"(x0), "r"(x1)); +} + +static inline long __syscall3(long n, long a, long b, long c) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2)); +} + +static inline long __syscall4(long n, long a, long b, long c, long d) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)); +} + +static inline long __syscall5(long n, long a, long b, long c, long d, long e) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)); +} + +static inline long __syscall6(long n, long a, long b, long c, long d, long e, long f) +{ + register long x8 __asm__("x8") = n; + register long x0 __asm__("x0") = a; + register long x1 __asm__("x1") = b; + register long x2 __asm__("x2") = c; + register long x3 __asm__("x3") = d; + register long x4 __asm__("x4") = e; + register long x5 __asm__("x5") = f; + __asm_syscall("r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)); +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__kernel_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6.39" +#define VDSO_CGR_SYM "__kernel_clock_getres" +#define VDSO_CGR_VER "LINUX_2.6.39" +#define VDSO_GTD_SYM "__kernel_gettimeofday" +#define VDSO_GTD_VER "LINUX_2.6.39" + +#define IPC_64 0 diff --git a/porting/linux/user/ldso/dynlink.c b/porting/linux/user/ldso/dynlink.c index 1a6fa9dab921d32df413c8fc2070c4dd9cbb8a96..d0022fc9ea89f915dcf6eec3281f32feb5217d5d 100644 --- a/porting/linux/user/ldso/dynlink.c +++ b/porting/linux/user/ldso/dynlink.c @@ -1757,8 +1757,6 @@ struct dso *load_library( ldso.namespace = namespace; ns_add_dso(namespace, &ldso); } - /* increase libc dlopen refcnt */ - a_inc(&ldso.nr_dlopen); return &ldso; } if (strchr(name, '/')) { @@ -1777,8 +1775,6 @@ struct dso *load_library( p = find_library_by_name(name, namespace, check_inherited); if (p) { LD_LOGD("load_library find_library_by_name found p, return it!"); - /* increase dlopen refcnt */ - a_inc(&p->nr_dlopen); return p; } if (strlen(name) > NAME_MAX) { @@ -1839,8 +1835,6 @@ struct dso *load_library( if (!p->shortname && pathname != name) p->shortname = strrchr(p->name, '/')+1; close(fd); - /* increase dlopen refcnt */ - a_inc(&p->nr_dlopen); LD_LOGD("load_library find_library_by_fstat, found p and return it!"); return p; } @@ -1886,7 +1880,6 @@ struct dso *load_library( p->ino = st.st_ino; p->needed_by = needed_by; p->name = p->buf; - p->nr_dlopen = 1; p->runtime_loaded = runtime; strcpy(p->name, pathname); /* Add a shortname only if name arg was not an explicit pathname. */ @@ -2487,7 +2480,6 @@ void __dls3(size_t *sp, size_t *auxv) #ifdef OHOS_ENABLE_PARAMETER InitParameterClient(); #endif - musl_log_reset(); ld_log_reset(); /* If the main program was already loaded by the kernel, * AT_PHDR will point to some location other than the dynamic @@ -2787,7 +2779,7 @@ static void prepare_lazy(struct dso *p) } /* add namespace function */ -static void *dlopen_impl( +static void *dlopen_impl_orig( const char *file, int mode, const char *namespace, const void *caller_addr, const dl_extinfo *extinfo) { struct dso *volatile p, *orig_tail, *orig_syms_tail, *orig_lazy_head, *next; @@ -2802,9 +2794,6 @@ static void *dlopen_impl( bool reserved_address = false; bool reserved_address_recursive = false; struct reserved_address_params reserved_params = {0}; -#ifdef HANDLE_RANDOMIZATION - void *handle = 0; -#endif #ifdef LOAD_ORDER_RANDOMIZATION struct loadtasks *tasks = NULL; struct loadtask *task = NULL; @@ -2812,12 +2801,8 @@ static void *dlopen_impl( #endif if (!file) { - LD_LOGD("dlopen_impl file is null, return head."); -#ifdef HANDLE_RANDOMIZATION - return assign_valid_handle(head); -#else + LD_LOGD("dlopen_impl_orig file is null, return head."); return head; -#endif } if (extinfo) { @@ -2908,16 +2893,16 @@ static void *dlopen_impl( #ifdef LOAD_ORDER_RANDOMIZATION tasks = create_loadtasks(); if (!tasks) { - LD_LOGE("dlopen_impl create loadtasks failed"); + LD_LOGE("dlopen_impl_orig create loadtasks failed"); goto end; } task = create_loadtask(file, head, ns, true); if (!task) { - LD_LOGE("dlopen_impl create loadtask failed"); + LD_LOGE("dlopen_impl_orig create loadtask failed"); goto end; } if (!load_library_header(task)) { - LD_LOGE("dlopen_impl load library header failed for %{public}s", task->name); + LD_LOGE("dlopen_impl_orig load library header failed for %{public}s", task->name); goto end; } if (reserved_address) { @@ -2925,7 +2910,7 @@ static void *dlopen_impl( } } if (!task->p) { - LD_LOGE("dlopen_impl load library failed for %{public}s", task->name); + LD_LOGE("dlopen_impl_orig load library failed for %{public}s", task->name); error(noload ? "Library %s is not already loaded" : "Error loading shared library %s: %m", @@ -3005,15 +2990,6 @@ static void *dlopen_impl( if (tls_cnt != orig_tls_cnt) install_new_tls(); orig_tail = tail; - -#ifdef HANDLE_RANDOMIZATION - handle = assign_valid_handle(p); - if (handle == 0) { - LD_LOGE("generate random handle failed"); - do_dlclose(p); - p = 0; - } -#endif end: debug.state = RT_CONSISTENT; _dl_debug_state(); @@ -3031,11 +3007,39 @@ end: internal_free(ctor_queue); } pthread_setcancelstate(cs, 0); + return p; +} + +static void *dlopen_impl( + const char *file, int mode, const char *namespace, const void *caller_addr, const dl_extinfo *extinfo){ + struct dso* p = (struct dso*)dlopen_impl_orig(file, mode, namespace, caller_addr, extinfo); + + if (p == NULL) { + return p; + } + + p->nr_dlopen++; + if (p->bfs_built) { + for (int i = 0; p->deps[i]; i++) { + p->deps[i]->nr_dlopen++; + + if (mode & RTLD_NODELETE) { + p->deps[i]->flags |= DSO_FLAGS_NODELETE; + } + } + } + #ifdef HANDLE_RANDOMIZATION + void *handle = assign_valid_handle(p); + if (handle == NULL) { + LD_LOGE("dlopen_impl: generate random handle failed"); + do_dlclose(p); + } + return handle; -#else - return p; #endif + + return p; } void *dlopen(const char *file, int mode) @@ -3252,8 +3256,10 @@ static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra) if (!p) p=head; p = p->next; ra2dso = true; +#ifndef HANDLE_RANDOMIZATION } else if (__dl_invalid_handle(p)) { return 0; +#endif } else { use_deps = 1; ns = p->namespace; @@ -3278,9 +3284,8 @@ static void *do_dlsym(struct dso *p, const char *s, const char *v, void *ra) return laddr(def.dso, def.sym->st_value); } -static int do_dlclose(struct dso *p) +static int dlclose_impl(struct dso *p) { - int old; size_t n; struct dso *d; @@ -3297,8 +3302,7 @@ static int do_dlclose(struct dso *p) return 0; } - old = a_fetch_add(&p->nr_dlopen, -1); - if (old > 1) + if (--(p->nr_dlopen) > 0) return 0; /* call destructors if needed */ @@ -3384,6 +3388,46 @@ static int do_dlclose(struct dso *p) return 0; } +static char* dlclose_deps_black_list[] = +{ + "/system/lib64/libhidebug.so", + "/system/lib64/libmsdp_neardetect_algorithm.z.so", + "/vendor/lib64/libhril_hdf.z.so" +}; + +static int do_dlclose(struct dso *p) +{ + bool ldclose_deps = true; + + for (int i = 0; i < sizeof(dlclose_deps_black_list)/sizeof(char*); i++) { + if (!strcmp(dlclose_deps_black_list[i], p->name)) { + ldclose_deps = false; + break; + } + } + + size_t deps_num; + + for (deps_num = 0; p->deps[deps_num]; deps_num++); + + struct dso **deps_bak = malloc(deps_num*sizeof(struct dso*)); + if (deps_bak != NULL) { + memcpy(deps_bak, p->deps, deps_num*sizeof(struct dso*)); + } + + LD_LOGI("do_dlclose name=%{public}s count=%{public}d by_dlopen=%{public}d", p->name, p->nr_dlopen, p->by_dlopen); + dlclose_impl(p); + + if (ldclose_deps) { + for (size_t i = 0; i < deps_num; i++) { + LD_LOGI("do_dlclose name=%{public}s count=%{public}d by_dlopen=%{public}d", deps_bak[i]->name, deps_bak[i]->nr_dlopen, deps_bak[i]->by_dlopen); + dlclose_impl(deps_bak[i]); + } + } + + free(deps_bak); +} + hidden int __dlclose(void *p) { int rc; @@ -3487,7 +3531,6 @@ int dladdr(const void *addr_arg, Dl_info *info) hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra) { void *res; - musl_log_reset(); ld_log_reset(); pthread_rwlock_rdlock(&lock); #ifdef HANDLE_RANDOMIZATION @@ -3511,7 +3554,6 @@ hidden void *__dlsym(void *restrict p, const char *restrict s, void *restrict ra hidden void *__dlvsym(void *restrict p, const char *restrict s, const char *restrict v, void *restrict ra) { void *res; - musl_log_reset(); ld_log_reset(); pthread_rwlock_rdlock(&lock); #ifdef HANDLE_RANDOMIZATION @@ -4104,8 +4146,6 @@ static bool load_library_header(struct loadtask *task) ns_add_dso(namespace, &ldso); } task->isloaded = true; - /* increase libc dlopen refcnt */ - a_inc(&ldso.nr_dlopen); task->p = &ldso; return true; } @@ -4121,9 +4161,7 @@ static bool load_library_header(struct loadtask *task) /* Search in namespace */ task->p = find_library_by_name(name, namespace, check_inherited); if (task->p) { - /* increase dlopen refcnt */ task->isloaded = true; - a_inc(&task->p->nr_dlopen); return true; } if (strlen(name) > NAME_MAX) { @@ -4189,9 +4227,7 @@ static bool load_library_header(struct loadtask *task) } close(task->fd); task->fd = -1; - /* increase dlopen refcnt */ task->isloaded = true; - a_inc(&task->p->nr_dlopen); return true; } @@ -4297,7 +4333,6 @@ static void task_load_library(struct loadtask *task, struct reserved_address_par if (!runtime) { reclaim_gaps(task->p); } - task->p->nr_dlopen = 1; task->p->runtime_loaded = runtime; if (runtime) task->p->by_dlopen = 1; diff --git a/porting/linux/user/src/internal/syscall.h b/porting/linux/user/src/internal/syscall.h index fb64c282263db57faaf10ee27c3e51ee1a2fde65..c546260ba001e0f8e984fa41993ac58dba88d9be 100644 --- a/porting/linux/user/src/internal/syscall.h +++ b/porting/linux/user/src/internal/syscall.h @@ -377,4 +377,7 @@ hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); hidden void *__vdsosym(const char *, const char *); +hidden void __get_vdso_info(); +hidden void *__get_vdso_addr(const char *, const char *); + #endif diff --git a/porting/linux/user/src/internal/vdso.c b/porting/linux/user/src/internal/vdso.c new file mode 100644 index 0000000000000000000000000000000000000000..3cb1d25b6690d3f3674b099d5bdabcd392ec435e --- /dev/null +++ b/porting/linux/user/src/internal/vdso.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "libc.h" +#include "syscall.h" + +#ifdef VDSO_USEFUL + +#if ULONG_MAX == 0xffffffff +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Phdr Phdr; +typedef Elf32_Sym Sym; +typedef Elf32_Verdef Verdef; +typedef Elf32_Verdaux Verdaux; +#else +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Phdr Phdr; +typedef Elf64_Sym Sym; +typedef Elf64_Verdef Verdef; +typedef Elf64_Verdaux Verdaux; +#endif + +static int checkver(Verdef *def, int vsym, const char *vername, char *strings) +{ + vsym &= 0x7fff; + for (;;) { + if (!(def->vd_flags & VER_FLG_BASE) + && (def->vd_ndx & 0x7fff) == vsym) + break; + if (def->vd_next == 0) + return 0; + def = (Verdef *)((char *)def + def->vd_next); + } + Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux); + return !strcmp(vername, strings + aux->vda_name); +} + +#define OK_TYPES (1<e_phoff); + size_t *dynv=0, base=-1; + for (i=0; ie_phnum; i++, ph=(void *)((char *)ph+eh->e_phentsize)) { + if (ph->p_type == PT_LOAD) + base = (size_t)eh + ph->p_offset - ph->p_vaddr; + else if (ph->p_type == PT_DYNAMIC) + dynv = (void *)((char *)eh + ph->p_offset); + } + if (!dynv || base==(size_t)-1) return ; + + for (i=0; dynv[i]; i+=2) { + void *p = (void *)(base + dynv[i+1]); + switch(dynv[i]) { + case DT_STRTAB: vdso_info.strings = p; break; + case DT_SYMTAB: vdso_info.syms = p; break; + case DT_HASH: vdso_info.hashtab = p; break; + case DT_VERSYM: vdso_info.versym = p; break; + case DT_VERDEF: vdso_info.verdef = p; break; + } + } + vdso_info.base = base; + return ; +} + +void *__get_vdso_addr(const char *vername, const char *name) +{ + if (!vdso_info.strings || !vdso_info.syms || !vdso_info.hashtab) return 0; + if (!vdso_info.verdef) vdso_info.versym = 0; + + size_t i; + for (i=0; i>4) & OK_BINDS)) continue; + if (!vdso_info.syms[i].st_shndx) continue; + if (strcmp(name, vdso_info.strings+vdso_info.syms[i].st_name)) continue; + if (vdso_info.versym && !checkver(vdso_info.verdef, vdso_info.versym[i], vername, vdso_info.strings)) + continue; + return (void *)(vdso_info.base + vdso_info.syms[i].st_value); + } + + return 0; +} + +#endif diff --git a/porting/linux/user/src/time/clock_getres.c b/porting/linux/user/src/time/clock_getres.c new file mode 100644 index 0000000000000000000000000000000000000000..d594b6466a5346b9522ac1bfd99c5e28d8e8817c --- /dev/null +++ b/porting/linux/user/src/time/clock_getres.c @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "syscall.h" +#include "atomic.h" + +#ifdef VDSO_CGR_SYM + +static void *volatile vdso_cgr; + +static int cgr_init(clockid_t clk, struct timespec *ts) +{ + __get_vdso_info(); + void *p = __get_vdso_addr(VDSO_CGR_VER, VDSO_CGR_SYM); + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))p; + a_cas_p(&vdso_cgr, (void *)cgr_init, p); + return f ? f(clk, ts) : -ENOSYS; +} + +static void *volatile vdso_cgr = (void *)cgr_init; + +#endif + +int clock_getres(clockid_t clk, struct timespec *ts) +{ + int r; +#ifdef VDSO_CGR_SYM + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))vdso_cgr; + if (f) { + r = f(clk, ts); + if (!r) return r; + if (r == -EINVAL) return __syscall_ret(r); + } +#endif + +#ifdef SYS_clock_getres_time64 + /* On a 32-bit arch, use the old syscall if it exists. */ + if (SYS_clock_getres != SYS_clock_getres_time64) { + long ts32[2]; + r = __syscall(SYS_clock_getres, clk, ts32); + if (!r && ts) { + ts->tv_sec = ts32[0]; + ts->tv_nsec = ts32[1]; + } + return __syscall_ret(r); + } +#endif + /* If reaching this point, it's a 64-bit arch or time64-only + * 32-bit arch and we can get result directly into timespec. */ + return syscall(SYS_clock_getres, clk, ts); +} diff --git a/porting/linux/user/src/time/clock_gettime.c b/porting/linux/user/src/time/clock_gettime.c new file mode 100644 index 0000000000000000000000000000000000000000..b1912f1499ec63752c19892c81ecac91ca98bd26 --- /dev/null +++ b/porting/linux/user/src/time/clock_gettime.c @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "syscall.h" +#include "atomic.h" + +#ifdef VDSO_CGT_SYM + +static void *volatile vdso_func; + +#ifdef VDSO_CGT32_SYM +static void *volatile vdso_func_32; +static int cgt_time32_wrap(clockid_t clk, struct timespec *ts) +{ + long ts32[2]; + int (*f)(clockid_t, long[2]) = + (int (*)(clockid_t, long[2]))vdso_func_32; + int r = f(clk, ts32); + if (!r) { + /* Fallback to syscalls if time32 overflowed. Maybe + * we lucked out and somehow migrated to a kernel with + * time64 syscalls available. */ + if (ts32[0] < 0) { + a_cas_p(&vdso_func, (void *)cgt_time32_wrap, 0); + return -ENOSYS; + } + ts->tv_sec = ts32[0]; + ts->tv_nsec = ts32[1]; + } + return r; +} +#endif + +static int cgt_init(clockid_t clk, struct timespec *ts) +{ + __get_vdso_info(); + void *p = __get_vdso_addr(VDSO_CGT_VER, VDSO_CGT_SYM); +#ifdef VDSO_CGT32_SYM + if (!p) { + void *q = __get_vdso_addr(VDSO_CGT32_VER, VDSO_CGT32_SYM); + if (q) { + a_cas_p(&vdso_func_32, 0, q); + p = cgt_time32_wrap; + } + } +#endif + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))p; + a_cas_p(&vdso_func, (void *)cgt_init, p); + return f ? f(clk, ts) : -ENOSYS; +} + +static void *volatile vdso_func = (void *)cgt_init; + +#endif + +int __clock_gettime(clockid_t clk, struct timespec *ts) +{ + int r; + +#ifdef VDSO_CGT_SYM + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))vdso_func; + if (f) { + r = f(clk, ts); + if (!r) return r; + if (r == -EINVAL) return __syscall_ret(r); + /* Fall through on errors other than EINVAL. Some buggy + * vdso implementations return ENOSYS for clocks they + * can't handle, rather than making the syscall. This + * also handles the case where cgt_init fails to find + * a vdso function to use. */ + } +#endif + +#ifdef SYS_clock_gettime64 + r = -ENOSYS; + if (sizeof(time_t) > 4) + r = __syscall(SYS_clock_gettime64, clk, ts); + if (SYS_clock_gettime == SYS_clock_gettime64 || r!=-ENOSYS) + return __syscall_ret(r); + long ts32[2]; + r = __syscall(SYS_clock_gettime, clk, ts32); + if (r==-ENOSYS && clk==CLOCK_REALTIME) { + r = __syscall(SYS_gettimeofday, ts32, 0); + ts32[1] *= 1000; + } + if (!r) { + ts->tv_sec = ts32[0]; + ts->tv_nsec = ts32[1]; + return r; + } + return __syscall_ret(r); +#else + r = __syscall(SYS_clock_gettime, clk, ts); + if (r == -ENOSYS) { + if (clk == CLOCK_REALTIME) { + __syscall(SYS_gettimeofday, ts, 0); + ts->tv_nsec = (int)ts->tv_nsec * 1000; + return 0; + } + r = -EINVAL; + } + return __syscall_ret(r); +#endif +} + +weak_alias(__clock_gettime, clock_gettime); diff --git a/porting/linux/user/src/time/gettimeofday.c b/porting/linux/user/src/time/gettimeofday.c new file mode 100644 index 0000000000000000000000000000000000000000..836655ac33e3d2e2e2bb67b206df2a03035b69d3 --- /dev/null +++ b/porting/linux/user/src/time/gettimeofday.c @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include "syscall.h" +#include "atomic.h" + +#ifdef VDSO_GTD_SYM + +static void *volatile vdso_gtd; + +static int gtd_init(struct timeval *tv, void *tz) +{ + __get_vdso_info(); + void *p = __get_vdso_addr(VDSO_GTD_VER, VDSO_GTD_SYM); + int (*f)(struct timeval *, void *) = + (int (*)(struct timval *, void *))p; + a_cas_p(&vdso_gtd, (void *)gtd_init, p); + return f ? f(tv, tz) : -ENOSYS; +} + +static void *volatile vdso_gtd = (void *)gtd_init; + +#endif + +int gettimeofday(struct timeval *restrict tv, void *restrict tz) +{ +#ifdef VDSO_GTD_SYM + int r; + int (*f)(struct timeval *, void *) = + (int (*)(struct timeval *, void *))vdso_gtd; + if (f) { + r = f(tv, tz); + if (!r) return r; + if (r == -EINVAL) return __syscall_ret(r); + } +#endif + + struct timespec ts; + if (!tv) return 0; + clock_gettime(CLOCK_REALTIME, &ts); + tv->tv_sec = ts.tv_sec; + tv->tv_usec = (int)ts.tv_nsec / 1000; + return 0; +} diff --git a/porting/linux/user/src/time/time.c b/porting/linux/user/src/time/time.c new file mode 100644 index 0000000000000000000000000000000000000000..679c14282e535d764fb67c692e5fbe2550db9a4e --- /dev/null +++ b/porting/linux/user/src/time/time.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2022 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include "syscall.h" +#include "atomic.h" + +#ifdef VDSO_TIME_SYM + +static void *volatile vdso_time; + +static time_t time_init(time_t *t) +{ + __get_vdso_info(); + void *p = __get_vdso_addr(VDSO_TIME_VER, VDSO_TIME_SYM); + time_t (*f)(time_t *) = + (time_t (*)(time_t *))p; + a_cas_p(&vdso_time, (void *)time_init, p); + return f ? f(t) : -ENOSYS; +} + +static void *volatile vdso_time = (void *)time_init; + +#endif + +time_t time(time_t *t) +{ +#ifdef VDSO_TIME_SYM + time_t (*f)(time_t *) = + (time_t (*)(time_t *))vdso_time; + if (f) { + return f(t); + } +#endif + + struct timespec ts; + __clock_gettime(CLOCK_REALTIME, &ts); + if (t) *t = ts.tv_sec; + return ts.tv_sec; +} diff --git a/porting/liteos_m_iccarm/kernel/src/malloc.c b/porting/liteos_m_iccarm/kernel/src/malloc.c index 674cb9883cf79337a115b10bf4e57a8c8c5d9ba0..c0c907c7b764c042427a09a79d1eb8630fd3d2d4 100644 --- a/porting/liteos_m_iccarm/kernel/src/malloc.c +++ b/porting/liteos_m_iccarm/kernel/src/malloc.c @@ -33,6 +33,7 @@ #include "los_config.h" #include "los_memory.h" +#ifdef LOSCFG_LIBC_ICCARM_MALLOC void *calloc(size_t nitems, size_t size) { size_t real_size; @@ -105,3 +106,4 @@ void *realloc(void *ptr, size_t size) return LOS_MemRealloc(OS_SYS_MEM_ADDR, ptr, size); } +#endif diff --git a/src/thread/sem_open.c b/src/thread/sem_open.c index de8555c5a6869ceda20c956cc6c8d1ea8470a138..6fb0c5b25d79167b9b476dc475d399367e4dc9d8 100644 --- a/src/thread/sem_open.c +++ b/src/thread/sem_open.c @@ -163,10 +163,12 @@ int sem_close(sem_t *sem) int i; LOCK(lock); for (i=0; i