diff --git a/components/lwp/lwp_syscall.c b/components/lwp/lwp_syscall.c index 8f65f606ef..e33ca0ea9e 100644 --- a/components/lwp/lwp_syscall.c +++ b/components/lwp/lwp_syscall.c @@ -76,6 +76,8 @@ #include "lwp_ipc_internal.h" #include +#include + #ifndef GRND_NONBLOCK #define GRND_NONBLOCK 0x0001 #endif /* GRND_NONBLOCK */ @@ -2621,6 +2623,54 @@ sysret_t sys_stat(const char *file, struct stat *buf) return ret; } +sysret_t sys_lstat(const char *file, struct stat *buf) +{ + int ret = 0; + int err; + size_t len; + size_t copy_len; + char *copy_path; + struct stat statbuff = {0}; + + if (!lwp_user_accessable((void *)buf, sizeof(struct stat))) + { + return -EFAULT; + } + + len = lwp_user_strlen(file, &err); + if (err) + { + return -EFAULT; + } + + copy_path = (char*)rt_malloc(len + 1); + if (!copy_path) + { + return -ENOMEM; + } + + copy_len = lwp_get_from_user(copy_path, (void*)file, len); + if (copy_len == 0) + { + rt_free(copy_path); + return -EFAULT; + } + copy_path[copy_len] = '\0'; +#ifdef RT_USING_DFS_V2 + ret = _SYS_WRAP(dfs_file_lstat(copy_path, &statbuff)); +#else + ret = _SYS_WRAP(stat(copy_path, &statbuff)); +#endif + rt_free(copy_path); + + if (ret == 0) + { + lwp_put_to_user(buf, &statbuff, sizeof statbuff); + } + + return ret; +} + sysret_t sys_notimpl(void) { return -ENOSYS; @@ -4292,6 +4342,99 @@ sysret_t sys_setaffinity(pid_t pid, size_t size, void *set) return -1; } +sysret_t sys_getaffinity(pid_t pid, size_t size, void *set) +{ +#ifdef ARCH_MM_MMU + cpu_set_t mask; + struct rt_lwp *lwp; + + if (size <= 0 || size > sizeof(cpu_set_t)) + { + return -EINVAL; + } + if (!lwp_user_accessable(set, size)) + { + return -EFAULT; + } + + if (pid == 0) lwp = lwp_self(); + else lwp = lwp_from_pid(pid); + if (!lwp) + { + return -ESRCH; + } + +#ifdef RT_USING_SMP + if (lwp->bind_cpu == RT_CPUS_NR) /* not bind */ + { + CPU_ZERO_S(size, &mask); + } + else /* set bind cpu */ + { + /* TODO: only single-core bindings are now supported of rt-smart */ + CPU_SET_S(lwp->bind_cpu, size, &mask); + } +#else + CPU_SET_S(0, size, &mask); +#endif + + if (lwp_put_to_user(set, &mask, size) != size) + { + return -1; + } + + return 0; +#else + return -1; +#endif +} + +sysret_t sys_sysinfo(void *info) +{ +#ifdef ARCH_MM_MMU + struct sysinfo kinfo = {0}; + rt_size_t total_pages = 0, free_pages = 0; + + if (!lwp_user_accessable(info, sizeof(struct sysinfo))) + { + return -EFAULT; + } + + kinfo.uptime = rt_tick_get_millisecond() / 1000; + /* TODO: 1, 5, and 15 minute load averages */ + kinfo.loads[0] = kinfo.loads[1] = kinfo.loads[2] = rt_object_get_length(RT_Object_Class_Thread); + rt_page_get_info(&total_pages, &free_pages); + kinfo.totalram = total_pages; + kinfo.freeram = free_pages; + + /* TODO: implementation procfs, here is counter the lwp number */ + struct lwp_avl_struct *pids = lwp_get_pid_ary(); + for (int index = 0; index < RT_LWP_MAX_NR; index++) + { + struct rt_lwp *lwp = (struct rt_lwp *)pids[index].data; + + if (lwp) + { + kinfo.procs++; + } + } + + rt_page_high_get_info(&total_pages, &free_pages); + kinfo.totalhigh = total_pages; + kinfo.freehigh = free_pages; + kinfo.mem_unit = ARCH_PAGE_SIZE; + + if (lwp_put_to_user(info, &kinfo, sizeof(struct sysinfo)) != sizeof(struct sysinfo)) + { + return -EFAULT; + } + + return 0; +#else + return -1; +#endif +} + sysret_t sys_sched_setparam(pid_t pid, void *param) { struct sched_param *sched_param = (struct sched_param *)param; @@ -4901,6 +5044,60 @@ sysret_t sys_umount2(char *__special_file, int __flags) return ret; } +sysret_t sys_link(const char *existing, const char *new) +{ + int ret = -1; + +#ifdef ARCH_MM_MMU + int err; + + lwp_user_strlen(existing, &err); + if (err) + { + return -EFAULT; + } + + lwp_user_strlen(new, &err); + if (err) + { + return -EFAULT; + } +#endif +#ifdef RT_USING_DFS_V2 + ret = dfs_file_link(existing, new); +#else + SET_ERRNO(EFAULT); +#endif + return (ret < 0 ? GET_ERRNO() : ret); +} + +sysret_t sys_symlink(const char *existing, const char *new) +{ + int ret = -1; + +#ifdef ARCH_MM_MMU + int err; + + lwp_user_strlen(existing, &err); + if (err) + { + return -EFAULT; + } + + lwp_user_strlen(new, &err); + if (err) + { + return -EFAULT; + } +#endif +#ifdef RT_USING_DFS_V2 + ret = dfs_file_symlink(existing, new); +#else + SET_ERRNO(EFAULT); +#endif + return (ret < 0 ? GET_ERRNO() : ret); +} + const static struct rt_syscall_def func_table[] = { SYSCALL_SIGN(sys_exit), /* 01 */ @@ -5110,7 +5307,7 @@ const static struct rt_syscall_def func_table[] = SYSCALL_SIGN(sys_mq_notify), SYSCALL_SIGN(sys_mq_getsetattr), SYSCALL_SIGN(sys_mq_close), - SYSCALL_SIGN(sys_stat), //TODO should be replaced by sys_lstat if symbolic link are implemented + SYSCALL_SIGN(sys_lstat), SYSCALL_SIGN(sys_uname), /* 170 */ SYSCALL_SIGN(sys_statfs), SYSCALL_SIGN(sys_statfs64), @@ -5119,6 +5316,10 @@ const static struct rt_syscall_def func_table[] = SYSCALL_SIGN(sys_openat), /* 175 */ SYSCALL_SIGN(sys_mount), SYSCALL_SIGN(sys_umount2), + SYSCALL_SIGN(sys_link), + SYSCALL_SIGN(sys_symlink), + SYSCALL_SIGN(sys_getaffinity), /* 180 */ + SYSCALL_SIGN(sys_sysinfo), }; const void *lwp_get_sys_api(rt_uint32_t number) diff --git a/components/mm/mm_page.c b/components/mm/mm_page.c index 9b3fdf74e7..f72083a9d3 100644 --- a/components/mm/mm_page.c +++ b/components/mm/mm_page.c @@ -46,6 +46,7 @@ static struct rt_page *page_list_high[RT_PAGE_MAX_ORDER]; #define page_start ((rt_page_t)rt_mpr_start) static rt_size_t page_nr; +static rt_size_t _high_pages_nr; static rt_size_t early_offset; static const char *get_name(rt_varea_t varea) @@ -672,6 +673,28 @@ void rt_page_get_info(rt_size_t *total_nr, rt_size_t *free_nr) *free_nr = total_free; } +void rt_page_high_get_info(rt_size_t *total_nr, rt_size_t *free_nr) +{ + int i; + rt_size_t total_free = 0; + rt_base_t level; + + level = rt_hw_interrupt_disable(); + for (i = 0; i < RT_PAGE_MAX_ORDER; i++) + { + struct rt_page *p = page_list_high[i]; + + while (p) + { + total_free += (1UL << i); + p = p->next; + } + } + rt_hw_interrupt_enable(level); + *total_nr = _high_pages_nr; + *free_nr = total_free; +} + static void _install_page(rt_page_t mpr_head, rt_region_t region, void *insert_handler) { void (*insert)(rt_page_t *page_list, rt_page_t page, int size_bits) = insert_handler; @@ -723,6 +746,10 @@ static void _install_page(rt_page_t mpr_head, rt_region_t region, void *insert_h /* insert to list */ rt_page_t *page_list = _get_page_list((void *)region.start); + if (page_list == page_list_high) + { + _high_pages_nr += 1 << (size_bits - ARCH_PAGE_SHIFT); + } insert(page_list, (rt_page_t)((char *)p - early_offset), size_bits - ARCH_PAGE_SHIFT); region.start += (1UL << size_bits); } diff --git a/components/mm/mm_page.h b/components/mm/mm_page.h index 4ced90f9aa..e5386640dc 100644 --- a/components/mm/mm_page.h +++ b/components/mm/mm_page.h @@ -88,6 +88,8 @@ rt_size_t rt_page_bits(rt_size_t size); void rt_page_get_info(rt_size_t *total_nr, rt_size_t *free_nr); +void rt_page_high_get_info(rt_size_t *total_nr, rt_size_t *free_nr); + void *rt_page_page2addr(struct rt_page *p); struct rt_page *rt_page_addr2page(void *addr);