mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2026-10-02 14:23:19 +08:00
sync smart & dfs (#8672)
Signed-off-by: xqyjlj <xqyjlj@126.com> Signed-off-by: Shell <smokewood@qq.com> Co-authored-by: xqyjlj <xqyjlj@126.com>
This commit is contained in:
@@ -81,7 +81,7 @@ CONFIG_RT_USING_CONSOLE=y
|
||||
CONFIG_RT_CONSOLEBUF_SIZE=256
|
||||
CONFIG_RT_CONSOLE_DEVICE_NAME="uart0"
|
||||
CONFIG_RT_VER_NUM=0x50100
|
||||
# CONFIG_RT_USING_STDC_ATOMIC is not set
|
||||
CONFIG_RT_USING_STDC_ATOMIC=y
|
||||
CONFIG_RT_BACKTRACE_LEVEL_MAX_NR=32
|
||||
CONFIG_RT_USING_CACHE=y
|
||||
CONFIG_RT_USING_HW_ATOMIC=y
|
||||
@@ -203,7 +203,7 @@ CONFIG_RT_USING_SOFT_RTC=y
|
||||
CONFIG_RT_USING_SDIO=y
|
||||
CONFIG_RT_SDIO_STACK_SIZE=4096
|
||||
CONFIG_RT_SDIO_THREAD_PRIORITY=15
|
||||
CONFIG_RT_MMCSD_STACK_SIZE=4096
|
||||
CONFIG_RT_MMCSD_STACK_SIZE=16384
|
||||
CONFIG_RT_MMCSD_THREAD_PREORITY=22
|
||||
CONFIG_RT_MMCSD_MAX_PARTITION=16
|
||||
# CONFIG_RT_SDIO_DEBUG is not set
|
||||
|
||||
@@ -54,6 +54,7 @@
|
||||
#define RT_CONSOLEBUF_SIZE 256
|
||||
#define RT_CONSOLE_DEVICE_NAME "uart0"
|
||||
#define RT_VER_NUM 0x50100
|
||||
#define RT_USING_STDC_ATOMIC
|
||||
#define RT_BACKTRACE_LEVEL_MAX_NR 32
|
||||
#define RT_USING_CACHE
|
||||
#define RT_USING_HW_ATOMIC
|
||||
@@ -138,7 +139,7 @@
|
||||
#define RT_USING_SDIO
|
||||
#define RT_SDIO_STACK_SIZE 4096
|
||||
#define RT_SDIO_THREAD_PRIORITY 15
|
||||
#define RT_MMCSD_STACK_SIZE 4096
|
||||
#define RT_MMCSD_STACK_SIZE 16384
|
||||
#define RT_MMCSD_THREAD_PREORITY 22
|
||||
#define RT_MMCSD_MAX_PARTITION 16
|
||||
#define RT_USING_SPI
|
||||
|
||||
@@ -10,10 +10,6 @@
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_SMART)
|
||||
#include <console.h>
|
||||
#endif
|
||||
|
||||
#include <virtio_console.h>
|
||||
|
||||
static int console_init()
|
||||
@@ -36,8 +32,6 @@ static int console_init()
|
||||
}
|
||||
INIT_ENV_EXPORT(console_init);
|
||||
|
||||
#ifdef FINSH_USING_MSH
|
||||
|
||||
static int console(int argc, char **argv)
|
||||
{
|
||||
rt_err_t result = RT_EOK;
|
||||
@@ -48,23 +42,6 @@ static int console(int argc, char **argv)
|
||||
{
|
||||
rt_kprintf("console change to %s\n", argv[2]);
|
||||
rt_console_set_device(argv[2]);
|
||||
|
||||
#ifdef RT_USING_POSIX_DEVIO
|
||||
{
|
||||
rt_device_t dev = rt_device_find(argv[2]);
|
||||
|
||||
if (dev != RT_NULL)
|
||||
{
|
||||
#ifdef RT_USING_SMART
|
||||
console_set_iodev(dev);
|
||||
#else
|
||||
rt_kprintf("TODO not supported\n");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#else
|
||||
finsh_set_device(argv[2]);
|
||||
#endif /* RT_USING_POSIX_DEVIO */
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -81,5 +58,3 @@ static int console(int argc, char **argv)
|
||||
return result;
|
||||
}
|
||||
MSH_CMD_EXPORT(console, set console name);
|
||||
|
||||
#endif /* FINSH_USING_MSH */
|
||||
|
||||
@@ -8,7 +8,6 @@
|
||||
* 2020/10/7 bernard the first version
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
int main(void)
|
||||
|
||||
@@ -45,6 +45,7 @@ endif
|
||||
|
||||
config RT_USING_DFS_V2
|
||||
bool "DFS v2.0"
|
||||
select RT_USING_DEVICE_OPS
|
||||
endchoice
|
||||
|
||||
if RT_USING_DFS_V1
|
||||
@@ -170,6 +171,13 @@ endif
|
||||
depends on RT_USING_DFS_ROMFS
|
||||
default n
|
||||
|
||||
if RT_USING_SMART
|
||||
config RT_USING_DFS_PTYFS
|
||||
bool "Using Pseudo-Teletype Filesystem (UNIX98 PTY)"
|
||||
depends on RT_USING_DFS_DEVFS
|
||||
default y
|
||||
endif
|
||||
|
||||
config RT_USING_DFS_CROMFS
|
||||
bool "Enable ReadOnly compressed file system on flash"
|
||||
default n
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -10,6 +10,9 @@
|
||||
#ifndef __DEVICE_FS_H__
|
||||
#define __DEVICE_FS_H__
|
||||
|
||||
int dfs_devfs_init(void);
|
||||
const struct dfs_file_ops *dfs_devfs_fops(void);
|
||||
mode_t dfs_devfs_device_to_mode(struct rt_device *device);
|
||||
void dfs_devfs_device_add(rt_device_t device);
|
||||
int dfs_devfs_update(void);
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -145,7 +145,7 @@ static struct dfs_vnode *dfs_mqueue_create_vnode(struct dfs_dentry *dentry, int
|
||||
}
|
||||
mq_file->msg_size = 8192;
|
||||
mq_file->max_msgs = 10;
|
||||
strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX);
|
||||
strncpy(mq_file->name, dentry->pathname + 1, RT_NAME_MAX - 1);
|
||||
dfs_mqueue_insert_after(&(mq_file->list));
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
# The Pseudo Terminal Filesystem
|
||||
|
||||
The device register on ptyfs is also registered in device frameworks with `rt_device_register()`.
|
||||
|
||||
It's possible to mount a new ptyfs instance on another path. Each instance is isolated to each other. And they don't share the id system. But generally speaking, you have to mount the ptyfs on `/dev` root, since all the file nodes in ptyfs are devices.
|
||||
@@ -0,0 +1,11 @@
|
||||
# RT-Thread building script for component
|
||||
|
||||
from building import *
|
||||
|
||||
cwd = GetCurrentDir()
|
||||
src = Glob('*.c')
|
||||
CPPPATH = [cwd]
|
||||
|
||||
group = DefineGroup('Filesystem', src, depend = ['RT_USING_DFS', 'RT_USING_DFS_PTYFS'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-12-02 Shell init ver.
|
||||
*/
|
||||
#ifndef __FS_PTYFS_H__
|
||||
#define __FS_PTYFS_H__
|
||||
#include <rtthread.h>
|
||||
|
||||
typedef rt_base_t ptsno_t;
|
||||
|
||||
ptsno_t ptyfs_register_pts(rt_device_t ptmx, rt_device_t pts);
|
||||
|
||||
rt_err_t ptyfs_unregister_pts(rt_device_t ptmx, ptsno_t ptsno);
|
||||
|
||||
const char *ptyfs_get_rootpath(rt_device_t ptmx);
|
||||
|
||||
#endif /* __FS_PTYFS_H__ */
|
||||
@@ -29,6 +29,9 @@ rt_weak const struct romfs_dirent _root_dirent[] =
|
||||
{
|
||||
{ROMFS_DIRENT_DIR, "dev", RT_NULL, 0},
|
||||
{ROMFS_DIRENT_DIR, "mnt", RT_NULL, 0},
|
||||
{ROMFS_DIRENT_DIR, "proc", RT_NULL, 0},
|
||||
{ROMFS_DIRENT_DIR, "etc", RT_NULL, 0},
|
||||
{ROMFS_DIRENT_DIR, "bin", RT_NULL, 0},
|
||||
{ROMFS_DIRENT_DIR, "dummy", (rt_uint8_t *)_dummy, sizeof(_dummy) / sizeof(_dummy[0])},
|
||||
{ROMFS_DIRENT_FILE, "dummy.txt", _dummy_txt, sizeof(_dummy_txt)},
|
||||
};
|
||||
|
||||
@@ -202,6 +202,7 @@ int dfs_tmpfs_ioctl(struct dfs_file *file, int cmd, void *args)
|
||||
|
||||
superblock = d_file->sb;
|
||||
RT_ASSERT(superblock != NULL);
|
||||
RT_UNUSED(superblock);
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
@@ -317,26 +318,21 @@ static ssize_t dfs_tmpfs_read(struct dfs_file *file, void *buf, size_t count, of
|
||||
return length;
|
||||
}
|
||||
|
||||
static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
static ssize_t _dfs_tmpfs_write(struct tmpfs_file *d_file, const void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
struct tmpfs_file *d_file;
|
||||
struct tmpfs_sb *superblock;
|
||||
|
||||
d_file = (struct tmpfs_file *)file->vnode->data;
|
||||
RT_ASSERT(d_file != NULL);
|
||||
|
||||
superblock = d_file->sb;
|
||||
RT_ASSERT(superblock != NULL);
|
||||
|
||||
rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER);
|
||||
|
||||
if (count + *pos > file->vnode->size)
|
||||
if (count + *pos > d_file->size)
|
||||
{
|
||||
rt_uint8_t *ptr;
|
||||
ptr = rt_realloc(d_file->data, *pos + count);
|
||||
if (ptr == NULL)
|
||||
{
|
||||
rt_mutex_release(&file->vnode->lock);
|
||||
rt_set_errno(-ENOMEM);
|
||||
return 0;
|
||||
}
|
||||
@@ -347,7 +343,6 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co
|
||||
/* update d_file and file size */
|
||||
d_file->data = ptr;
|
||||
d_file->size = *pos + count;
|
||||
file->vnode->size = d_file->size;
|
||||
LOG_D("tmpfile ptr:%x, size:%d", ptr, d_file->size);
|
||||
}
|
||||
|
||||
@@ -356,6 +351,21 @@ static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t co
|
||||
|
||||
/* update file current position */
|
||||
*pos += count;
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t dfs_tmpfs_write(struct dfs_file *file, const void *buf, size_t count, off_t *pos)
|
||||
{
|
||||
struct tmpfs_file *d_file;
|
||||
|
||||
d_file = (struct tmpfs_file *)file->vnode->data;
|
||||
RT_ASSERT(d_file != NULL);
|
||||
|
||||
rt_mutex_take(&file->vnode->lock, RT_WAITING_FOREVER);
|
||||
|
||||
count = _dfs_tmpfs_write(d_file, buf, count, pos);
|
||||
|
||||
rt_mutex_release(&file->vnode->lock);
|
||||
|
||||
return count;
|
||||
@@ -504,6 +514,7 @@ static int dfs_tmpfs_getdents(struct dfs_file *file,
|
||||
|
||||
superblock = d_file->sb;
|
||||
RT_ASSERT(superblock != RT_NULL);
|
||||
RT_UNUSED(superblock);
|
||||
|
||||
/* make integer count */
|
||||
count = (count / sizeof(struct dirent));
|
||||
@@ -797,6 +808,8 @@ static ssize_t dfs_tmp_page_read(struct dfs_file *file, struct dfs_page *page)
|
||||
|
||||
ssize_t dfs_tmp_page_write(struct dfs_page *page)
|
||||
{
|
||||
off_t pos;
|
||||
size_t count = 0;
|
||||
struct tmpfs_file *d_file;
|
||||
|
||||
if (page->aspace->vnode->type == FT_DIRECTORY)
|
||||
@@ -806,13 +819,16 @@ ssize_t dfs_tmp_page_write(struct dfs_page *page)
|
||||
|
||||
d_file = (struct tmpfs_file *)(page->aspace->vnode->data);
|
||||
RT_ASSERT(d_file != RT_NULL);
|
||||
|
||||
rt_mutex_take(&page->aspace->vnode->lock, RT_WAITING_FOREVER);
|
||||
if (page->len > 0)
|
||||
memcpy(d_file->data + page->fpos, page->page, page->len);
|
||||
|
||||
{
|
||||
pos = page->fpos;
|
||||
count = _dfs_tmpfs_write(d_file, page->page, page->len, &pos);
|
||||
}
|
||||
rt_mutex_release(&page->aspace->vnode->lock);
|
||||
|
||||
return F_OK;
|
||||
return count;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
#include <rtatomic.h>
|
||||
#include <rtdevice.h>
|
||||
|
||||
#ifndef ATTR_MODE_SET
|
||||
#define ATTR_MODE_SET (1 << 6)
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_ATIME_SET
|
||||
#define ATTR_ATIME_SET (1 << 7)
|
||||
#endif
|
||||
@@ -33,6 +37,14 @@
|
||||
#define ATTR_MTIME_SET (1 << 8)
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_UID_SET
|
||||
#define ATTR_UID_SET (1 << 9)
|
||||
#endif
|
||||
|
||||
#ifndef ATTR_GID_SET
|
||||
#define ATTR_GID_SET (1 << 10)
|
||||
#endif
|
||||
|
||||
#ifndef AT_SYMLINK_NOFOLLOW
|
||||
#define AT_SYMLINK_NOFOLLOW 0x100
|
||||
#endif
|
||||
|
||||
@@ -175,20 +175,25 @@ int dfs_file_isdir(const char *path);
|
||||
int dfs_file_access(const char *path, mode_t mode);
|
||||
int dfs_file_chdir(const char *path);
|
||||
char *dfs_file_getcwd(char *buf, size_t size);
|
||||
char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode);
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
int dfs_file_mmap2(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
|
||||
|
||||
int dfs_file_mmap(struct dfs_file *file, struct dfs_mmap2_args *mmap2);
|
||||
#endif
|
||||
|
||||
char *dfs_nolink_path(struct dfs_mnt **mnt, char *fullpath, int mode);
|
||||
|
||||
/* 0x5254 is just a magic number to make these relatively unique ("RT") */
|
||||
#define RT_FIOFTRUNCATE 0x52540000U
|
||||
#define RT_FIOGETADDR 0x52540001U
|
||||
#define RT_FIOMMAP2 0x52540002U
|
||||
|
||||
/* dfs_file_realpath mode */
|
||||
#define DFS_REALPATH_EXCEPT_LAST 0
|
||||
#define DFS_REALPATH_EXCEPT_NONE 1
|
||||
#define DFS_REALPATH_ONLY_LAST 3
|
||||
|
||||
char *dfs_file_realpath(struct dfs_mnt **mnt, const char *fullpath, int mode);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -32,7 +32,9 @@ struct dfs_partition
|
||||
struct dfs_attr
|
||||
{
|
||||
unsigned int ia_valid;
|
||||
mode_t st_mode;
|
||||
uid_t st_uid;
|
||||
gid_t st_gid;
|
||||
mode_t st_mode;
|
||||
struct timespec ia_atime;
|
||||
struct timespec ia_mtime;
|
||||
};
|
||||
|
||||
@@ -23,6 +23,8 @@ extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
struct rt_varea;
|
||||
struct rt_aspace;
|
||||
struct dfs_vnode;
|
||||
struct dfs_dentry;
|
||||
struct dfs_aspace;
|
||||
@@ -30,7 +32,8 @@ struct dfs_aspace;
|
||||
struct dfs_mmap
|
||||
{
|
||||
rt_list_t mmap_node;
|
||||
struct rt_varea *varea;
|
||||
struct rt_aspace *aspace;
|
||||
void *vaddr;
|
||||
};
|
||||
|
||||
struct dfs_page
|
||||
|
||||
@@ -557,6 +557,111 @@ exit:
|
||||
return newfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The fd in the current process dup to designate fd table.
|
||||
*
|
||||
* @param oldfd is the fd in current process.
|
||||
*
|
||||
* @param fdtab is the fd table to dup, if empty, use global (_fdtab).
|
||||
*
|
||||
* @return -1 on failed or the allocated file descriptor.
|
||||
*/
|
||||
int dfs_dup_to(int oldfd, struct dfs_fdtable *fdtab)
|
||||
{
|
||||
int newfd = -1;
|
||||
struct dfs_fdtable *fdt = NULL;
|
||||
|
||||
if (dfs_file_lock() != RT_EOK)
|
||||
{
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
if (fdtab == NULL)
|
||||
{
|
||||
fdtab = &_fdtab;
|
||||
}
|
||||
|
||||
/* check old fd */
|
||||
fdt = dfs_fdtable_get();
|
||||
if ((oldfd < 0) || (oldfd >= fdt->maxfd))
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
if (!fdt->fds[oldfd])
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
/* get a new fd*/
|
||||
newfd = _fdt_slot_alloc(fdtab, DFS_STDIO_OFFSET);
|
||||
if (newfd >= 0)
|
||||
{
|
||||
fdtab->fds[newfd] = fdt->fds[oldfd];
|
||||
|
||||
/* inc ref_count */
|
||||
rt_atomic_add(&(fdtab->fds[newfd]->ref_count), 1);
|
||||
}
|
||||
exit:
|
||||
dfs_file_unlock();
|
||||
|
||||
return newfd;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The fd in the designate fd table dup to current process.
|
||||
*
|
||||
* @param oldfd is the fd in the designate fd table.
|
||||
*
|
||||
* @param fdtab is the fd table for oldfd, if empty, use global (_fdtab).
|
||||
*
|
||||
* @return -1 on failed or the allocated file descriptor.
|
||||
*/
|
||||
int dfs_dup_from(int oldfd, struct dfs_fdtable *fdtab)
|
||||
{
|
||||
int newfd = -1;
|
||||
struct dfs_file *file;
|
||||
|
||||
if (dfs_file_lock() != RT_EOK)
|
||||
{
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
if (fdtab == NULL)
|
||||
{
|
||||
fdtab = &_fdtab;
|
||||
}
|
||||
|
||||
/* check old fd */
|
||||
if ((oldfd < 0) || (oldfd >= fdtab->maxfd))
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
if (!fdtab->fds[oldfd])
|
||||
{
|
||||
goto exit;
|
||||
}
|
||||
/* get a new fd*/
|
||||
newfd = fd_new();
|
||||
file = fd_get(newfd);
|
||||
if (newfd >= 0 && file)
|
||||
{
|
||||
file->mode = fdtab->fds[oldfd]->mode;
|
||||
file->flags = fdtab->fds[oldfd]->flags;
|
||||
file->fops = fdtab->fds[oldfd]->fops;
|
||||
file->dentry = dfs_dentry_ref(fdtab->fds[oldfd]->dentry);
|
||||
file->vnode = fdtab->fds[oldfd]->vnode;
|
||||
file->mmap_context = RT_NULL;
|
||||
file->data = fdtab->fds[oldfd]->data;
|
||||
}
|
||||
|
||||
dfs_file_close(fdtab->fds[oldfd]);
|
||||
|
||||
exit:
|
||||
fdt_fd_release(fdtab, oldfd);
|
||||
dfs_file_unlock();
|
||||
|
||||
return newfd;
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
sysret_t sys_dup(int oldfd)
|
||||
#else
|
||||
@@ -856,7 +961,11 @@ int dfs_fd_dump(int argc, char** argv)
|
||||
{
|
||||
int index;
|
||||
|
||||
dfs_file_lock();
|
||||
if (dfs_file_lock() != RT_EOK)
|
||||
{
|
||||
return -RT_ENOSYS;
|
||||
}
|
||||
|
||||
for (index = 0; index < _fdtab.maxfd; index++)
|
||||
{
|
||||
struct dfs_file *file = _fdtab.fds[index];
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -269,7 +269,6 @@ static void dfs_pcache_thread(void *parameter)
|
||||
{
|
||||
page->len = page->size;
|
||||
}
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
if (aspace->ops->write)
|
||||
{
|
||||
aspace->ops->write(page);
|
||||
@@ -676,9 +675,14 @@ static int dfs_page_unmap(struct dfs_page *page)
|
||||
|
||||
if (map)
|
||||
{
|
||||
void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos);
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE);
|
||||
rt_varea_unmap_page(map->varea, vaddr);
|
||||
rt_varea_t varea;
|
||||
void *vaddr;
|
||||
|
||||
varea = rt_aspace_query(map->aspace, map->vaddr);
|
||||
RT_ASSERT(varea);
|
||||
vaddr = dfs_aspace_vaddr(varea, page->fpos);
|
||||
|
||||
rt_varea_unmap_page(varea, vaddr);
|
||||
|
||||
rt_free(map);
|
||||
}
|
||||
@@ -741,7 +745,6 @@ static void dfs_page_release(struct dfs_page *page)
|
||||
{
|
||||
page->len = page->size;
|
||||
}
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
if (aspace->ops->write)
|
||||
{
|
||||
aspace->ops->write(page);
|
||||
@@ -995,7 +998,6 @@ static struct dfs_page *dfs_aspace_load_page(struct dfs_file *file, off_t pos)
|
||||
page->size = ARCH_PAGE_SIZE;
|
||||
page->fpos = pos / ARCH_PAGE_SIZE * ARCH_PAGE_SIZE;
|
||||
aspace->ops->read(file, page);
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
page->ref_count ++;
|
||||
|
||||
dfs_page_insert(page);
|
||||
@@ -1105,7 +1107,6 @@ int dfs_aspace_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
|
||||
len = count > len ? len : count;
|
||||
if (len)
|
||||
{
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
rt_memcpy(ptr, page->page + *pos - page->fpos, len);
|
||||
ptr += len;
|
||||
*pos += len;
|
||||
@@ -1158,7 +1159,6 @@ int dfs_aspace_write(struct dfs_file *file, const void *buf, size_t count, off_t
|
||||
len = page->fpos + ARCH_PAGE_SIZE - *pos;
|
||||
len = count > len ? len : count;
|
||||
rt_memcpy(page->page + *pos - page->fpos, ptr, len);
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
ptr += len;
|
||||
*pos += len;
|
||||
count -= len;
|
||||
@@ -1225,7 +1225,7 @@ int dfs_aspace_flush(struct dfs_aspace *aspace)
|
||||
{
|
||||
page->len = page->size;
|
||||
}
|
||||
//rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, page->page, page->size);
|
||||
|
||||
if (aspace->ops->write)
|
||||
{
|
||||
aspace->ops->write(page);
|
||||
@@ -1277,6 +1277,7 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
|
||||
void *ret = RT_NULL;
|
||||
struct dfs_page *page;
|
||||
struct dfs_aspace *aspace = file->vnode->aspace;
|
||||
rt_aspace_t target_aspace = varea->aspace;
|
||||
|
||||
page = dfs_page_lookup(file, dfs_aspace_fpos(varea, vaddr));
|
||||
if (page)
|
||||
@@ -1284,7 +1285,8 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
|
||||
struct dfs_mmap *map = (struct dfs_mmap *)rt_calloc(1, sizeof(struct dfs_mmap));
|
||||
if (map)
|
||||
{
|
||||
void *pg_paddr = rt_kmem_v2p(page->page);
|
||||
void *pg_vaddr = page->page;
|
||||
void *pg_paddr = rt_kmem_v2p(pg_vaddr);
|
||||
int err = rt_varea_map_range(varea, vaddr, pg_paddr, page->size);
|
||||
if (err == RT_EOK)
|
||||
{
|
||||
@@ -1301,10 +1303,12 @@ void *dfs_aspace_mmap(struct dfs_file *file, struct rt_varea *varea, void *vaddr
|
||||
* fetching of the next instruction can see the coherent data with the data cache,
|
||||
* TLB, MMU, main memory, and all the other observers in the computer system.
|
||||
*/
|
||||
rt_hw_cpu_dcache_ops(RT_HW_CACHE_FLUSH, vaddr, ARCH_PAGE_SIZE);
|
||||
rt_hw_cpu_icache_ops(RT_HW_CACHE_INVALIDATE, vaddr, ARCH_PAGE_SIZE);
|
||||
|
||||
ret = page->page;
|
||||
map->varea = varea;
|
||||
ret = pg_vaddr;
|
||||
map->aspace = target_aspace;
|
||||
map->vaddr = vaddr;
|
||||
dfs_aspace_lock(aspace);
|
||||
rt_list_insert_after(&page->mmap_head, &map->mmap_node);
|
||||
dfs_page_release(page);
|
||||
@@ -1329,6 +1333,8 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea)
|
||||
{
|
||||
struct dfs_vnode *vnode = file->vnode;
|
||||
struct dfs_aspace *aspace = vnode->aspace;
|
||||
void *unmap_start = varea->start;
|
||||
void *unmap_end = (char *)unmap_start + varea->size;
|
||||
|
||||
if (aspace)
|
||||
{
|
||||
@@ -1347,20 +1353,32 @@ int dfs_aspace_unmap(struct dfs_file *file, struct rt_varea *varea)
|
||||
{
|
||||
rt_list_t *node, *tmp;
|
||||
struct dfs_mmap *map;
|
||||
rt_varea_t map_varea = RT_NULL;
|
||||
|
||||
node = page->mmap_head.next;
|
||||
|
||||
while (node != &page->mmap_head)
|
||||
{
|
||||
rt_aspace_t map_aspace;
|
||||
map = rt_list_entry(node, struct dfs_mmap, mmap_node);
|
||||
tmp = node;
|
||||
node = node->next;
|
||||
|
||||
if (map && varea == map->varea)
|
||||
if (map && varea->aspace == map->aspace
|
||||
&& map->vaddr >= unmap_start && map->vaddr < unmap_end)
|
||||
{
|
||||
void *vaddr = dfs_aspace_vaddr(map->varea, page->fpos);
|
||||
void *vaddr = map->vaddr;
|
||||
map_aspace = map->aspace;
|
||||
|
||||
rt_varea_unmap_page(map->varea, vaddr);
|
||||
if (!map_varea || map_varea->aspace != map_aspace ||
|
||||
vaddr < map_varea->start ||
|
||||
vaddr >= map_varea->start + map_varea->size)
|
||||
{
|
||||
/* lock the tree so we don't access uncompleted data */
|
||||
map_varea = rt_aspace_query(map_aspace, vaddr);
|
||||
}
|
||||
|
||||
rt_varea_unmap_page(map_varea, vaddr);
|
||||
|
||||
if (varea->attr == MMU_MAP_U_RWCB && page->fpos < page->aspace->vnode->size)
|
||||
{
|
||||
@@ -1405,7 +1423,7 @@ int dfs_aspace_page_unmap(struct dfs_file *file, struct rt_varea *varea, void *v
|
||||
tmp = node;
|
||||
node = node->next;
|
||||
|
||||
if (map && varea == map->varea)
|
||||
if (map && varea->aspace == map->aspace && vaddr == map->vaddr)
|
||||
{
|
||||
if (varea->attr == MMU_MAP_U_RWCB)
|
||||
{
|
||||
|
||||
@@ -57,17 +57,6 @@ menuconfig RT_USING_SERIAL
|
||||
default 64
|
||||
endif
|
||||
|
||||
config RT_USING_TTY
|
||||
bool "Using TTY SYSTEM"
|
||||
depends on RT_USING_SMART
|
||||
default y
|
||||
|
||||
if RT_USING_TTY
|
||||
config RT_TTY_DEBUG
|
||||
bool "Using TTY DEBUG"
|
||||
default n
|
||||
endif
|
||||
|
||||
config RT_USING_CAN
|
||||
bool "Using CAN device drivers"
|
||||
default n
|
||||
|
||||
@@ -29,6 +29,10 @@
|
||||
#include <rtdevice.h> /* for wqueue_init */
|
||||
#endif /* RT_USING_POSIX_DEVIO */
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
#include <devfs.h>
|
||||
#endif /* RT_USING_DFS_V2 */
|
||||
|
||||
#ifdef RT_USING_DEVICE
|
||||
|
||||
#ifdef RT_USING_DEVICE_OPS
|
||||
@@ -78,6 +82,10 @@ rt_err_t rt_device_register(rt_device_t dev,
|
||||
rt_wqueue_init(&(dev->wait_queue));
|
||||
#endif /* RT_USING_POSIX_DEVIO */
|
||||
|
||||
#ifdef RT_USING_DFS_V2
|
||||
dfs_devfs_device_add(dev);
|
||||
#endif /* RT_USING_DFS_V2 */
|
||||
|
||||
return RT_EOK;
|
||||
}
|
||||
RTM_EXPORT(rt_device_register);
|
||||
|
||||
@@ -107,7 +107,7 @@ struct rt_pic_irq
|
||||
rt_uint32_t mode;
|
||||
|
||||
rt_uint32_t priority;
|
||||
RT_DECLARE_BITMAP(affinity, RT_CPUS_NR);
|
||||
RT_BITMAP_DECLARE(affinity, RT_CPUS_NR);
|
||||
|
||||
rt_list_t list;
|
||||
rt_list_t children_nodes;
|
||||
|
||||
@@ -179,4 +179,5 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
||||
rt_uint32_t flag,
|
||||
void *data);
|
||||
|
||||
rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial);
|
||||
#endif
|
||||
|
||||
@@ -191,4 +191,5 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
||||
rt_uint32_t flag,
|
||||
void *data);
|
||||
|
||||
rt_err_t rt_hw_serial_register_tty(struct rt_serial_device *serial);
|
||||
#endif
|
||||
|
||||
@@ -33,5 +33,6 @@ void rt_completion_init(struct rt_completion *completion);
|
||||
rt_err_t rt_completion_wait(struct rt_completion *completion,
|
||||
rt_int32_t timeout);
|
||||
void rt_completion_done(struct rt_completion *completion);
|
||||
rt_err_t rt_completion_wakeup(struct rt_completion *completion);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-11-20 Shell Add cond var API in kernel
|
||||
*/
|
||||
|
||||
#ifndef __LWP_TERMINAL_CONDVAR_H__
|
||||
#define __LWP_TERMINAL_CONDVAR_H__
|
||||
|
||||
#include <rtthread.h>
|
||||
|
||||
typedef struct rt_condvar
|
||||
{
|
||||
#ifdef USING_RT_OBJECT
|
||||
struct rt_object parent;
|
||||
#endif
|
||||
rt_atomic_t waiters_cnt;
|
||||
rt_atomic_t waiting_mtx;
|
||||
struct rt_wqueue event;
|
||||
} *rt_condvar_t;
|
||||
|
||||
void rt_condvar_init(rt_condvar_t cv, char *name);
|
||||
int rt_condvar_timedwait(rt_condvar_t cv, rt_mutex_t mtx, int suspend_flag,
|
||||
rt_tick_t timeout);
|
||||
int rt_condvar_signal(rt_condvar_t cv);
|
||||
int rt_condvar_broadcast(rt_condvar_t cv);
|
||||
|
||||
rt_inline void rt_condvar_detach(rt_condvar_t cv)
|
||||
{
|
||||
RT_UNUSED(cv);
|
||||
return ;
|
||||
}
|
||||
|
||||
#endif /* __LWP_TERMINAL_CONDVAR_H__ */
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include <rtdef.h>
|
||||
#include <rtconfig.h>
|
||||
#include "condvar.h"
|
||||
|
||||
/**
|
||||
* Pipe Device
|
||||
@@ -34,6 +35,7 @@ struct rt_pipe_device
|
||||
int writer;
|
||||
int reader;
|
||||
|
||||
struct rt_condvar waitfor_parter;
|
||||
struct rt_mutex lock;
|
||||
};
|
||||
typedef struct rt_pipe_device rt_pipe_t;
|
||||
|
||||
@@ -49,6 +49,7 @@ int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int timeout);
|
||||
int rt_wqueue_wait_killable(rt_wqueue_t *queue, int condition, int timeout);
|
||||
int rt_wqueue_wait_interruptible(rt_wqueue_t *queue, int condition, int timeout);
|
||||
void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key);
|
||||
void rt_wqueue_wakeup_all(rt_wqueue_t *queue, void *key);
|
||||
|
||||
#define DEFINE_WAIT_FUNC(name, function) \
|
||||
struct rt_wqueue_node name = { \
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "ipc/completion.h"
|
||||
#include "ipc/dataqueue.h"
|
||||
#include "ipc/workqueue.h"
|
||||
#include "ipc/condvar.h"
|
||||
#include "ipc/waitqueue.h"
|
||||
#include "ipc/pipe.h"
|
||||
#include "ipc/poll.h"
|
||||
|
||||
@@ -134,7 +134,7 @@ RTM_EXPORT(rt_completion_wait);
|
||||
*
|
||||
* @param completion is a pointer to a completion object.
|
||||
*/
|
||||
void rt_completion_done(struct rt_completion *completion)
|
||||
static int _completion_done(struct rt_completion *completion)
|
||||
{
|
||||
rt_base_t level;
|
||||
rt_err_t error;
|
||||
@@ -145,7 +145,7 @@ void rt_completion_done(struct rt_completion *completion)
|
||||
if (RT_COMPLETION_FLAG(completion) == RT_COMPLETED)
|
||||
{
|
||||
rt_spin_unlock_irqrestore(&_completion_lock, level);
|
||||
return;
|
||||
return -RT_EBUSY;
|
||||
}
|
||||
|
||||
suspend_thread = RT_COMPLETION_THREAD(completion);
|
||||
@@ -160,10 +160,38 @@ void rt_completion_done(struct rt_completion *completion)
|
||||
LOG_D("%s: failed to resume thread", __func__);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* no thread waiting */
|
||||
error = -RT_EEMPTY;
|
||||
}
|
||||
|
||||
completion->susp_thread_n_flag = RT_COMPLETION_NEW_STAT(RT_NULL, RT_COMPLETED);
|
||||
|
||||
rt_spin_unlock_irqrestore(&_completion_lock, level);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function indicates a completion has done.
|
||||
*
|
||||
* @param completion is a pointer to a completion object.
|
||||
*/
|
||||
void rt_completion_done(struct rt_completion *completion)
|
||||
{
|
||||
_completion_done(completion);
|
||||
}
|
||||
RTM_EXPORT(rt_completion_done);
|
||||
|
||||
/**
|
||||
* @brief This function indicates a completion has done and wakeup the thread
|
||||
*
|
||||
* @param completion is a pointer to a completion object.
|
||||
*/
|
||||
rt_err_t rt_completion_wakeup(struct rt_completion *completion)
|
||||
{
|
||||
return _completion_done(completion);
|
||||
}
|
||||
RTM_EXPORT(rt_completion_wakeup);
|
||||
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-11-20 Shell Support of condition variable
|
||||
*/
|
||||
#define DBG_TAG "ipc.condvar"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <rtdevice.h>
|
||||
#include <rtatomic.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
static struct rt_spinlock _local_cv_queue_lock = RT_SPINLOCK_INIT;
|
||||
|
||||
#define CV_ASSERT_LOCKED(cv) \
|
||||
RT_ASSERT(!(cv)->waiting_mtx || \
|
||||
rt_mutex_get_owner((rt_mutex_t)(cv)->waiting_mtx) == \
|
||||
rt_thread_self())
|
||||
|
||||
void rt_condvar_init(rt_condvar_t cv, char *name)
|
||||
{
|
||||
#ifdef USING_RT_OBJECT
|
||||
/* TODO: support rt object */
|
||||
rt_object_init();
|
||||
#endif
|
||||
|
||||
rt_wqueue_init(&cv->event);
|
||||
rt_atomic_store(&cv->waiters_cnt, 0);
|
||||
rt_atomic_store(&cv->waiting_mtx, 0);
|
||||
}
|
||||
|
||||
static int _waitq_inqueue(rt_wqueue_t *queue, struct rt_wqueue_node *node,
|
||||
rt_tick_t timeout, int suspend_flag)
|
||||
{
|
||||
rt_thread_t tcb = node->polling_thread;
|
||||
rt_timer_t timer = &(tcb->thread_timer);
|
||||
rt_err_t ret;
|
||||
|
||||
if (queue->flag != RT_WQ_FLAG_WAKEUP)
|
||||
{
|
||||
ret = rt_thread_suspend_with_flag(tcb, suspend_flag);
|
||||
if (ret == RT_EOK)
|
||||
{
|
||||
rt_wqueue_add(queue, node);
|
||||
if (timeout != RT_WAITING_FOREVER)
|
||||
{
|
||||
rt_timer_control(timer, RT_TIMER_CTRL_SET_TIME, &timeout);
|
||||
|
||||
rt_timer_start(timer);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = RT_EOK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#define INIT_WAITQ_NODE(node) \
|
||||
{ \
|
||||
.polling_thread = rt_thread_self(), .key = 0, \
|
||||
.wakeup = __wqueue_default_wake, .wqueue = &cv->event, \
|
||||
.list = RT_LIST_OBJECT_INIT(node.list) \
|
||||
}
|
||||
|
||||
int rt_condvar_timedwait(rt_condvar_t cv, rt_mutex_t mtx, int suspend_flag,
|
||||
rt_tick_t timeout)
|
||||
{
|
||||
rt_err_t acq_mtx_succ, rc;
|
||||
rt_atomic_t waiting_mtx;
|
||||
struct rt_wqueue_node node = INIT_WAITQ_NODE(node);
|
||||
|
||||
/* not allowed in IRQ & critical section */
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1);
|
||||
CV_ASSERT_LOCKED(cv);
|
||||
|
||||
/**
|
||||
* for the worst case, this is racy with the following works to reset field
|
||||
* before mutex is taken. The spinlock then comes to rescue.
|
||||
*/
|
||||
rt_spin_lock(&_local_cv_queue_lock);
|
||||
waiting_mtx = rt_atomic_load(&cv->waiting_mtx);
|
||||
if (!waiting_mtx)
|
||||
acq_mtx_succ = rt_atomic_compare_exchange_strong(
|
||||
&cv->waiting_mtx, &waiting_mtx, (size_t)mtx);
|
||||
else
|
||||
acq_mtx_succ = 0;
|
||||
|
||||
rt_spin_unlock(&_local_cv_queue_lock);
|
||||
|
||||
if (acq_mtx_succ == 1 || waiting_mtx == (size_t)mtx)
|
||||
{
|
||||
rt_atomic_add(&cv->waiters_cnt, 1);
|
||||
|
||||
rt_enter_critical();
|
||||
|
||||
if (suspend_flag == RT_INTERRUPTIBLE)
|
||||
rc = _waitq_inqueue(&cv->event, &node, timeout, RT_INTERRUPTIBLE);
|
||||
else /* UNINTERRUPTIBLE is forbidden, since it's not safe for user space */
|
||||
rc = _waitq_inqueue(&cv->event, &node, timeout, RT_KILLABLE);
|
||||
|
||||
acq_mtx_succ = rt_mutex_release(mtx);
|
||||
RT_ASSERT(acq_mtx_succ == 0);
|
||||
rt_exit_critical();
|
||||
|
||||
if (rc == RT_EOK)
|
||||
{
|
||||
rt_schedule();
|
||||
|
||||
rc = rt_get_errno();
|
||||
rc = rc > 0 ? -rc : rc;
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_D("%s() failed to suspend", __func__);
|
||||
}
|
||||
|
||||
rt_wqueue_remove(&node);
|
||||
|
||||
rt_spin_lock(&_local_cv_queue_lock);
|
||||
if (rt_atomic_add(&cv->waiters_cnt, -1) == 1)
|
||||
{
|
||||
waiting_mtx = (size_t)mtx;
|
||||
acq_mtx_succ = rt_atomic_compare_exchange_strong(&cv->waiting_mtx,
|
||||
&waiting_mtx, 0);
|
||||
RT_ASSERT(acq_mtx_succ == 1);
|
||||
}
|
||||
rt_spin_unlock(&_local_cv_queue_lock);
|
||||
|
||||
acq_mtx_succ = rt_mutex_take(mtx, RT_WAITING_FOREVER);
|
||||
RT_ASSERT(acq_mtx_succ == 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG_D("%s: conflict waiting mutex", __func__);
|
||||
rc = -EBUSY;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** Keep in mind that we always operating when cv.waiting_mtx is taken */
|
||||
|
||||
int rt_condvar_signal(rt_condvar_t cv)
|
||||
{
|
||||
CV_ASSERT_LOCKED(cv);
|
||||
|
||||
/* to avoid spurious wakeups */
|
||||
if (rt_atomic_load(&cv->waiters_cnt) > 0)
|
||||
rt_wqueue_wakeup(&cv->event, 0);
|
||||
|
||||
cv->event.flag = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rt_condvar_broadcast(rt_condvar_t cv)
|
||||
{
|
||||
CV_ASSERT_LOCKED(cv);
|
||||
|
||||
/* to avoid spurious wakeups */
|
||||
if (rt_atomic_load(&cv->waiters_cnt) > 0)
|
||||
rt_wqueue_wakeup_all(&cv->event, 0);
|
||||
|
||||
cv->event.flag = 0;
|
||||
return 0;
|
||||
}
|
||||
@@ -9,11 +9,13 @@
|
||||
* 2017-11-08 JasonJiaJie fix memory leak issue when close a pipe.
|
||||
* 2023-06-28 shell return POLLHUP when writer closed its channel on poll()
|
||||
* fix flag test on pipe_fops_open()
|
||||
* 2023-12-02 shell Make read pipe operation interruptable.
|
||||
*/
|
||||
#include <rthw.h>
|
||||
#include <rtdevice.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/errno.h>
|
||||
#include <ipc/condvar.h>
|
||||
|
||||
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
|
||||
#include <unistd.h>
|
||||
@@ -69,12 +71,12 @@ static int pipe_fops_open(struct dfs_file *fd)
|
||||
|
||||
if ((fd->flags & O_ACCMODE) == O_RDONLY)
|
||||
{
|
||||
pipe->reader = 1;
|
||||
pipe->reader += 1;
|
||||
}
|
||||
|
||||
if ((fd->flags & O_ACCMODE) == O_WRONLY)
|
||||
{
|
||||
pipe->writer = 1;
|
||||
pipe->writer += 1;
|
||||
}
|
||||
if (fd->vnode->ref_count == 1)
|
||||
{
|
||||
@@ -86,6 +88,21 @@ static int pipe_fops_open(struct dfs_file *fd)
|
||||
}
|
||||
}
|
||||
|
||||
if ((fd->flags & O_ACCMODE) == O_RDONLY && !pipe->writer)
|
||||
{
|
||||
/* wait for partner */
|
||||
rc = rt_condvar_timedwait(&pipe->waitfor_parter, &pipe->lock,
|
||||
RT_INTERRUPTIBLE, RT_WAITING_FOREVER);
|
||||
if (rc != 0)
|
||||
{
|
||||
pipe->reader--;
|
||||
}
|
||||
}
|
||||
else if ((fd->flags & O_ACCMODE) == O_WRONLY)
|
||||
{
|
||||
rt_condvar_broadcast(&pipe->waitfor_parter);
|
||||
}
|
||||
|
||||
__exit:
|
||||
rt_mutex_release(&pipe->lock);
|
||||
|
||||
@@ -117,12 +134,12 @@ static int pipe_fops_close(struct dfs_file *fd)
|
||||
|
||||
if ((fd->flags & O_RDONLY) == O_RDONLY)
|
||||
{
|
||||
pipe->reader = 0;
|
||||
pipe->reader -= 1;
|
||||
}
|
||||
|
||||
if ((fd->flags & O_WRONLY) == O_WRONLY)
|
||||
{
|
||||
pipe->writer = 0;
|
||||
pipe->writer -= 1;
|
||||
while (!rt_list_isempty(&pipe->reader_queue.waiting_list))
|
||||
{
|
||||
rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
|
||||
@@ -234,7 +251,8 @@ static ssize_t pipe_fops_read(struct dfs_file *fd, void *buf, size_t count)
|
||||
|
||||
rt_mutex_release(&pipe->lock);
|
||||
rt_wqueue_wakeup(&pipe->writer_queue, (void*)POLLOUT);
|
||||
rt_wqueue_wait(&pipe->reader_queue, 0, -1);
|
||||
if (rt_wqueue_wait_interruptible(&pipe->reader_queue, 0, -1) == -RT_EINTR)
|
||||
return -EINTR;
|
||||
rt_mutex_take(&pipe->lock, RT_WAITING_FOREVER);
|
||||
}
|
||||
}
|
||||
@@ -309,7 +327,8 @@ static ssize_t pipe_fops_write(struct dfs_file *fd, const void *buf, size_t coun
|
||||
rt_mutex_release(&pipe->lock);
|
||||
rt_wqueue_wakeup(&pipe->reader_queue, (void*)POLLIN);
|
||||
/* pipe full, waiting on suspended write list */
|
||||
rt_wqueue_wait(&pipe->writer_queue, 0, -1);
|
||||
if (rt_wqueue_wait_interruptible(&pipe->writer_queue, 0, -1) == -RT_EINTR)
|
||||
return -EINTR;
|
||||
rt_mutex_take(&pipe->lock, -1);
|
||||
}
|
||||
rt_mutex_release(&pipe->lock);
|
||||
@@ -611,6 +630,8 @@ rt_pipe_t *rt_pipe_create(const char *name, int bufsz)
|
||||
rt_mutex_init(&pipe->lock, name, RT_IPC_FLAG_FIFO);
|
||||
rt_wqueue_init(&pipe->reader_queue);
|
||||
rt_wqueue_init(&pipe->writer_queue);
|
||||
rt_condvar_init(&pipe->waitfor_parter, "piwfp");
|
||||
|
||||
pipe->writer = 0;
|
||||
pipe->reader = 0;
|
||||
|
||||
@@ -674,6 +695,7 @@ int rt_pipe_delete(const char *name)
|
||||
|
||||
pipe = (rt_pipe_t *)device;
|
||||
|
||||
rt_condvar_detach(&pipe->waitfor_parter);
|
||||
rt_mutex_detach(&pipe->lock);
|
||||
#if defined(RT_USING_POSIX_DEVIO) && defined(RT_USING_POSIX_PIPE)
|
||||
resource_id_put(&id_mgr, pipe->pipeno);
|
||||
@@ -736,11 +758,6 @@ int pipe(int fildes[2])
|
||||
pipe->is_named = RT_FALSE; /* unamed pipe */
|
||||
pipe->pipeno = pipeno;
|
||||
rt_snprintf(dev_name, sizeof(dev_name), "/dev/%s", dname);
|
||||
fildes[0] = open(dev_name, O_RDONLY, 0);
|
||||
if (fildes[0] < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
fildes[1] = open(dev_name, O_WRONLY, 0);
|
||||
if (fildes[1] < 0)
|
||||
@@ -749,6 +766,12 @@ int pipe(int fildes[2])
|
||||
return -1;
|
||||
}
|
||||
|
||||
fildes[0] = open(dev_name, O_RDONLY, 0);
|
||||
if (fildes[0] < 0)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,11 @@
|
||||
* to blocked thread.
|
||||
* 2022-01-24 THEWON let rt_wqueue_wait return thread->error when using signal
|
||||
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
|
||||
* 2023-11-21 Shell Support wakeup_all
|
||||
*/
|
||||
#define DBG_TAG "ipc.waitqueue"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <rthw.h>
|
||||
@@ -64,7 +68,8 @@ int __wqueue_default_wake(struct rt_wqueue_node *wait, void *key)
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will wake up a pending thread on the specified waiting queue that meets the conditions.
|
||||
* @brief This function will wake up a pending thread on the specified
|
||||
* waiting queue that meets the conditions.
|
||||
*
|
||||
* @param queue is a pointer to the wait queue.
|
||||
*
|
||||
@@ -94,17 +99,89 @@ void rt_wqueue_wakeup(rt_wqueue_t *queue, void *key)
|
||||
entry = rt_list_entry(node, struct rt_wqueue_node, list);
|
||||
if (entry->wakeup(entry, key) == 0)
|
||||
{
|
||||
rt_thread_resume(entry->polling_thread);
|
||||
need_schedule = 1;
|
||||
/**
|
||||
* even though another thread may interrupt the thread and
|
||||
* wakeup it meanwhile, we can asuume that condition is ready
|
||||
*/
|
||||
entry->polling_thread->error = RT_EOK;
|
||||
if (!rt_thread_resume(entry->polling_thread))
|
||||
{
|
||||
need_schedule = 1;
|
||||
|
||||
rt_list_remove(&(entry->list));
|
||||
break;
|
||||
rt_list_remove(&(entry->list));
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
|
||||
if (need_schedule)
|
||||
rt_schedule();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This function will wake up all pending thread on the specified
|
||||
* waiting queue that meets the conditions.
|
||||
*
|
||||
* @param queue is a pointer to the wait queue.
|
||||
*
|
||||
* @param key is the wakeup conditions, but it is not effective now, because
|
||||
* default wakeup function always return 0.
|
||||
* If user wants to use it, user should define their own wakeup
|
||||
* function.
|
||||
*/
|
||||
void rt_wqueue_wakeup_all(rt_wqueue_t *queue, void *key)
|
||||
{
|
||||
rt_base_t level;
|
||||
int need_schedule = 0;
|
||||
|
||||
rt_list_t *queue_list;
|
||||
struct rt_list_node *node;
|
||||
struct rt_wqueue_node *entry;
|
||||
|
||||
queue_list = &(queue->waiting_list);
|
||||
|
||||
level = rt_spin_lock_irqsave(&(queue->spinlock));
|
||||
/* set wakeup flag in the queue */
|
||||
queue->flag = RT_WQ_FLAG_WAKEUP;
|
||||
|
||||
if (!(rt_list_isempty(queue_list)))
|
||||
{
|
||||
for (node = queue_list->next; node != queue_list; )
|
||||
{
|
||||
entry = rt_list_entry(node, struct rt_wqueue_node, list);
|
||||
if (entry->wakeup(entry, key) == 0)
|
||||
{
|
||||
/**
|
||||
* even though another thread may interrupt the thread and
|
||||
* wakeup it meanwhile, we can asuume that condition is ready
|
||||
*/
|
||||
entry->polling_thread->error = RT_EOK;
|
||||
if (!rt_thread_resume(entry->polling_thread))
|
||||
{
|
||||
need_schedule = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* wakeup happened too soon that waker hadn't slept */
|
||||
LOG_D("%s: Thread resume failed", __func__);
|
||||
}
|
||||
node = node->next;
|
||||
}
|
||||
else
|
||||
{
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&(queue->spinlock), level);
|
||||
if (need_schedule)
|
||||
rt_schedule();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -184,7 +261,7 @@ __exit_wakeup:
|
||||
|
||||
rt_wqueue_remove(&__wait);
|
||||
|
||||
return tid->error;
|
||||
return tid->error > 0 ? -tid->error : tid->error;
|
||||
}
|
||||
|
||||
int rt_wqueue_wait(rt_wqueue_t *queue, int condition, int msec)
|
||||
|
||||
@@ -136,6 +136,7 @@ rt_inline void rt_ktime_hrtimer_keep_errno(rt_ktime_hrtimer_t timer, rt_err_t er
|
||||
RT_ASSERT(timer != RT_NULL);
|
||||
|
||||
timer->error = err;
|
||||
rt_set_errno(-err);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1109,17 +1109,20 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id)
|
||||
|
||||
if (tag && id >= 0)
|
||||
{
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
if (!rt_list_isempty(&_aliases_nodes))
|
||||
{
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info->id == id)
|
||||
{
|
||||
np = info->np;
|
||||
break;
|
||||
if (info->id == id)
|
||||
{
|
||||
np = info->np;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1130,18 +1133,20 @@ struct rt_ofw_node *rt_ofw_get_alias_node(const char *tag, int id)
|
||||
int ofw_alias_node_id(struct rt_ofw_node *np)
|
||||
{
|
||||
int id;
|
||||
struct alias_info *info;
|
||||
struct alias_info *info = RT_NULL;
|
||||
|
||||
if (np)
|
||||
{
|
||||
id = -1;
|
||||
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
if (!rt_list_isempty(&_aliases_nodes))
|
||||
{
|
||||
if (info->np == np)
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
{
|
||||
id = info->id;
|
||||
break;
|
||||
if (info->np == np)
|
||||
{
|
||||
id = info->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1161,18 +1166,20 @@ int rt_ofw_get_alias_id(struct rt_ofw_node *np, const char *tag)
|
||||
if (np && tag)
|
||||
{
|
||||
id = -1;
|
||||
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
if (!rt_list_isempty(&_aliases_nodes))
|
||||
{
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info->np == np)
|
||||
{
|
||||
id = info->id;
|
||||
break;
|
||||
if (info->np == np)
|
||||
{
|
||||
id = info->id;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1192,17 +1199,19 @@ int rt_ofw_get_alias_last_id(const char *tag)
|
||||
if (tag)
|
||||
{
|
||||
id = -1;
|
||||
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
if (!rt_list_isempty(&_aliases_nodes))
|
||||
{
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
rt_list_for_each_entry(info, &_aliases_nodes, list)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (rt_strncmp(info->tag, tag, info->tag_len))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (info->id > id)
|
||||
{
|
||||
id = info->id;
|
||||
if (info->id > id)
|
||||
{
|
||||
id = info->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1465,7 +1474,7 @@ static const char *ofw_get_prop_fuzzy_name(const struct rt_ofw_node *np, const c
|
||||
char *sf, split_field[64];
|
||||
rt_size_t len = 0, max_ak = 0;
|
||||
const char *str, *result = RT_NULL;
|
||||
RT_DECLARE_BITMAP(ak, sizeof(split_field));
|
||||
RT_BITMAP_DECLARE(ak, sizeof(split_field));
|
||||
struct rt_ofw_prop *prop;
|
||||
|
||||
/*
|
||||
|
||||
@@ -8,6 +8,9 @@ src = []
|
||||
if not GetDepend(['RT_USING_SERIAL']):
|
||||
Return('group')
|
||||
|
||||
if GetDepend(['RT_USING_SMART']):
|
||||
src += Glob('serial_tty.c')
|
||||
|
||||
if GetDepend(['RT_USING_SERIAL_V2']):
|
||||
src += ['serial_v2.c']
|
||||
else:
|
||||
|
||||
@@ -909,7 +909,7 @@ static rt_ssize_t rt_serial_write(struct rt_device *dev,
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_TTY)
|
||||
#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_SMART)
|
||||
struct speed_baudrate_item
|
||||
{
|
||||
speed_t speed;
|
||||
@@ -1058,7 +1058,7 @@ static rt_err_t rt_serial_control(struct rt_device *dev,
|
||||
}
|
||||
break;
|
||||
#ifdef RT_USING_POSIX_STDIO
|
||||
#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_TTY)
|
||||
#if defined(RT_USING_POSIX_TERMIOS) && !defined(RT_USING_SMART)
|
||||
case TCGETA:
|
||||
{
|
||||
struct termios *tio = (struct termios*)args;
|
||||
@@ -1315,9 +1315,21 @@ rt_err_t rt_hw_serial_register(struct rt_serial_device *serial,
|
||||
device->fops = &_serial_fops;
|
||||
#endif
|
||||
|
||||
#if defined(RT_USING_SMART)
|
||||
rt_hw_serial_register_tty(serial);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(RT_USING_SMART) && defined(LWP_DEBUG)
|
||||
static volatile int _early_input = 0;
|
||||
int lwp_startup_debug_request(void)
|
||||
{
|
||||
return _early_input;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* ISR for serial interrupt */
|
||||
void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
|
||||
{
|
||||
@@ -1360,8 +1372,17 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
|
||||
rt_spin_unlock_irqrestore(&(serial->spinlock), level);
|
||||
}
|
||||
|
||||
/* invoke callback */
|
||||
if (serial->parent.rx_indicate != RT_NULL)
|
||||
/**
|
||||
* Invoke callback.
|
||||
* First try notify if any, and if notify is existed, rx_indicate()
|
||||
* is not callback. This seperate the priority and makes the reuse
|
||||
* of same serial device reasonable for RT console.
|
||||
*/
|
||||
if (serial->rx_notify.notify)
|
||||
{
|
||||
serial->rx_notify.notify(serial->rx_notify.dev);
|
||||
}
|
||||
else if (serial->parent.rx_indicate != RT_NULL)
|
||||
{
|
||||
rt_size_t rx_length;
|
||||
|
||||
@@ -1376,10 +1397,9 @@ void rt_hw_serial_isr(struct rt_serial_device *serial, int event)
|
||||
serial->parent.rx_indicate(&serial->parent, rx_length);
|
||||
}
|
||||
}
|
||||
if (serial->rx_notify.notify)
|
||||
{
|
||||
serial->rx_notify.notify(serial->rx_notify.dev);
|
||||
}
|
||||
#if defined(RT_USING_SMART) && defined(LWP_DEBUG)
|
||||
_early_input = 1;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
case RT_SERIAL_EVENT_TX_DONE:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,10 +0,0 @@
|
||||
from building import *
|
||||
|
||||
# The set of source files associated with this SConscript file.
|
||||
src = Glob('*.c')
|
||||
cwd = GetCurrentDir()
|
||||
CPPPATH = [cwd + "/include"]
|
||||
|
||||
group = DefineGroup('tty', src, depend = ['RT_USING_SMART', 'RT_USING_TTY'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021.12.07 linzhenxing first version
|
||||
*/
|
||||
#ifndef __CONSOLE_
|
||||
#define __CONSOLE_
|
||||
#include <rtthread.h>
|
||||
#include "tty.h"
|
||||
|
||||
struct tty_struct *console_tty_get(void);
|
||||
struct rt_device *console_get_iodev(void);
|
||||
struct rt_device *console_set_iodev(struct rt_device *iodev);
|
||||
rt_err_t console_register(const char *name, struct rt_device *iodev);
|
||||
#endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021.12.07 linzhenxing first version
|
||||
*/
|
||||
#ifndef __TTY_LDISC_
|
||||
#define __TTY_LDISC_
|
||||
#include <rtthread.h>
|
||||
#include <dfs.h>
|
||||
#include <dfs_fs.h>
|
||||
#include <tty.h>
|
||||
#if defined(RT_USING_POSIX_TERMIOS)
|
||||
#include <termios.h>
|
||||
#endif
|
||||
struct tty_struct;
|
||||
|
||||
struct tty_ldisc_ops
|
||||
{
|
||||
char *name;
|
||||
int num;
|
||||
|
||||
int (*open) (struct dfs_file *fd);
|
||||
int (*close) (struct tty_struct *tty);
|
||||
int (*ioctl) (struct dfs_file *fd, int cmd, void *args);
|
||||
int (*read) (struct dfs_file *fd, void *buf, size_t count);
|
||||
int (*write) (struct dfs_file *fd, const void *buf, size_t count);
|
||||
int (*flush) (struct dfs_file *fd);
|
||||
int (*lseek) (struct dfs_file *fd, off_t offset);
|
||||
int (*getdents) (struct dfs_file *fd, struct dirent *dirp, uint32_t count);
|
||||
|
||||
int (*poll) (struct dfs_file *fd, struct rt_pollreq *req);
|
||||
void (*set_termios) (struct tty_struct *tty, struct termios *old);
|
||||
int (*receive_buf) (struct tty_struct *tty,char *cp, int count);
|
||||
|
||||
int refcount;
|
||||
};
|
||||
|
||||
struct tty_ldisc
|
||||
{
|
||||
struct tty_ldisc_ops *ops;
|
||||
struct tty_struct *tty;
|
||||
};
|
||||
|
||||
#define TTY_LDISC_MAGIC 0x5403
|
||||
|
||||
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
|
||||
void tty_ldisc_kill(struct tty_struct *tty);
|
||||
void tty_ldisc_init(struct tty_struct *tty);
|
||||
void tty_ldisc_release(struct tty_struct *tty);
|
||||
void n_tty_init(void);
|
||||
|
||||
#endif // __TTY_LDISC_
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,122 +0,0 @@
|
||||
#include <stddef.h>
|
||||
#include <rtthread.h>
|
||||
#include <tty.h>
|
||||
#if defined(RT_USING_POSIX_DEVIO)
|
||||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
#define DBG_TAG "TTY_IOCTL"
|
||||
#ifdef RT_TTY_DEBUG
|
||||
#define DBG_LVL DBG_LOG
|
||||
#else
|
||||
#define DBG_LVL DBG_INFO
|
||||
#endif /* RT_TTY_DEBUG */
|
||||
#include <rtdbg.h>
|
||||
|
||||
/*
|
||||
* Internal flag options for termios setting behavior
|
||||
*/
|
||||
#define TERMIOS_FLUSH 1
|
||||
#define TERMIOS_WAIT 2
|
||||
#define TERMIOS_TERMIO 4
|
||||
#define TERMIOS_OLD 8
|
||||
|
||||
/**
|
||||
* set_termios - set termios values for a tty
|
||||
* @tty: terminal device
|
||||
* @arg: user data
|
||||
* @opt: option information
|
||||
*
|
||||
* Helper function to prepare termios data and run necessary other
|
||||
* functions before using tty_set_termios to do the actual changes.
|
||||
*
|
||||
* Locking:
|
||||
* Called functions take ldisc and termios_rwsem locks
|
||||
*/
|
||||
|
||||
static int set_termios(struct tty_struct *tty, void *arg, int opt)
|
||||
{
|
||||
struct termios old_termios;
|
||||
struct tty_ldisc *ld = RT_NULL;
|
||||
struct termios *new_termios = (struct termios *)arg;
|
||||
rt_base_t level = 0;
|
||||
int retval = tty_check_change(tty);
|
||||
|
||||
if (retval)
|
||||
{
|
||||
return retval;
|
||||
}
|
||||
|
||||
memcpy(&old_termios, &(tty->init_termios), sizeof(struct termios));
|
||||
level = rt_spin_lock_irqsave(&tty->spinlock);
|
||||
tty->init_termios = *new_termios;
|
||||
rt_spin_unlock_irqrestore(&tty->spinlock, level);
|
||||
ld = tty->ldisc;
|
||||
if (ld != NULL)
|
||||
{
|
||||
if (ld->ops->set_termios)
|
||||
{
|
||||
ld->ops->set_termios(tty, &old_termios);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int n_tty_ioctl_extend(struct tty_struct *tty, int cmd, void *args)
|
||||
{
|
||||
int ret = 0;
|
||||
void *p = (void *)args;
|
||||
struct tty_struct *real_tty = RT_NULL;
|
||||
|
||||
if (tty->type == TTY_DRIVER_TYPE_PTY && tty->subtype == PTY_TYPE_MASTER)
|
||||
{
|
||||
real_tty = tty->other_struct;
|
||||
}
|
||||
else
|
||||
{
|
||||
real_tty = tty;
|
||||
}
|
||||
|
||||
switch(cmd)
|
||||
{
|
||||
case TCGETS:
|
||||
case TCGETA:
|
||||
{
|
||||
struct termios *tio = (struct termios *)p;
|
||||
if (tio == RT_NULL)
|
||||
{
|
||||
return -RT_EINVAL;
|
||||
}
|
||||
|
||||
memcpy(tio, &real_tty->init_termios, sizeof(real_tty->init_termios));
|
||||
return ret;
|
||||
}
|
||||
case TCSETSF:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_OLD);
|
||||
}
|
||||
case TCSETSW:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_OLD);
|
||||
}
|
||||
case TCSETS:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_OLD);
|
||||
}
|
||||
case TCSETAF:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_FLUSH | TERMIOS_WAIT | TERMIOS_TERMIO);
|
||||
}
|
||||
case TCSETAW:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_WAIT | TERMIOS_TERMIO);
|
||||
}
|
||||
case TCSETA:
|
||||
{
|
||||
return set_termios(real_tty, p, TERMIOS_TERMIO);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
@@ -1,178 +0,0 @@
|
||||
#include <tty.h>
|
||||
#include <tty_ldisc.h>
|
||||
|
||||
#define DBG_TAG "TTY_LDISC"
|
||||
#ifdef RT_TTY_DEBUG
|
||||
#define DBG_LVL DBG_LOG
|
||||
#else
|
||||
#define DBG_LVL DBG_INFO
|
||||
#endif /* RT_TTY_DEBUG */
|
||||
#include <rtdbg.h>
|
||||
|
||||
extern struct tty_ldisc_ops n_tty_ops;
|
||||
static struct tty_ldisc_ops *tty_ldiscs[NR_LDISCS] = {
|
||||
&n_tty_ops, /* N_TTY = 0 */
|
||||
};
|
||||
|
||||
static struct rt_spinlock _spinlock = RT_SPINLOCK_INIT;
|
||||
|
||||
static struct tty_ldisc_ops *get_ldops(int disc)
|
||||
{
|
||||
struct tty_ldisc_ops *ldops = RT_NULL;
|
||||
rt_base_t level = 0;
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
ldops = tty_ldiscs[disc];
|
||||
if (ldops)
|
||||
{
|
||||
ldops->refcount++;
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
return ldops;
|
||||
}
|
||||
|
||||
static void put_ldops(struct tty_ldisc_ops *ldops)
|
||||
{
|
||||
rt_base_t level = 0;
|
||||
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
ldops->refcount--;
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
}
|
||||
|
||||
static struct tty_ldisc *tty_ldisc_get(struct tty_struct *tty, int disc)
|
||||
{
|
||||
struct tty_ldisc *ld = RT_NULL;
|
||||
struct tty_ldisc_ops *ldops = RT_NULL;
|
||||
|
||||
if (disc < N_TTY || disc >= NR_LDISCS)
|
||||
{
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
ldops = get_ldops(disc);
|
||||
if (ldops == RT_NULL)
|
||||
{
|
||||
LOG_E("tty ldisc get error\n");
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
ld = rt_malloc(sizeof(struct tty_ldisc));
|
||||
if (ld == RT_NULL)
|
||||
{
|
||||
ldops->refcount--;
|
||||
return RT_NULL;
|
||||
}
|
||||
|
||||
ld->ops = ldops;
|
||||
ld->tty = tty;
|
||||
|
||||
return ld;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_ldisc_put - release the ldisc
|
||||
*
|
||||
* Complement of tty_ldisc_get().
|
||||
*/
|
||||
static void tty_ldisc_put(struct tty_ldisc *ld)
|
||||
{
|
||||
if (ld)
|
||||
{
|
||||
put_ldops(ld->ops);
|
||||
rt_free(ld);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_ldisc_close - close a line discipline
|
||||
* @tty: tty we are opening the ldisc on
|
||||
* @ld: discipline to close
|
||||
*
|
||||
* A helper close method. Also a convenient debugging and check
|
||||
* point.
|
||||
*/
|
||||
static void tty_ldisc_close(struct tty_struct *tty, struct tty_ldisc *ld)
|
||||
{
|
||||
if (ld && ld->ops->close)
|
||||
{
|
||||
ld->ops->close(tty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_ldisc_kill - teardown ldisc
|
||||
* @tty: tty being released
|
||||
*
|
||||
* Perform final close of the ldisc and reset tty->ldisc
|
||||
*/
|
||||
void tty_ldisc_kill(struct tty_struct *tty)
|
||||
{
|
||||
if (tty && tty->ldisc)
|
||||
{
|
||||
/*
|
||||
* Now kill off the ldisc
|
||||
*/
|
||||
tty_ldisc_close(tty, tty->ldisc);
|
||||
tty_ldisc_put(tty->ldisc);
|
||||
/* Force an oops if we mess this up */
|
||||
tty->ldisc = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc)
|
||||
{
|
||||
int ret = 0;
|
||||
rt_base_t level = 0;
|
||||
|
||||
if (disc < N_TTY || disc >= NR_LDISCS)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
tty_ldiscs[disc] = new_ldisc;
|
||||
new_ldisc->num = disc;
|
||||
new_ldisc->refcount = 0;
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_ldisc_release - release line discipline
|
||||
* @tty: tty being shut down (or one end of pty pair)
|
||||
*
|
||||
* Called during the final close of a tty or a pty pair in order to shut
|
||||
* down the line discpline layer. On exit, each tty's ldisc is NULL.
|
||||
*/
|
||||
|
||||
void tty_ldisc_release(struct tty_struct *tty)
|
||||
{
|
||||
struct tty_struct *o_tty = tty->other_struct;
|
||||
|
||||
/*
|
||||
* Shutdown this line discipline. As this is the final close,
|
||||
* it does not race with the set_ldisc code path.
|
||||
*/
|
||||
tty_ldisc_kill(tty);
|
||||
if (o_tty)
|
||||
{
|
||||
tty_ldisc_kill(o_tty);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* tty_ldisc_init - ldisc setup for new tty
|
||||
* @tty: tty being allocated
|
||||
*
|
||||
* Set up the line discipline objects for a newly allocated tty. Note that
|
||||
* the tty structure is not completely set up when this call is made.
|
||||
*/
|
||||
|
||||
void tty_ldisc_init(struct tty_struct *tty)
|
||||
{
|
||||
if (tty)
|
||||
{
|
||||
tty->ldisc = tty_ldisc_get(tty, N_TTY);
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,10 @@
|
||||
#include <dfs_mnt.h>
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_SMART
|
||||
#include "lwp.h"
|
||||
#endif /* RT_USING_SMART */
|
||||
|
||||
static int msh_readline(int fd, char *line_buf, int size)
|
||||
{
|
||||
char ch;
|
||||
@@ -159,7 +163,11 @@ static int cmd_ls(int argc, char **argv)
|
||||
if (argc == 1)
|
||||
{
|
||||
#ifdef DFS_USING_WORKDIR
|
||||
#ifdef RT_USING_SMART
|
||||
ls(lwp_getcwd());
|
||||
#else
|
||||
ls(working_directory);
|
||||
#endif
|
||||
#else
|
||||
ls("/");
|
||||
#endif
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
* 2023-08-12 Meco Man re-implement RT-Thread lightweight timezone API
|
||||
* 2023-09-15 xqyjlj perf rt_hw_interrupt_disable/enable
|
||||
* 2023-10-23 Shell add lock for _g_timerid
|
||||
* 2023-11-16 Shell Fixup of nanosleep if previous call was interrupted
|
||||
*/
|
||||
|
||||
#include "sys/time.h"
|
||||
@@ -544,20 +545,24 @@ int nanosleep(const struct timespec *rqtp, struct timespec *rmtp)
|
||||
unsigned long ns = rqtp->tv_sec * NANOSECOND_PER_SECOND + rqtp->tv_nsec;
|
||||
rt_ktime_boottime_get_ns(&old_ts);
|
||||
rt_ktime_hrtimer_ndelay(ns);
|
||||
if (rt_get_errno() == -RT_EINTR)
|
||||
if (rt_get_errno() == RT_EINTR)
|
||||
{
|
||||
if (rmtp)
|
||||
{
|
||||
rt_base_t rsec, rnsec;
|
||||
rt_ktime_boottime_get_ns(&new_ts);
|
||||
|
||||
rmtp->tv_sec = 0;
|
||||
rmtp->tv_nsec =
|
||||
(old_ts.tv_nsec + ns) - ((new_ts.tv_sec - old_ts.tv_sec) * NANOSECOND_PER_SECOND + new_ts.tv_nsec);
|
||||
|
||||
if (rmtp->tv_nsec > NANOSECOND_PER_SECOND)
|
||||
rsec = old_ts.tv_sec + rqtp->tv_sec - new_ts.tv_sec;
|
||||
rnsec = old_ts.tv_nsec + rqtp->tv_nsec - new_ts.tv_nsec;
|
||||
if (rnsec < 0)
|
||||
{
|
||||
rmtp->tv_nsec %= NANOSECOND_PER_SECOND;
|
||||
rmtp->tv_sec += rmtp->tv_nsec / NANOSECOND_PER_SECOND;
|
||||
rmtp->tv_sec = rsec - 1;
|
||||
rmtp->tv_nsec = NANOSECOND_PER_SECOND + rnsec;
|
||||
}
|
||||
else
|
||||
{
|
||||
rmtp->tv_sec = rsec;
|
||||
rmtp->tv_nsec = rnsec;
|
||||
}
|
||||
}
|
||||
rt_set_errno(EINTR);
|
||||
|
||||
@@ -32,9 +32,13 @@ extern "C" {
|
||||
|
||||
#define DT_UNKNOWN 0x00
|
||||
#define DT_FIFO 0x01
|
||||
#define DT_SYMLINK 0x03
|
||||
#define DT_CHR 0x02
|
||||
#define DT_DIR 0x04
|
||||
#define DT_BLK 0x06
|
||||
#define DT_REG 0x08
|
||||
#define DT_LNK 0x0a
|
||||
#define DT_SOCK 0x0c
|
||||
#define DT_SYMLINK DT_LNK
|
||||
|
||||
#ifndef HAVE_DIR_STRUCTURE
|
||||
#define HAVE_DIR_STRUCTURE
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef RT_USING_MUSLLIBC
|
||||
#include_next <sys/ioctl.h>
|
||||
#else
|
||||
|
||||
struct winsize
|
||||
{
|
||||
unsigned short ws_row;
|
||||
@@ -23,9 +27,6 @@ struct winsize
|
||||
unsigned short ws_ypixel;
|
||||
};
|
||||
|
||||
#ifdef RT_USING_MUSLLIBC
|
||||
#include <bits/ioctl.h>
|
||||
#else
|
||||
/*
|
||||
* Direction bits, which any architecture can choose to override
|
||||
* before including this file.
|
||||
|
||||
@@ -19,6 +19,8 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _POSIX_VDISABLE 0
|
||||
|
||||
#define STDIN_FILENO 0 /* standard input file descriptor */
|
||||
#define STDOUT_FILENO 1 /* standard output file descriptor */
|
||||
#define STDERR_FILENO 2 /* standard error file descriptor */
|
||||
|
||||
@@ -13,12 +13,37 @@
|
||||
|
||||
#include_next <fcntl.h>
|
||||
|
||||
#ifndef O_DIRECTORY
|
||||
#define O_DIRECTORY 0x200000
|
||||
#endif
|
||||
#define O_CREAT 0100
|
||||
#define O_EXCL 0200
|
||||
#define O_NOCTTY 0400
|
||||
#define O_TRUNC 01000
|
||||
#define O_APPEND 02000
|
||||
#define O_NONBLOCK 04000
|
||||
#define O_DSYNC 010000
|
||||
#define O_SYNC 04010000
|
||||
#define O_RSYNC 04010000
|
||||
#define O_DIRECTORY 040000
|
||||
#define O_NOFOLLOW 0100000
|
||||
#define O_CLOEXEC 02000000
|
||||
|
||||
#define O_ASYNC 020000
|
||||
#define O_DIRECT 0200000
|
||||
#define O_LARGEFILE 0400000
|
||||
#define O_NOATIME 01000000
|
||||
#define O_PATH 010000000
|
||||
#define O_TMPFILE 020040000
|
||||
#define O_NDELAY O_NONBLOCK
|
||||
|
||||
#ifndef O_BINARY
|
||||
#define O_BINARY 0x10000
|
||||
#define O_BINARY 00
|
||||
#endif
|
||||
|
||||
#ifndef O_SEARCH
|
||||
#define O_SEARCH O_PATH
|
||||
#endif /* O_SEARCH */
|
||||
|
||||
#ifndef O_EXEC
|
||||
#define O_EXEC O_PATH
|
||||
#endif /* O_EXEC */
|
||||
|
||||
#endif
|
||||
|
||||
@@ -27,7 +27,7 @@ if RT_USING_POSIX_FS
|
||||
select RT_USING_POSIX_POLL
|
||||
default y if RT_USING_SMART
|
||||
default n
|
||||
|
||||
|
||||
config RT_USING_POSIX_EVENTFD
|
||||
bool "Enable I/O event eventfd <sys/eventfd.h>"
|
||||
select RT_USING_POSIX_POLL
|
||||
|
||||
@@ -4,9 +4,14 @@
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-07-29 zmq810150896 first version
|
||||
* 2024/03/26 TroyMitchelle Add comments for all functions, members within structure members and fix incorrect naming of triggered
|
||||
* Date Author Notes
|
||||
* 2023-07-29 zmq810150896 first version
|
||||
* 2024/03/26 TroyMitchelle Add comments for all functions, members within structure members and fix incorrect naming of triggered
|
||||
* 2023-12-14 Shell When poll goes to sleep before the waitqueue has added a
|
||||
* record and finished enumerating all the fd's, it may be
|
||||
* incorrectly woken up. This is basically because the poll
|
||||
* mechanism wakeup algorithm does not correctly distinguish
|
||||
* the current wait state.
|
||||
*/
|
||||
|
||||
#include <rtthread.h>
|
||||
@@ -27,6 +32,12 @@
|
||||
|
||||
struct rt_eventpoll;
|
||||
|
||||
enum rt_epoll_status {
|
||||
RT_EPOLL_STAT_INIT,
|
||||
RT_EPOLL_STAT_TRIG,
|
||||
RT_EPOLL_STAT_WAITING,
|
||||
};
|
||||
|
||||
/* Monitor queue */
|
||||
struct rt_fd_list
|
||||
{
|
||||
@@ -44,15 +55,15 @@ struct rt_fd_list
|
||||
|
||||
struct rt_eventpoll
|
||||
{
|
||||
rt_uint32_t triggered; /**< Indicates if the wait thread is triggered */
|
||||
rt_wqueue_t epoll_read; /**< Epoll read queue */
|
||||
rt_thread_t polling_thread; /**< Polling thread */
|
||||
struct rt_mutex lock; /**< Mutex lock */
|
||||
struct rt_fd_list *fdlist; /**< Monitor list */
|
||||
int eventpoll_num; /**< Number of ready lists */
|
||||
rt_pollreq_t req; /**< Poll request structure */
|
||||
struct rt_spinlock spinlock;/**< Spin lock */
|
||||
rt_slist_t rdl_head; /**< Ready list head */
|
||||
rt_wqueue_t epoll_read; /**< Epoll read queue */
|
||||
rt_thread_t polling_thread; /**< Polling thread */
|
||||
struct rt_mutex lock; /**< Mutex lock */
|
||||
struct rt_fd_list *fdlist; /**< Monitor list */
|
||||
int eventpoll_num; /**< Number of ready lists */
|
||||
rt_pollreq_t req; /**< Poll request structure */
|
||||
struct rt_spinlock spinlock; /**< Spin lock */
|
||||
rt_slist_t rdl_head; /**< Ready list head */
|
||||
enum rt_epoll_status status; /* the waited thread whether triggered */
|
||||
};
|
||||
|
||||
static int epoll_close(struct dfs_file *file);
|
||||
@@ -85,8 +96,7 @@ static int epoll_close_fdlist(struct rt_fd_list *fdlist)
|
||||
while (list->next != RT_NULL)
|
||||
{
|
||||
fre_node = list->next;
|
||||
if (fre_node->wqn.wqueue)
|
||||
rt_wqueue_remove(&fre_node->wqn);
|
||||
rt_wqueue_remove(&fre_node->wqn);
|
||||
|
||||
list->next = fre_node->next;
|
||||
rt_free(fre_node);
|
||||
@@ -188,13 +198,14 @@ static int epoll_wqueue_callback(struct rt_wqueue_node *wait, void *key)
|
||||
struct rt_fd_list *fdlist;
|
||||
struct rt_eventpoll *ep;
|
||||
rt_base_t level;
|
||||
int is_waiting = 0;
|
||||
|
||||
if (key && !((rt_ubase_t)key & wait->key))
|
||||
return -1;
|
||||
|
||||
fdlist = rt_container_of(wait, struct rt_fd_list, wqn);
|
||||
|
||||
ep = fdlist->ep;
|
||||
|
||||
if (ep)
|
||||
{
|
||||
level = rt_spin_lock_irqsave(&ep->spinlock);
|
||||
@@ -203,16 +214,21 @@ static int epoll_wqueue_callback(struct rt_wqueue_node *wait, void *key)
|
||||
rt_slist_append(&ep->rdl_head, &fdlist->rdl_node);
|
||||
fdlist->exclusive = 0;
|
||||
fdlist->is_rdl_node = RT_TRUE;
|
||||
ep->triggered = 1;
|
||||
ep->eventpoll_num++;
|
||||
is_waiting = (ep->status == RT_EPOLL_STAT_WAITING);
|
||||
ep->status = RT_EPOLL_STAT_TRIG;
|
||||
rt_wqueue_wakeup(&ep->epoll_read, (void *)POLLIN);
|
||||
}
|
||||
rt_spin_unlock_irqrestore(&ep->spinlock, level);
|
||||
}
|
||||
|
||||
return __wqueue_default_wake(wait, key);
|
||||
}
|
||||
if (is_waiting)
|
||||
{
|
||||
return __wqueue_default_wake(wait, key);
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Adds a callback function to the wait queue associated with epoll.
|
||||
@@ -265,8 +281,8 @@ static void epoll_ctl_install(struct rt_fd_list *fdlist, struct rt_eventpoll *ep
|
||||
rt_slist_append(&ep->rdl_head, &fdlist->rdl_node);
|
||||
fdlist->exclusive = 0;
|
||||
fdlist->is_rdl_node = RT_TRUE;
|
||||
ep->triggered = 1;
|
||||
ep->eventpoll_num++;
|
||||
ep->status = RT_EPOLL_STAT_TRIG;
|
||||
ep->eventpoll_num ++;
|
||||
rt_spin_unlock_irqrestore(&ep->spinlock, level);
|
||||
rt_mutex_release(&ep->lock);
|
||||
}
|
||||
@@ -282,7 +298,7 @@ static void epoll_ctl_install(struct rt_fd_list *fdlist, struct rt_eventpoll *ep
|
||||
*/
|
||||
static void epoll_member_init(struct rt_eventpoll *ep)
|
||||
{
|
||||
ep->triggered = 0;
|
||||
ep->status = RT_EPOLL_STAT_INIT;
|
||||
ep->eventpoll_num = 0;
|
||||
ep->polling_thread = rt_thread_self();
|
||||
ep->fdlist = RT_NULL;
|
||||
@@ -678,7 +694,7 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec)
|
||||
|
||||
level = rt_spin_lock_irqsave(&ep->spinlock);
|
||||
|
||||
if (timeout != 0 && !ep->triggered)
|
||||
if (timeout != 0 && ep->status != RT_EPOLL_STAT_TRIG)
|
||||
{
|
||||
if (rt_thread_suspend_with_flag(thread, RT_KILLABLE) == RT_EOK)
|
||||
{
|
||||
@@ -690,15 +706,19 @@ static int epoll_wait_timeout(struct rt_eventpoll *ep, int msec)
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
}
|
||||
|
||||
ep->status = RT_EPOLL_STAT_WAITING;
|
||||
|
||||
rt_spin_unlock_irqrestore(&ep->spinlock, level);
|
||||
|
||||
rt_schedule();
|
||||
|
||||
level = rt_spin_lock_irqsave(&ep->spinlock);
|
||||
if (ep->status == RT_EPOLL_STAT_WAITING)
|
||||
ep->status = RT_EPOLL_STAT_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
ret = !ep->triggered;
|
||||
ret = !(ep->status == RT_EPOLL_STAT_TRIG);
|
||||
rt_spin_unlock_irqrestore(&ep->spinlock, level);
|
||||
|
||||
return ret;
|
||||
@@ -867,7 +887,7 @@ static int epoll_do(struct rt_eventpoll *ep, struct epoll_event *events, int max
|
||||
if (event_num || istimeout)
|
||||
{
|
||||
level = rt_spin_lock_irqsave(&ep->spinlock);
|
||||
ep->triggered = 0;
|
||||
ep->status = RT_EPOLL_STAT_INIT;
|
||||
rt_spin_unlock_irqrestore(&ep->spinlock, level);
|
||||
if ((timeout >= 0) || (event_num > 0))
|
||||
break;
|
||||
|
||||
@@ -7,6 +7,12 @@
|
||||
* Date Author Notes
|
||||
* 2016-12-28 Bernard first version
|
||||
* 2018-03-09 Bernard Add protection for pt->triggered.
|
||||
* 2023-12-04 Shell Fix return code and error verification
|
||||
* 2023-12-14 Shell When poll goes to sleep before the waitqueue has added a
|
||||
* record and finished enumerating all the fd's, it may be
|
||||
* incorrectly woken up. This is basically because the poll
|
||||
* mechanism wakeup algorithm does not correctly distinguish
|
||||
* the current wait state.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
@@ -16,11 +22,16 @@
|
||||
#include "poll.h"
|
||||
|
||||
struct rt_poll_node;
|
||||
enum rt_poll_status {
|
||||
RT_POLL_STAT_INIT,
|
||||
RT_POLL_STAT_TRIG,
|
||||
RT_POLL_STAT_WAITING,
|
||||
};
|
||||
|
||||
struct rt_poll_table
|
||||
{
|
||||
rt_pollreq_t req;
|
||||
rt_uint32_t triggered; /* the waited thread whether triggered */
|
||||
enum rt_poll_status status; /* the waited thread whether triggered */
|
||||
rt_thread_t polling_thread;
|
||||
struct rt_poll_node *nodes;
|
||||
};
|
||||
@@ -36,15 +47,25 @@ static RT_DEFINE_SPINLOCK(_spinlock);
|
||||
|
||||
static int __wqueue_pollwake(struct rt_wqueue_node *wait, void *key)
|
||||
{
|
||||
rt_ubase_t level;
|
||||
struct rt_poll_node *pn;
|
||||
int is_waiting;
|
||||
|
||||
if (key && !((rt_ubase_t)key & wait->key))
|
||||
return -1;
|
||||
|
||||
pn = rt_container_of(wait, struct rt_poll_node, wqn);
|
||||
pn->pt->triggered = 1;
|
||||
|
||||
return __wqueue_default_wake(wait, key);
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
is_waiting = (pn->pt->status == RT_POLL_STAT_WAITING);
|
||||
|
||||
pn->pt->status = RT_POLL_STAT_TRIG;
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
|
||||
if (is_waiting)
|
||||
return __wqueue_default_wake(wait, key);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
|
||||
@@ -71,7 +92,7 @@ static void _poll_add(rt_wqueue_t *wq, rt_pollreq_t *req)
|
||||
static void poll_table_init(struct rt_poll_table *pt)
|
||||
{
|
||||
pt->req._proc = _poll_add;
|
||||
pt->triggered = 0;
|
||||
pt->status = RT_POLL_STAT_INIT;
|
||||
pt->nodes = RT_NULL;
|
||||
pt->polling_thread = rt_thread_self();
|
||||
}
|
||||
@@ -89,7 +110,7 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
|
||||
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
|
||||
if (timeout != 0 && !pt->triggered)
|
||||
if (timeout != 0 && pt->status != RT_POLL_STAT_TRIG)
|
||||
{
|
||||
if (rt_thread_suspend_with_flag(thread, RT_INTERRUPTIBLE) == RT_EOK)
|
||||
{
|
||||
@@ -99,17 +120,31 @@ static int poll_wait_timeout(struct rt_poll_table *pt, int msec)
|
||||
RT_TIMER_CTRL_SET_TIME,
|
||||
&timeout);
|
||||
rt_timer_start(&(thread->thread_timer));
|
||||
rt_set_errno(RT_ETIMEOUT);
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
rt_set_errno(0);
|
||||
}
|
||||
pt->status = RT_POLL_STAT_WAITING;
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
|
||||
rt_schedule();
|
||||
|
||||
level = rt_spin_lock_irqsave(&_spinlock);
|
||||
if (pt->status == RT_POLL_STAT_WAITING)
|
||||
pt->status = RT_POLL_STAT_INIT;
|
||||
}
|
||||
}
|
||||
|
||||
ret = !pt->triggered;
|
||||
ret = rt_get_errno();
|
||||
if (ret == RT_EINTR)
|
||||
ret = -RT_EINTR;
|
||||
else if (pt->status == RT_POLL_STAT_TRIG)
|
||||
ret = RT_EOK;
|
||||
else
|
||||
ret = -RT_ETIMEOUT;
|
||||
|
||||
rt_spin_unlock_irqrestore(&_spinlock, level);
|
||||
|
||||
return ret;
|
||||
@@ -170,7 +205,7 @@ static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, in
|
||||
{
|
||||
pf = fds;
|
||||
num = 0;
|
||||
pt->triggered = 0;
|
||||
pt->status = RT_POLL_STAT_INIT;
|
||||
|
||||
for (n = 0; n < nfds; n ++)
|
||||
{
|
||||
@@ -194,8 +229,13 @@ static int poll_do(struct pollfd *fds, nfds_t nfds, struct rt_poll_table *pt, in
|
||||
if (num || istimeout)
|
||||
break;
|
||||
|
||||
if (poll_wait_timeout(pt, msec))
|
||||
ret = poll_wait_timeout(pt, msec);
|
||||
if (ret == -RT_EINTR)
|
||||
return -EINTR;
|
||||
else if (ret == -RT_ETIMEOUT)
|
||||
istimeout = 1;
|
||||
else
|
||||
istimeout = 0;
|
||||
}
|
||||
|
||||
return num;
|
||||
|
||||
@@ -36,6 +36,20 @@ struct termios {
|
||||
speed_t __c_ospeed;
|
||||
};
|
||||
|
||||
#ifndef NCC
|
||||
#define NCC 8
|
||||
|
||||
struct termio
|
||||
{
|
||||
unsigned short c_iflag; /* input mode flags */
|
||||
unsigned short c_oflag; /* output mode flags */
|
||||
unsigned short c_cflag; /* control mode flags */
|
||||
unsigned short c_lflag; /* local mode flags */
|
||||
unsigned char c_line; /* line discipline */
|
||||
unsigned char c_cc[NCC]; /* control characters */
|
||||
};
|
||||
#endif
|
||||
|
||||
/* c_cc characters */
|
||||
#define VINTR 0
|
||||
#define VQUIT 1
|
||||
|
||||
+2
-19
@@ -8,7 +8,7 @@ menuconfig RT_USING_LWP
|
||||
if RT_USING_LWP
|
||||
config LWP_DEBUG
|
||||
bool "Enable debugging features of LwP"
|
||||
default n
|
||||
default y
|
||||
|
||||
config RT_LWP_MAX_NR
|
||||
int "The max number of light-weight process"
|
||||
@@ -51,24 +51,6 @@ if RT_USING_LWP
|
||||
default y
|
||||
endif
|
||||
|
||||
config LWP_UNIX98_PTY
|
||||
bool "The unix98 PTY support"
|
||||
default n
|
||||
|
||||
if LWP_UNIX98_PTY
|
||||
config LWP_PTY_INPUT_BFSZ
|
||||
int "The unix98 PTY input buffer size"
|
||||
default 1024
|
||||
|
||||
config LWP_PTY_PTS_SIZE
|
||||
int "The unix98 PTY device max num"
|
||||
default 3
|
||||
|
||||
config LWP_PTY_USING_DEBUG
|
||||
bool "The unix98 PTY debug output"
|
||||
default n
|
||||
endif
|
||||
|
||||
menuconfig RT_USING_LDSO
|
||||
bool "LDSO: dynamic load shared objects"
|
||||
depends on RT_USING_DFS_V2
|
||||
@@ -85,5 +67,6 @@ if RT_USING_LWP
|
||||
default n
|
||||
endif
|
||||
|
||||
source "$RTT_DIR/components/lwp/terminal/Kconfig"
|
||||
endif
|
||||
|
||||
|
||||
@@ -22,11 +22,6 @@ if arch == 'risc-v':
|
||||
if cpu in rv64:
|
||||
cpu = 'rv64'
|
||||
|
||||
if GetDepend('LWP_UNIX98_PTY'):
|
||||
# print("LWP_UNIX98_PTY")
|
||||
src += Glob('unix98pty/*.c')
|
||||
CPPPATH += ['unix98pty/']
|
||||
|
||||
if platform in platform_file.keys(): # support platforms
|
||||
if arch in support_arch.keys() and cpu in support_arch[arch]:
|
||||
asm_path = 'arch/' + arch + '/' + cpu + '/*_' + platform_file[platform]
|
||||
@@ -40,6 +35,12 @@ if platform in platform_file.keys(): # support platforms
|
||||
CPPPATH = [cwd]
|
||||
CPPPATH += [cwd + '/arch/' + arch + '/' + cpu]
|
||||
|
||||
# Terminal I/O Subsystem
|
||||
termios_path = ['./terminal/', './terminal/freebsd/']
|
||||
for item in termios_path:
|
||||
src += Glob(item + '*.c')
|
||||
CPPPATH += ['./terminal/']
|
||||
|
||||
group = DefineGroup('lwP', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH)
|
||||
|
||||
Return('group')
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
* 2021-05-18 Jesven first version
|
||||
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||
* 2023-10-16 Shell Support a new backtrace framework
|
||||
* 2023-08-03 Shell Support of syscall restart (SA_RESTART)
|
||||
*/
|
||||
|
||||
#include <armv8.h>
|
||||
@@ -123,6 +124,7 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack,
|
||||
|
||||
#define ALGIN_BYTES (16)
|
||||
|
||||
/* the layout is part of ABI, dont change it */
|
||||
struct signal_ucontext
|
||||
{
|
||||
rt_int64_t sigreturn;
|
||||
@@ -130,11 +132,62 @@ struct signal_ucontext
|
||||
|
||||
siginfo_t si;
|
||||
|
||||
rt_align(16)
|
||||
rt_align(ALGIN_BYTES)
|
||||
struct rt_hw_exp_stack frame;
|
||||
};
|
||||
|
||||
void *arch_signal_ucontext_restore(rt_base_t user_sp)
|
||||
RT_STATIC_ASSERT(abi_offset_compatible, offsetof(struct signal_ucontext, si) == UCTX_ABI_OFFSET_TO_SI);
|
||||
|
||||
void *arch_signal_ucontext_get_frame(struct signal_ucontext *uctx)
|
||||
{
|
||||
return &uctx->frame;
|
||||
}
|
||||
|
||||
/* internal used only */
|
||||
void arch_syscall_prepare_signal(rt_base_t rc, struct rt_hw_exp_stack *exp_frame)
|
||||
{
|
||||
long x0 = exp_frame->x0;
|
||||
exp_frame->x0 = rc;
|
||||
exp_frame->x7 = x0;
|
||||
return ;
|
||||
}
|
||||
|
||||
void arch_syscall_restart(void *sp, void *ksp);
|
||||
|
||||
void arch_syscall_set_errno(void *eframe, int expected, int code)
|
||||
{
|
||||
struct rt_hw_exp_stack *exp_frame = eframe;
|
||||
if (exp_frame->x0 == -expected)
|
||||
exp_frame->x0 = -code;
|
||||
return ;
|
||||
}
|
||||
|
||||
void arch_signal_check_erestart(void *eframe, void *ksp)
|
||||
{
|
||||
struct rt_hw_exp_stack *exp_frame = eframe;
|
||||
long rc = exp_frame->x0;
|
||||
long sys_id = exp_frame->x8;
|
||||
(void)sys_id;
|
||||
|
||||
if (rc == -ERESTART)
|
||||
{
|
||||
LOG_D("%s(rc=%ld,sys_id=%ld,pid=%d)", __func__, rc, sys_id, lwp_self()->pid);
|
||||
LOG_D("%s: restart rc = %ld", lwp_get_syscall_name(sys_id), rc);
|
||||
exp_frame->x0 = exp_frame->x7;
|
||||
arch_syscall_restart(eframe, ksp);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
static void arch_signal_post_action(struct signal_ucontext *new_sp, rt_base_t kernel_sp)
|
||||
{
|
||||
arch_signal_check_erestart(&new_sp->frame, (void *)kernel_sp);
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp)
|
||||
{
|
||||
struct signal_ucontext *new_sp;
|
||||
new_sp = (void *)user_sp;
|
||||
@@ -142,6 +195,7 @@ void *arch_signal_ucontext_restore(rt_base_t user_sp)
|
||||
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||
{
|
||||
lwp_thread_signal_mask(rt_thread_self(), LWP_SIG_MASK_CMD_SET_MASK, &new_sp->save_sigmask, RT_NULL);
|
||||
arch_signal_post_action(new_sp, kernel_sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -157,7 +211,7 @@ void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo,
|
||||
lwp_sigset_t *save_sig_mask)
|
||||
{
|
||||
struct signal_ucontext *new_sp;
|
||||
new_sp = (void *)(user_sp - sizeof(struct signal_ucontext));
|
||||
new_sp = (void *)((user_sp - sizeof(struct signal_ucontext)) & ~0xf);
|
||||
|
||||
if (lwp_user_accessable(new_sp, sizeof(*new_sp)))
|
||||
{
|
||||
|
||||
@@ -11,8 +11,7 @@
|
||||
#ifndef LWP_ARCH_H__
|
||||
#define LWP_ARCH_H__
|
||||
|
||||
#include <lwp.h>
|
||||
#include <lwp_arch_comm.h>
|
||||
#include <rtconfig.h>
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
|
||||
@@ -26,6 +25,13 @@
|
||||
#define USER_VADDR_START 0x00200000UL
|
||||
#define USER_LOAD_VADDR USER_VADDR_START
|
||||
|
||||
#define UCTX_ABI_OFFSET_TO_SI 16
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
|
||||
#include <lwp.h>
|
||||
#include <lwp_arch_comm.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
@@ -34,7 +40,7 @@ unsigned long rt_hw_ffz(unsigned long x);
|
||||
|
||||
rt_inline void icache_invalid_all(void)
|
||||
{
|
||||
asm volatile ("ic ialluis\n\tisb sy":::"memory");
|
||||
__asm__ volatile ("ic ialluis\n\tisb sy":::"memory");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -57,11 +63,14 @@ void *arch_signal_ucontext_save(rt_base_t user_sp, siginfo_t *psiginfo,
|
||||
* @param user_sp sp of user
|
||||
* @return void*
|
||||
*/
|
||||
void *arch_signal_ucontext_restore(rt_base_t user_sp);
|
||||
void *arch_signal_ucontext_restore(rt_base_t user_sp, rt_base_t kernel_sp);
|
||||
void arch_syscall_restart(void *sp, void *ksp);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* __ASSEMBLY__ */
|
||||
|
||||
#endif
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
#endif /*LWP_ARCH_H__*/
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
* Date Author Notes
|
||||
* 2021-05-18 Jesven first version
|
||||
* 2023-07-16 Shell Move part of the codes to C from asm in signal handling
|
||||
* 2023-08-03 Shell Support of syscall restart (SA_RESTART)
|
||||
*/
|
||||
|
||||
#ifndef __ASSEMBLY__
|
||||
@@ -17,6 +18,7 @@
|
||||
#include "asm-generic.h"
|
||||
#include "asm-fpu.h"
|
||||
#include "armv8.h"
|
||||
#include "lwp_arch.h"
|
||||
|
||||
/*********************
|
||||
* SPSR BIT *
|
||||
@@ -155,6 +157,14 @@ START_POINT_END(SVC_Handler)
|
||||
|
||||
.global arch_syscall_exit
|
||||
arch_syscall_exit:
|
||||
|
||||
/**
|
||||
* @brief back up former x0 which is required to restart syscall, then setup
|
||||
* syscall return value in stack frame
|
||||
*/
|
||||
mov x1, sp
|
||||
bl arch_syscall_prepare_signal
|
||||
|
||||
msr daifset, #3
|
||||
|
||||
ldp x2, x3, [sp], #0x10 /* SPSR and ELR. */
|
||||
@@ -177,7 +187,10 @@ arch_syscall_exit:
|
||||
ldp x12, x13, [sp], #0x10
|
||||
ldp x10, x11, [sp], #0x10
|
||||
ldp x8, x9, [sp], #0x10
|
||||
add sp, sp, #0x40
|
||||
ldp x6, x7, [sp], #0x10
|
||||
ldp x4, x5, [sp], #0x10
|
||||
ldp x2, x3, [sp], #0x10
|
||||
ldp x0, x1, [sp], #0x10
|
||||
RESTORE_FPU sp
|
||||
|
||||
/* the sp is reset to the outer most level, irq and fiq are disabled */
|
||||
@@ -383,10 +396,53 @@ lwp_check_debug_quit:
|
||||
ldp x29, x30, [sp], #0x10
|
||||
ret
|
||||
|
||||
.global arch_syscall_restart
|
||||
arch_syscall_restart:
|
||||
msr daifset, 3
|
||||
|
||||
mov sp, x1
|
||||
/* drop exception frame in user stack */
|
||||
msr sp_el0, x0
|
||||
|
||||
/* restore previous exception frame */
|
||||
msr spsel, #0
|
||||
|
||||
ldp x2, x3, [sp], #0x10
|
||||
msr elr_el1, x2
|
||||
msr spsr_el1, x3
|
||||
|
||||
ldp x29, x30, [sp], #0x10
|
||||
|
||||
ldp x28, x29, [sp], #0x10
|
||||
msr fpcr, x28
|
||||
msr fpsr, x29
|
||||
|
||||
ldp x28, x29, [sp], #0x10
|
||||
ldp x26, x27, [sp], #0x10
|
||||
ldp x24, x25, [sp], #0x10
|
||||
ldp x22, x23, [sp], #0x10
|
||||
ldp x20, x21, [sp], #0x10
|
||||
ldp x18, x19, [sp], #0x10
|
||||
ldp x16, x17, [sp], #0x10
|
||||
ldp x14, x15, [sp], #0x10
|
||||
ldp x12, x13, [sp], #0x10
|
||||
ldp x10, x11, [sp], #0x10
|
||||
ldp x8, x9, [sp], #0x10
|
||||
ldp x6, x7, [sp], #0x10
|
||||
ldp x4, x5, [sp], #0x10
|
||||
ldp x2, x3, [sp], #0x10
|
||||
ldp x0, x1, [sp], #0x10
|
||||
RESTORE_FPU sp
|
||||
|
||||
msr spsel, #1
|
||||
|
||||
b vector_exception
|
||||
|
||||
arch_signal_quit:
|
||||
|
||||
/* drop current exception frame */
|
||||
add sp, sp, #CONTEXT_SIZE
|
||||
mov x1, sp
|
||||
mrs x0, sp_el0
|
||||
bl arch_signal_ucontext_restore
|
||||
add x0, x0, #-CONTEXT_SIZE
|
||||
@@ -456,6 +512,11 @@ arch_thread_signal_enter:
|
||||
|
||||
/* arch_signal_ucontext_save(user_sp, psiginfo, exp_frame, save_sig_mask); */
|
||||
bl arch_signal_ucontext_save
|
||||
mov x22, x0
|
||||
/* get and saved pointer to uframe */
|
||||
bl arch_signal_ucontext_get_frame
|
||||
mov x2, x0
|
||||
mov x0, x22
|
||||
|
||||
dc cvau, x0
|
||||
dsb sy
|
||||
@@ -483,12 +544,15 @@ arch_thread_signal_enter:
|
||||
/** set the return address to the sigreturn */
|
||||
mov x30, x0
|
||||
|
||||
cbnz x21, 1f
|
||||
mov x21, x30
|
||||
1:
|
||||
/** set the entry address of signal handler */
|
||||
msr elr_el1, x21
|
||||
|
||||
/* siginfo is above the return address */
|
||||
add x2, x30, 16
|
||||
add x1, x2, #CONTEXT_SIZE
|
||||
add x1, x30, UCTX_ABI_OFFSET_TO_SI
|
||||
/* uframe is saved in x2 */
|
||||
mov x0, x19
|
||||
|
||||
/**
|
||||
|
||||
@@ -192,6 +192,12 @@ void *arch_signal_ucontext_save(rt_base_t lr, siginfo_t *psiginfo,
|
||||
return new_sp;
|
||||
}
|
||||
|
||||
void arch_syscall_set_errno(void *eframe, int expected, int code)
|
||||
{
|
||||
/* NO support */
|
||||
return ;
|
||||
}
|
||||
|
||||
#ifdef LWP_ENABLE_ASID
|
||||
#define MAX_ASID_BITS 8
|
||||
#define MAX_ASID (1 << MAX_ASID_BITS)
|
||||
|
||||
@@ -35,7 +35,7 @@ rt_inline unsigned long rt_hw_ffz(unsigned long x)
|
||||
|
||||
rt_inline void icache_invalid_all(void)
|
||||
{
|
||||
asm volatile ("mcr p15, 0, r0, c7, c5, 0\ndsb\nisb":::"memory");//iciallu
|
||||
__asm__ volatile ("mcr p15, 0, r0, c7, c5, 0\ndsb\nisb":::"memory");//iciallu
|
||||
}
|
||||
|
||||
unsigned int arch_get_asid(struct rt_lwp *lwp);
|
||||
|
||||
@@ -242,6 +242,7 @@ int arch_set_thread_context(void (*exit)(void), void *new_thread_stack,
|
||||
* | |
|
||||
* +------------------------+ --> thread sp
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define ALGIN_BYTES (16)
|
||||
@@ -317,6 +318,12 @@ void *arch_signal_ucontext_save(int signo, siginfo_t *psiginfo,
|
||||
return new_sp;
|
||||
}
|
||||
|
||||
void arch_syscall_set_errno(void *eframe, int expected, int code)
|
||||
{
|
||||
/* NO support */
|
||||
return ;
|
||||
}
|
||||
|
||||
/**
|
||||
* void lwp_exec_user(void *args, void *kernel_stack, void *user_entry)
|
||||
*/
|
||||
|
||||
@@ -28,9 +28,9 @@
|
||||
|
||||
#define FUTEX_CLOCK_REALTIME 256
|
||||
|
||||
#define FUTEX_WAITERS 0x80000000
|
||||
#define FUTEX_OWNER_DIED 0x40000000
|
||||
#define FUTEX_TID_MASK 0x3fffffff
|
||||
#define FUTEX_WAITERS 0x80000000
|
||||
#define FUTEX_OWNER_DIED 0x40000000
|
||||
#define FUTEX_TID_MASK 0x3fffffff
|
||||
|
||||
struct robust_list
|
||||
{
|
||||
|
||||
+170
-98
File diff suppressed because it is too large
Load Diff
+138
-21
File diff suppressed because it is too large
Load Diff
@@ -61,6 +61,10 @@ rt_noreturn void arch_thread_signal_enter(int signo, siginfo_t *psiginfo,
|
||||
void *exp_frame, void *entry_uaddr,
|
||||
lwp_sigset_t *save_sig_mask);
|
||||
|
||||
void arch_signal_check_erestart(void *eframe, void *ksp);
|
||||
|
||||
void arch_syscall_set_errno(void *eframe, int expected, int code);
|
||||
|
||||
int arch_backtrace_uthread(rt_thread_t thread);
|
||||
|
||||
#endif /* __LWP_ARCH_COMM__ */
|
||||
|
||||
@@ -797,6 +797,7 @@ int lwp_load(const char *filename, struct rt_lwp *lwp, uint8_t *load_addr, size_
|
||||
|
||||
/* copy file name to process name */
|
||||
rt_strncpy(lwp->cmd, filename, RT_NAME_MAX);
|
||||
lwp->exe_file = dfs_normalize_path(NULL, filename); // malloc
|
||||
|
||||
ret = elf_file_load(&load_info);
|
||||
if (ret != RT_EOK)
|
||||
|
||||
+15
-14
@@ -475,6 +475,11 @@ static long _futex_wake(rt_futex_t futex, struct rt_lwp *lwp, int number,
|
||||
{
|
||||
number--;
|
||||
woken_cnt++;
|
||||
is_empty = RT_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_empty = RT_TRUE;
|
||||
}
|
||||
_futex_unlock(lwp, op_flags);
|
||||
}
|
||||
@@ -512,23 +517,16 @@ static long _futex_requeue(rt_futex_t futex1, rt_futex_t futex2,
|
||||
*/
|
||||
while (nr_wake && !is_empty)
|
||||
{
|
||||
rt_sched_lock_level_t slvl;
|
||||
rt_sched_lock(&slvl);
|
||||
is_empty = rt_list_isempty(&(futex1->waiting_thread));
|
||||
if (!is_empty)
|
||||
if (rt_susp_list_dequeue(&futex1->waiting_thread, RT_EOK))
|
||||
{
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(futex1->waiting_thread.next);
|
||||
/* remove from waiting list */
|
||||
rt_list_remove(&RT_THREAD_LIST_NODE(thread));
|
||||
|
||||
thread->error = RT_EOK;
|
||||
/* resume the suspended thread */
|
||||
rt_thread_resume(thread);
|
||||
|
||||
nr_wake--;
|
||||
woken_cnt++;
|
||||
is_empty = RT_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
is_empty = RT_TRUE;
|
||||
}
|
||||
rt_sched_unlock(slvl);
|
||||
}
|
||||
rtn = woken_cnt;
|
||||
|
||||
@@ -542,7 +540,10 @@ static long _futex_requeue(rt_futex_t futex1, rt_futex_t futex2,
|
||||
{
|
||||
rt_sched_lock_level_t slvl;
|
||||
rt_sched_lock(&slvl);
|
||||
|
||||
/* moving from one susp list to another */
|
||||
is_empty = rt_list_isempty(&(futex1->waiting_thread));
|
||||
|
||||
if (!is_empty)
|
||||
{
|
||||
thread = RT_THREAD_LIST_NODE_ENTRY(futex1->waiting_thread.next);
|
||||
@@ -914,7 +915,7 @@ void lwp_futex_exit_robust_list(rt_thread_t thread)
|
||||
rc = _fetch_robust_entry(&next_entry, &entry->next, &next_pi);
|
||||
if (entry != pending)
|
||||
{
|
||||
if (_handle_futex_death((void *)entry + futex_offset, thread, pi,
|
||||
if (_handle_futex_death((int *)((size_t)entry + futex_offset), thread, pi,
|
||||
RT_FALSE))
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-07-25 Shell first version
|
||||
* 2023-11-25 Shell Add pgrp, session lock API
|
||||
*/
|
||||
|
||||
#define DBG_TAG "lwp.internal"
|
||||
@@ -15,7 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include "lwp_internal.h"
|
||||
|
||||
static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t interruptable)
|
||||
static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
|
||||
{
|
||||
LWP_DEF_RETURN_CODE(rc);
|
||||
int retry;
|
||||
@@ -45,15 +46,15 @@ static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t i
|
||||
|
||||
do {
|
||||
retry = 0;
|
||||
if (interruptable)
|
||||
if (flags & LWP_MTX_FLAGS_INTR)
|
||||
rc = rt_mutex_take_interruptible(mtx, effect_timeout);
|
||||
else
|
||||
rc = rt_mutex_take(mtx, effect_timeout);
|
||||
rc = rt_mutex_take_killable(mtx, effect_timeout);
|
||||
|
||||
#ifdef LWP_DEBUG
|
||||
if (rc == RT_EOK)
|
||||
{
|
||||
if (rt_mutex_get_hold(mtx) > 1)
|
||||
if (!(flags & LWP_MTX_FALGS_NESTED) && rt_mutex_get_hold(mtx) > 1)
|
||||
{
|
||||
LOG_W("Already hold the lock");
|
||||
rt_backtrace();
|
||||
@@ -88,6 +89,7 @@ static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t i
|
||||
}
|
||||
else
|
||||
{
|
||||
rc = -RT_EINVAL;
|
||||
LOG_W("%s: mtx should not be NULL", __func__);
|
||||
RT_ASSERT(0);
|
||||
}
|
||||
@@ -95,10 +97,10 @@ static rt_err_t _mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t i
|
||||
LWP_RETURN(rc);
|
||||
}
|
||||
|
||||
rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t interruptable)
|
||||
rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags)
|
||||
{
|
||||
LWP_DEF_RETURN_CODE(rc);
|
||||
rc = _mutex_take_safe(mtx, timeout, interruptable);
|
||||
rc = _mutex_take_safe(mtx, timeout, flags);
|
||||
LWP_RETURN(rc);
|
||||
}
|
||||
|
||||
@@ -116,18 +118,17 @@ rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx)
|
||||
LWP_RETURN(rc);
|
||||
}
|
||||
|
||||
rt_err_t lwp_critical_enter(struct rt_lwp *lwp)
|
||||
rt_err_t lwp_critical_enter(struct rt_lwp *lwp, int flags)
|
||||
{
|
||||
rt_err_t rc;
|
||||
rc = lwp_mutex_take_safe(&lwp->lwp_lock, RT_WAITING_FOREVER, 0);
|
||||
do {
|
||||
rc = lwp_mutex_take_safe(&lwp->lwp_lock, RT_WAITING_FOREVER, flags);
|
||||
} while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
|
||||
|
||||
/* if current process is force killed */
|
||||
if (rc != RT_EOK)
|
||||
if (rc != RT_EOK && rc != -RT_EINTR)
|
||||
{
|
||||
if (rc == -RT_EINTR && lwp_self() != RT_NULL)
|
||||
sys_exit(EXIT_SUCCESS);
|
||||
else
|
||||
LOG_I("%s: unexpected return code = %ld", __func__, rc);
|
||||
LOG_I("%s: unexpected return code = %ld", __func__, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
@@ -137,3 +138,45 @@ rt_err_t lwp_critical_exit(struct rt_lwp *lwp)
|
||||
{
|
||||
return lwp_mutex_release_safe(&lwp->lwp_lock);
|
||||
}
|
||||
|
||||
rt_err_t lwp_pgrp_critical_enter(struct rt_processgroup *pgrp, int flags)
|
||||
{
|
||||
rt_err_t rc;
|
||||
do {
|
||||
rc = lwp_mutex_take_safe(&pgrp->mutex, RT_WAITING_FOREVER, flags);
|
||||
} while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
|
||||
|
||||
/* if current process is force killed */
|
||||
if (rc != RT_EOK && rc != -RT_EINTR)
|
||||
{
|
||||
LOG_I("%s: unexpected return code = %ld", __func__, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
rt_err_t lwp_pgrp_critical_exit(struct rt_processgroup *pgrp)
|
||||
{
|
||||
return lwp_mutex_release_safe(&pgrp->mutex);
|
||||
}
|
||||
|
||||
rt_err_t lwp_sess_critical_enter(struct rt_session *sess, int flags)
|
||||
{
|
||||
rt_err_t rc;
|
||||
do {
|
||||
rc = lwp_mutex_take_safe(&sess->mutex, RT_WAITING_FOREVER, flags);
|
||||
} while (rc != RT_EOK && !(flags & LWP_MTX_FLAGS_INTR) && rc == -RT_EINTR);
|
||||
|
||||
/* if current process is force killed */
|
||||
if (rc != RT_EOK && rc != -RT_EINTR)
|
||||
{
|
||||
LOG_I("%s: unexpected return code = %ld", __func__, rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
rt_err_t lwp_sess_critical_exit(struct rt_session *sess)
|
||||
{
|
||||
return lwp_mutex_release_safe(&sess->mutex);
|
||||
}
|
||||
|
||||
@@ -6,21 +6,32 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-07-25 Shell first version
|
||||
* 2023-11-25 Shell Add pgrp, session lock API
|
||||
*/
|
||||
|
||||
#ifndef __LWP_INTERNAL_H__
|
||||
#define __LWP_INTERNAL_H__
|
||||
|
||||
#include "lwp.h"
|
||||
#include "lwp_arch.h"
|
||||
#include "lwp_user_mm.h"
|
||||
#include "lwp_mm.h"
|
||||
|
||||
#include <rtthread.h>
|
||||
#include "libc_musl.h"
|
||||
|
||||
struct rt_lwp;
|
||||
rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, rt_bool_t interruptable);
|
||||
|
||||
#define LWP_MTX_FLAGS_INTR 0x1 /* interruptible waiting */
|
||||
#define LWP_MTX_FALGS_NESTED 0x2 /* allow nested */
|
||||
rt_err_t lwp_mutex_take_safe(rt_mutex_t mtx, rt_int32_t timeout, int flags);
|
||||
rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx);
|
||||
|
||||
rt_inline rt_bool_t lwp_in_user_space(const char *addr)
|
||||
{
|
||||
return (addr >= (char *)USER_VADDR_START && addr < (char *)USER_VADDR_TOP);
|
||||
}
|
||||
|
||||
#ifdef RT_USING_SMP
|
||||
#define LOCAL_IRQ_MASK() rt_hw_local_irq_disable()
|
||||
#define LOCAL_IRQ_UNMASK(level) rt_hw_local_irq_enable(level)
|
||||
@@ -30,16 +41,34 @@ rt_err_t lwp_mutex_release_safe(rt_mutex_t mtx);
|
||||
#endif
|
||||
|
||||
#ifndef LWP_USING_CPUS_LOCK
|
||||
rt_err_t lwp_critical_enter(struct rt_lwp *lwp);
|
||||
rt_err_t lwp_sess_critical_enter(struct rt_session *sess, int flags);
|
||||
rt_err_t lwp_sess_critical_exit(struct rt_session *sess);
|
||||
rt_err_t lwp_pgrp_critical_enter(struct rt_processgroup *pgrp, int flags);
|
||||
rt_err_t lwp_pgrp_critical_exit(struct rt_processgroup *pgrp);
|
||||
rt_err_t lwp_critical_enter(struct rt_lwp *lwp, int flags);
|
||||
rt_err_t lwp_critical_exit(struct rt_lwp *lwp);
|
||||
|
||||
#define LWP_LOCK(lwp) \
|
||||
do { \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_critical_enter(lwp) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
#define LWP_ASSERT_LOCKED(proc) RT_ASSERT(rt_mutex_get_owner(&(proc)->lwp_lock) == rt_thread_self())
|
||||
#define PGRP_ASSERT_LOCKED(pgrp) RT_ASSERT(rt_mutex_get_owner(&(pgrp)->mutex) == rt_thread_self())
|
||||
|
||||
#define LWP_LOCK(lwp) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_critical_enter(lwp, 0) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LWP_LOCK_NESTED(lwp) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_critical_enter(lwp, LWP_MTX_FALGS_NESTED) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define LWP_UNLOCK(lwp) \
|
||||
@@ -50,10 +79,72 @@ rt_err_t lwp_critical_exit(struct rt_lwp *lwp);
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PGRP_LOCK(pgrp) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_pgrp_critical_enter(pgrp, 0) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PGRP_LOCK_NESTED(pgrp) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_pgrp_critical_enter(pgrp, LWP_MTX_FALGS_NESTED) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define PGRP_UNLOCK(pgrp) \
|
||||
do \
|
||||
{ \
|
||||
if (lwp_pgrp_critical_exit(pgrp) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SESS_LOCK(sess) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_sess_critical_enter(sess, 0) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SESS_LOCK_NESTED(sess) \
|
||||
do \
|
||||
{ \
|
||||
RT_DEBUG_SCHEDULER_AVAILABLE(1); \
|
||||
if (lwp_sess_critical_enter(sess, LWP_MTX_FALGS_NESTED) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SESS_UNLOCK(sess) \
|
||||
do \
|
||||
{ \
|
||||
if (lwp_sess_critical_exit(sess) != RT_EOK) \
|
||||
{ \
|
||||
RT_ASSERT(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
|
||||
#define LWP_LOCK(lwp) rt_base_t level = rt_hw_interrupt_disable()
|
||||
#define LWP_UNLOCK(lwp) rt_hw_interrupt_enable(level)
|
||||
#define PGRP_LOCK(pgrp) rt_base_t level = rt_hw_interrupt_disable()
|
||||
#define PGRP_UNLOCK(pgrp) rt_hw_interrupt_enable(level)
|
||||
#define SESS_LOCK(sess) rt_base_t level = rt_hw_interrupt_disable()
|
||||
#define SESS_UNLOCK(sess) rt_hw_interrupt_enable(level)
|
||||
|
||||
#endif /* LWP_USING_CPUS_LOCK */
|
||||
|
||||
@@ -95,4 +186,6 @@ rt_err_t lwp_critical_exit(struct rt_lwp *lwp);
|
||||
#define LWP_RETURN(name) {RT_ASSERT(name != _LWP_UNINITIALIZED_RC);return name;}
|
||||
#endif /* LWP_DEBUG */
|
||||
|
||||
int load_ldso(struct rt_lwp *lwp, char *exec_name, char *const argv[], char *const envp[]);
|
||||
|
||||
#endif /* __LWP_INTERNAL_H__ */
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-11-13 Shell init ver.
|
||||
*/
|
||||
|
||||
#define DBG_TAG "lwp.tty"
|
||||
#define DBG_LVL DBG_INFO
|
||||
#include <rtdbg.h>
|
||||
|
||||
#include <terminal/terminal.h>
|
||||
#include "lwp_internal.h"
|
||||
|
||||
static void jobctrl_set_pgrp_orphaned(struct rt_processgroup *pgrp)
|
||||
{
|
||||
rt_lwp_t proc, nx_proc;
|
||||
PGRP_LOCK(pgrp);
|
||||
|
||||
pgrp->is_orphaned = 1;
|
||||
rt_list_for_each_entry(proc, &pgrp->process, pgrp_node)
|
||||
{
|
||||
LWP_LOCK(proc);
|
||||
if (proc->jobctl_stopped)
|
||||
{
|
||||
LWP_UNLOCK(proc);
|
||||
rt_list_for_each_entry_safe(proc, nx_proc, &pgrp->process, pgrp_node)
|
||||
{
|
||||
LWP_LOCK(proc);
|
||||
lwp_signal_kill(proc, SIGHUP, SI_KERNEL, 0);
|
||||
lwp_signal_kill(proc, SIGCONT, SI_KERNEL, 0);
|
||||
LWP_UNLOCK(proc);
|
||||
}
|
||||
}
|
||||
LWP_UNLOCK(proc);
|
||||
}
|
||||
|
||||
PGRP_UNLOCK(pgrp);
|
||||
}
|
||||
|
||||
void lwp_jobctrl_on_exit(struct rt_lwp *lwp)
|
||||
{
|
||||
rt_processgroup_t pgrp;
|
||||
rt_session_t session;
|
||||
lwp_tty_t tp;
|
||||
|
||||
pgrp = lwp->pgrp;
|
||||
RT_ASSERT(pgrp);
|
||||
session = pgrp->session;
|
||||
RT_ASSERT(session);
|
||||
|
||||
/**
|
||||
* as a session leader, we have to mark tty as freed. So others can race to
|
||||
* take it before we actually close and released that tty
|
||||
*/
|
||||
SESS_LOCK(session);
|
||||
if (session->sid == lwp->pid)
|
||||
{
|
||||
tp = session->ctty;
|
||||
session->leader = 0;
|
||||
|
||||
/* signal to foreground group that modem is disconnected */
|
||||
if (tp)
|
||||
{
|
||||
tty_lock(tp);
|
||||
if (tp->t_session == session)
|
||||
lwp_tty_signal_pgrp(tp, SIGHUP);
|
||||
tty_unlock(tp);
|
||||
}
|
||||
|
||||
/* revoke tty vnode ? */
|
||||
|
||||
rt_list_for_each_entry(pgrp, &session->processgroup, pgrp_list_node)
|
||||
{
|
||||
jobctrl_set_pgrp_orphaned(pgrp);
|
||||
}
|
||||
|
||||
}
|
||||
SESS_UNLOCK(session);
|
||||
|
||||
/* release tty */
|
||||
/* allow tty stolen? */
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+498
-210
File diff suppressed because it is too large
Load Diff
@@ -11,14 +11,14 @@
|
||||
#ifndef LWP_PID_H__
|
||||
#define LWP_PID_H__
|
||||
|
||||
#include "lwp.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define LWP_CREATE_FLAG_NONE 0x0000
|
||||
#define LWP_CREATE_FLAG_ALLOC_PID 0x0001 /* allocate pid on lwp object create */
|
||||
#define LWP_CREATE_FLAG_NONE 0x0000
|
||||
#define LWP_CREATE_FLAG_ALLOC_PID 0x0001 /* allocate pid on lwp object create */
|
||||
#define LWP_CREATE_FLAG_INIT_USPACE 0x0002 /* do user space initialization */
|
||||
#define LWP_CREATE_FLAG_NOTRACE_EXEC 0x0004 /* not trace if execve() after fork() */
|
||||
|
||||
struct rt_lwp;
|
||||
|
||||
@@ -46,6 +46,7 @@ void lwp_free(struct rt_lwp* lwp);
|
||||
int lwp_ref_inc(struct rt_lwp *lwp);
|
||||
int lwp_ref_dec(struct rt_lwp *lwp);
|
||||
|
||||
struct rt_lwp* lwp_from_pid_raw_locked(pid_t pid);
|
||||
struct rt_lwp* lwp_from_pid_locked(pid_t pid);
|
||||
pid_t lwp_to_pid(struct rt_lwp* lwp);
|
||||
|
||||
@@ -54,7 +55,29 @@ char* lwp_pid2name(int32_t pid);
|
||||
|
||||
int lwp_getpid(void);
|
||||
|
||||
pid_t lwp_waitpid(const pid_t pid, int *status, int options);
|
||||
struct rusage
|
||||
{
|
||||
struct timeval ru_utime;
|
||||
struct timeval ru_stime;
|
||||
|
||||
long ru_maxrss;
|
||||
long ru_ixrss;
|
||||
long ru_idrss;
|
||||
long ru_isrss;
|
||||
long ru_minflt;
|
||||
long ru_majflt;
|
||||
long ru_nswap;
|
||||
long ru_inblock;
|
||||
long ru_oublock;
|
||||
long ru_msgsnd;
|
||||
long ru_msgrcv;
|
||||
long ru_nsignals;
|
||||
long ru_nvcsw;
|
||||
long ru_nivcsw;
|
||||
long reserved[16];
|
||||
};
|
||||
pid_t lwp_waitpid(const pid_t pid, int *status, int options, struct rusage *ru);
|
||||
rt_err_t lwp_waitpid_kick(struct rt_lwp *parent, struct rt_lwp *self_lwp);
|
||||
pid_t waitpid(pid_t pid, int *status, int options);
|
||||
long list_process(void);
|
||||
|
||||
@@ -85,8 +108,9 @@ rt_inline void lwp_from_pid_release_lock(struct rt_lwp *lwp)
|
||||
lwp_ref_dec(lwp);
|
||||
}
|
||||
|
||||
void lwp_thread_exit(rt_thread_t thread, rt_base_t status);
|
||||
void lwp_exit(struct rt_lwp *lwp, rt_base_t status);
|
||||
typedef rt_base_t lwp_status_t;
|
||||
void lwp_thread_exit(rt_thread_t thread, int status);
|
||||
void lwp_exit(struct rt_lwp *lwp, lwp_status_t status);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,27 +0,0 @@
|
||||
#include <rthw.h>
|
||||
#include <rtthread.h>
|
||||
|
||||
#include "lwp.h"
|
||||
//#include "lwp_tid.h"
|
||||
#include "lwp_pid.h"
|
||||
|
||||
int setsid(void)
|
||||
{
|
||||
int err = -EPERM;
|
||||
struct rt_thread *current_thread = rt_thread_self();
|
||||
struct rt_lwp *current_lwp = (struct rt_lwp *)rt_thread_self()->lwp;
|
||||
|
||||
if (current_lwp->session == current_thread->tid)
|
||||
{
|
||||
return err;
|
||||
}
|
||||
|
||||
current_lwp->session = current_thread->tid;
|
||||
current_lwp->__pgrp = current_thread->tid;
|
||||
current_lwp->leader = 1;
|
||||
current_lwp->tty = RT_NULL;
|
||||
current_lwp->tty_old_pgrp = 0;
|
||||
|
||||
err = current_lwp->session;
|
||||
return err;
|
||||
}
|
||||
+458
-88
File diff suppressed because it is too large
Load Diff
+68
-15
@@ -7,6 +7,7 @@
|
||||
* Date Author Notes
|
||||
* 2020-02-23 Jesven first version.
|
||||
* 2023-07-06 Shell update the generation, pending and delivery API
|
||||
* 2023-11-22 Shell support for job control signal
|
||||
*/
|
||||
|
||||
#ifndef __LWP_SIGNAL_H__
|
||||
@@ -17,23 +18,33 @@
|
||||
#include <rtthread.h>
|
||||
#include <sys/signal.h>
|
||||
|
||||
struct timespec;
|
||||
struct itimerspec;
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define _USIGNAL_SIGMASK(signo) (1u << ((signo)-1))
|
||||
#define LWP_SIG_IGNORE_SET (_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG))
|
||||
#define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
|
||||
#define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
|
||||
#define LWP_SIG_USER_SA_FLAGS \
|
||||
(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
|
||||
#define LWP_SIG_NO_IGN_SET \
|
||||
(_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
|
||||
_USIGNAL_SIGMASK(SIGKILL))
|
||||
#define LWP_SIG_IGNORE_SET \
|
||||
(_USIGNAL_SIGMASK(SIGCHLD) | _USIGNAL_SIGMASK(SIGURG) | \
|
||||
_USIGNAL_SIGMASK(SIGWINCH) /* from 4.3 BSD, not POSIX.1 */)
|
||||
#define LWP_SIG_JOBCTL_SET \
|
||||
(_USIGNAL_SIGMASK(SIGCONT) | _USIGNAL_SIGMASK(SIGSTOP) | \
|
||||
_USIGNAL_SIGMASK(SIGTSTP) | _USIGNAL_SIGMASK(SIGTTIN) | \
|
||||
_USIGNAL_SIGMASK(SIGTTOU))
|
||||
#define LWP_SIG_STOP_SET \
|
||||
(_USIGNAL_SIGMASK(SIGSTOP) | _USIGNAL_SIGMASK(SIGTSTP) | \
|
||||
_USIGNAL_SIGMASK(SIGTTIN) | _USIGNAL_SIGMASK(SIGTTOU))
|
||||
#define LWP_SIG_ACT_DFL ((lwp_sighandler_t)0)
|
||||
#define LWP_SIG_ACT_IGN ((lwp_sighandler_t)1)
|
||||
#define LWP_SIG_USER_SA_FLAGS \
|
||||
(SA_NOCLDSTOP | SA_NOCLDWAIT | SA_SIGINFO | SA_ONSTACK | SA_RESTART | \
|
||||
SA_NODEFER | SA_RESETHAND | SA_EXPOSE_TAGBITS)
|
||||
#define LWP_SIG_INVALID_TIMER ((timer_t)-1)
|
||||
|
||||
typedef enum {
|
||||
typedef enum
|
||||
{
|
||||
LWP_SIG_MASK_CMD_BLOCK,
|
||||
LWP_SIG_MASK_CMD_UNBLOCK,
|
||||
LWP_SIG_MASK_CMD_SET_MASK,
|
||||
@@ -43,7 +54,8 @@ typedef enum {
|
||||
/**
|
||||
* LwP implementation of POSIX signal
|
||||
*/
|
||||
struct lwp_signal {
|
||||
struct lwp_signal
|
||||
{
|
||||
timer_t real_timer;
|
||||
struct lwp_sigqueue sig_queue;
|
||||
rt_thread_t sig_dispatch_thr[_LWP_NSIG];
|
||||
@@ -55,9 +67,12 @@ struct lwp_signal {
|
||||
lwp_sigset_t sig_action_onstack;
|
||||
lwp_sigset_t sig_action_restart;
|
||||
lwp_sigset_t sig_action_siginfo;
|
||||
lwp_sigset_t sig_action_nocldstop;
|
||||
lwp_sigset_t sig_action_nocldwait;
|
||||
};
|
||||
|
||||
struct rt_lwp;
|
||||
struct rt_processgroup;
|
||||
|
||||
#ifndef ARCH_MM_MMU
|
||||
void lwp_sighandler_set(int sig, lwp_sighandler_t func);
|
||||
@@ -93,12 +108,14 @@ rt_inline void lwp_thread_signal_detach(struct lwp_thread_signal *tsig)
|
||||
* @param signo the signal number
|
||||
* @param code as in siginfo
|
||||
* @param value as in siginfo
|
||||
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as successful
|
||||
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
||||
* successful
|
||||
*
|
||||
* @note the *signal_kill have the same definition of a successful return as
|
||||
* kill() in IEEE Std 1003.1-2017
|
||||
*/
|
||||
rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code, long value);
|
||||
rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code,
|
||||
lwp_siginfo_ext_t value);
|
||||
|
||||
/**
|
||||
* @brief set or examine the signal action of signo
|
||||
@@ -119,9 +136,11 @@ rt_err_t lwp_signal_action(struct rt_lwp *lwp, int signo,
|
||||
* @param signo the signal number
|
||||
* @param code as in siginfo
|
||||
* @param value as in siginfo
|
||||
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as successful
|
||||
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
||||
* successful
|
||||
*/
|
||||
rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, long value);
|
||||
rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code,
|
||||
lwp_siginfo_ext_t value);
|
||||
|
||||
/**
|
||||
* @brief set signal mask of target thread
|
||||
@@ -136,7 +155,8 @@ rt_err_t lwp_thread_signal_mask(rt_thread_t thread, lwp_sig_mask_cmd_t how,
|
||||
const lwp_sigset_t *sigset, lwp_sigset_t *oset);
|
||||
|
||||
/**
|
||||
* @brief Catch signal if exists and no return, otherwise return with no side effect
|
||||
* @brief Catch signal if exists and no return, otherwise return with no
|
||||
* side effect
|
||||
*
|
||||
* @param exp_frame the exception frame on kernel stack
|
||||
*/
|
||||
@@ -172,10 +192,43 @@ rt_err_t lwp_thread_signal_timedwait(rt_thread_t thread, lwp_sigset_t *sigset,
|
||||
*/
|
||||
void lwp_thread_signal_pending(rt_thread_t thread, lwp_sigset_t *sigset);
|
||||
|
||||
/**
|
||||
* @brief send a signal to the process group
|
||||
*
|
||||
* @param pgrp target process group
|
||||
* @param signo the signal number
|
||||
* @param code as in siginfo
|
||||
* @param value as in siginfo
|
||||
* @return rt_err_t RT_EINVAL if the parameter is invalid, RT_EOK as
|
||||
* successful
|
||||
*/
|
||||
rt_err_t lwp_pgrp_signal_kill(struct rt_processgroup *pgrp, long signo,
|
||||
long code, lwp_siginfo_ext_t value);
|
||||
|
||||
rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig)
|
||||
{
|
||||
unsigned long sig = _sig - 1;
|
||||
|
||||
if (_LWP_NSIG_WORDS == 1)
|
||||
{
|
||||
return 1 & (set->sig[0] >> sig);
|
||||
}
|
||||
else
|
||||
{
|
||||
return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
|
||||
}
|
||||
}
|
||||
|
||||
struct itimerspec;
|
||||
|
||||
rt_bool_t lwp_sigisign(struct rt_lwp *lwp, int _sig);
|
||||
|
||||
rt_err_t lwp_signal_setitimer(struct rt_lwp *lwp, int which,
|
||||
const struct itimerspec *restrict new,
|
||||
struct itimerspec *restrict old);
|
||||
|
||||
rt_bool_t lwp_signal_restart_syscall(struct rt_lwp *lwp, int error_code);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -113,7 +113,7 @@ struct musl_ifreq
|
||||
{
|
||||
union
|
||||
{
|
||||
#define IFNAMSIZ 16
|
||||
#define IFNAMSIZ 16
|
||||
char ifrn_name[IFNAMSIZ];
|
||||
} ifr_ifrn;
|
||||
union
|
||||
@@ -133,4 +133,23 @@ struct musl_ifreq
|
||||
} ifr_ifru;
|
||||
};
|
||||
|
||||
struct musl_rtentry
|
||||
{
|
||||
unsigned long int rt_pad1;
|
||||
struct musl_sockaddr rt_dst;
|
||||
struct musl_sockaddr rt_gateway;
|
||||
struct musl_sockaddr rt_genmask;
|
||||
unsigned short int rt_flags;
|
||||
short int rt_pad2;
|
||||
unsigned long int rt_pad3;
|
||||
unsigned char rt_tos;
|
||||
unsigned char rt_class;
|
||||
short int rt_pad4[sizeof(long)/2-1];
|
||||
short int rt_metric;
|
||||
char *rt_dev;
|
||||
unsigned long int rt_mtu;
|
||||
unsigned long int rt_window;
|
||||
unsigned short int rt_irtt;
|
||||
};
|
||||
|
||||
#endif /* __LWP_SYS_SOCKET_H__ */
|
||||
|
||||
+382
-375
File diff suppressed because it is too large
Load Diff
@@ -108,10 +108,15 @@ sysret_t sys_log(const char* log, int size);
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
sysret_t sys_futex(int *uaddr, int op, int val, const struct timespec *timeout, int *uaddr2, int val3);
|
||||
sysret_t sys_pmutex(void *umutex, int op, void *arg);
|
||||
sysret_t sys_cacheflush(void *addr, int len, int cache);
|
||||
#endif /* ARCH_MM_MMU */
|
||||
|
||||
sysret_t sys_setsid(void);
|
||||
sysret_t sys_getsid(pid_t pid);
|
||||
sysret_t sys_setpgid(pid_t pid, pid_t pgid);
|
||||
sysret_t sys_getpgid(pid_t pid);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2021-01-15 shaojinchun first version
|
||||
* 2023-11-16 xqyjlj Fix the case where tid is 0
|
||||
*/
|
||||
|
||||
#define DBG_TAG "lwp.tid"
|
||||
@@ -126,20 +127,28 @@ void lwp_tid_put(int tid)
|
||||
lwp_mutex_release_safe(&tid_lock);
|
||||
}
|
||||
|
||||
rt_thread_t lwp_tid_get_thread_and_inc_ref(int tid)
|
||||
rt_thread_t lwp_tid_get_thread_raw(int tid)
|
||||
{
|
||||
struct lwp_avl_struct *p;
|
||||
rt_thread_t thread = RT_NULL;
|
||||
lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
|
||||
|
||||
p = lwp_avl_find(tid, lwp_tid_root);
|
||||
if (p)
|
||||
{
|
||||
thread = (rt_thread_t)p->data;
|
||||
if (thread != RT_NULL)
|
||||
{
|
||||
thread->tid_ref_count += 1;
|
||||
}
|
||||
}
|
||||
return thread;
|
||||
}
|
||||
|
||||
rt_thread_t lwp_tid_get_thread_and_inc_ref(int tid)
|
||||
{
|
||||
rt_thread_t thread = RT_NULL;
|
||||
|
||||
lwp_mutex_take_safe(&tid_lock, RT_WAITING_FOREVER, 0);
|
||||
thread = tid ? lwp_tid_get_thread_raw(tid) : rt_thread_self();
|
||||
if (thread != RT_NULL)
|
||||
{
|
||||
thread->tid_ref_count += 1;
|
||||
}
|
||||
lwp_mutex_release_safe(&tid_lock);
|
||||
return thread;
|
||||
|
||||
@@ -23,10 +23,7 @@
|
||||
|
||||
#ifdef ARCH_MM_MMU
|
||||
|
||||
#include <lwp.h>
|
||||
#include <lwp_arch.h>
|
||||
#include <lwp_mm.h>
|
||||
#include <lwp_user_mm.h>
|
||||
#include "lwp_internal.h"
|
||||
|
||||
#include <mm_aspace.h>
|
||||
#include <mm_fault.h>
|
||||
@@ -161,10 +158,10 @@ void lwp_aspace_switch(struct rt_thread *thread)
|
||||
|
||||
void lwp_unmap_user_space(struct rt_lwp *lwp)
|
||||
{
|
||||
arch_user_space_free(lwp);
|
||||
if (lwp->aspace)
|
||||
arch_user_space_free(lwp);
|
||||
}
|
||||
|
||||
|
||||
static void *_lwp_map_user(struct rt_lwp *lwp, void *map_va, size_t map_size,
|
||||
int text)
|
||||
{
|
||||
@@ -566,6 +563,14 @@ int lwp_munmap(struct rt_lwp *lwp, void *addr, size_t length)
|
||||
return lwp_errno_to_posix(ret);
|
||||
}
|
||||
|
||||
void *lwp_mremap(struct rt_lwp *lwp, void *old_address, size_t old_size,
|
||||
size_t new_size, int flags, void *new_address)
|
||||
{
|
||||
RT_ASSERT(lwp);
|
||||
|
||||
return rt_aspace_mremap_range(lwp->aspace, old_address, old_size, new_size, flags, new_address);
|
||||
}
|
||||
|
||||
size_t lwp_get_from_user(void *dst, void *src, size_t size)
|
||||
{
|
||||
struct rt_lwp *lwp = RT_NULL;
|
||||
@@ -621,11 +626,6 @@ size_t lwp_put_to_user(void *dst, void *src, size_t size)
|
||||
return lwp_data_put(lwp, dst, src, size);
|
||||
}
|
||||
|
||||
rt_inline rt_bool_t _in_user_space(const char *addr)
|
||||
{
|
||||
return (addr >= (char *)USER_VADDR_START && addr < (char *)USER_VADDR_TOP);
|
||||
}
|
||||
|
||||
rt_inline rt_bool_t _can_unaligned_access(const char *addr)
|
||||
{
|
||||
return rt_kmem_v2p((char *)addr) - PV_OFFSET == addr;
|
||||
@@ -636,9 +636,9 @@ void *lwp_memcpy(void * __restrict dst, const void * __restrict src, size_t size
|
||||
void *rc = dst;
|
||||
long len;
|
||||
|
||||
if (_in_user_space(dst))
|
||||
if (lwp_in_user_space(dst))
|
||||
{
|
||||
if (!_in_user_space(src))
|
||||
if (!lwp_in_user_space(src))
|
||||
{
|
||||
len = lwp_put_to_user(dst, (void *)src, size);
|
||||
if (!len)
|
||||
@@ -654,7 +654,7 @@ void *lwp_memcpy(void * __restrict dst, const void * __restrict src, size_t size
|
||||
}
|
||||
else
|
||||
{
|
||||
if (_in_user_space(src))
|
||||
if (lwp_in_user_space(src))
|
||||
{
|
||||
len = lwp_get_from_user(dst, (void *)src, size);
|
||||
if (!len)
|
||||
@@ -979,6 +979,13 @@ size_t lwp_user_strlen(const char *s)
|
||||
return lwp_user_strlen_ext(lwp, s);
|
||||
}
|
||||
|
||||
size_t lwp_strlen(struct rt_lwp *lwp, const char *s)
|
||||
{
|
||||
if (lwp_in_user_space(s))
|
||||
return lwp_user_strlen_ext(lwp, s);
|
||||
else
|
||||
return strlen(s);
|
||||
}
|
||||
|
||||
char** lwp_get_command_line_args(struct rt_lwp *lwp)
|
||||
{
|
||||
|
||||
@@ -56,6 +56,9 @@ void* lwp_mmap2(struct rt_lwp *lwp, void *addr, size_t length, int prot, int fla
|
||||
*/
|
||||
int lwp_munmap(struct rt_lwp *lwp, void *addr, size_t length);
|
||||
|
||||
void *lwp_mremap(struct rt_lwp *lwp, void *old_address, size_t old_size,
|
||||
size_t new_size, int flags, void *new_address);
|
||||
|
||||
/**
|
||||
* @brief Test if address from user is accessible address by user
|
||||
*
|
||||
@@ -163,6 +166,7 @@ rt_base_t lwp_brk(void *addr);
|
||||
|
||||
size_t lwp_user_strlen(const char *s);
|
||||
size_t lwp_user_strlen_ext(struct rt_lwp *lwp, const char *s);
|
||||
size_t lwp_strlen(struct rt_lwp *lwp, const char *s);
|
||||
|
||||
int lwp_fork_aspace(struct rt_lwp *dest_lwp, struct rt_lwp *src_lwp);
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
menuconfig LWP_USING_TERMINAL
|
||||
bool "Terminal I/O Subsystem"
|
||||
depends on RT_USING_SMART
|
||||
default y
|
||||
|
||||
if LWP_USING_TERMINAL
|
||||
config LWP_PTY_MAX_PARIS_LIMIT
|
||||
int "Max number of pty devices registered at the same time"
|
||||
default 64
|
||||
help
|
||||
This upper limit is set to protect kernel memory from draining
|
||||
out by the application if it keeps allocating pty devices.
|
||||
endif
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-11-13 Shell init ver.
|
||||
*/
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed under sponsorship from Snow
|
||||
* B.V., the Netherlands.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TTYDISC_H_
|
||||
#define _SYS_TTYDISC_H_
|
||||
|
||||
#ifndef __LWP_TERMINAL_H__
|
||||
#error "can only be included through <terminal.h>"
|
||||
#endif /* !__LWP_TERMINAL_H__ */
|
||||
|
||||
#include <rtdef.h>
|
||||
|
||||
struct rt_wqueue;
|
||||
struct rt_thread;
|
||||
struct lwp_tty;
|
||||
struct uio;
|
||||
|
||||
/* Top half routines. */
|
||||
void ttydisc_open(struct lwp_tty *tp);
|
||||
void ttydisc_close(struct lwp_tty *tp);
|
||||
int ttydisc_read(struct lwp_tty *tp, struct uio *uio, int ioflag);
|
||||
int ttydisc_write(struct lwp_tty *tp, struct uio *uio, int ioflag);
|
||||
void ttydisc_optimize(struct lwp_tty *tp);
|
||||
|
||||
/* Bottom half routines. */
|
||||
void ttydisc_modem(struct lwp_tty *tp, int open);
|
||||
#define ttydisc_can_bypass(tp) ((tp)->t_flags & TF_BYPASS)
|
||||
int ttydisc_rint(struct lwp_tty *tp, char c, int flags);
|
||||
size_t ttydisc_rint_simple(struct lwp_tty *tp, const void *buf, size_t len);
|
||||
size_t ttydisc_rint_bypass(struct lwp_tty *tp, const void *buf, size_t len);
|
||||
void ttydisc_rint_done(struct lwp_tty *tp);
|
||||
size_t ttydisc_rint_poll(struct lwp_tty *tp);
|
||||
size_t ttydisc_getc(struct lwp_tty *tp, void *buf, size_t len);
|
||||
int ttydisc_getc_uio(struct lwp_tty *tp, struct uio *uio);
|
||||
size_t ttydisc_getc_poll(struct lwp_tty *tp);
|
||||
|
||||
/* Error codes for ttydisc_rint(). */
|
||||
#define TRE_FRAMING 0x01
|
||||
#define TRE_PARITY 0x02
|
||||
#define TRE_OVERRUN 0x04
|
||||
#define TRE_BREAK 0x08
|
||||
|
||||
#endif /* !_SYS_TTYDISC_H_ */
|
||||
@@ -0,0 +1,180 @@
|
||||
/*
|
||||
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Change Logs:
|
||||
* Date Author Notes
|
||||
* 2023-11-13 Shell init ver.
|
||||
*/
|
||||
|
||||
#include "bsd_porting.h"
|
||||
|
||||
/*-
|
||||
* SPDX-License-Identifier: BSD-2-Clause
|
||||
*
|
||||
* Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Portions of this software were developed under sponsorship from Snow
|
||||
* B.V., the Netherlands.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#ifndef _SYS_TTYQUEUE_H_
|
||||
#define _SYS_TTYQUEUE_H_
|
||||
|
||||
#ifndef __LWP_TERMINAL_H__
|
||||
#error "can only be included through <teminal.h>"
|
||||
#endif /* !__LWP_TERMINAL_H__ */
|
||||
|
||||
struct lwp_tty;
|
||||
struct ttyinq_block;
|
||||
struct ttyoutq_block;
|
||||
struct uio;
|
||||
|
||||
/* Data input queue. */
|
||||
struct ttyinq
|
||||
{
|
||||
struct ttyinq_block *ti_firstblock;
|
||||
struct ttyinq_block *ti_startblock;
|
||||
struct ttyinq_block *ti_reprintblock;
|
||||
struct ttyinq_block *ti_lastblock;
|
||||
unsigned int ti_begin;
|
||||
unsigned int ti_linestart;
|
||||
unsigned int ti_reprint;
|
||||
unsigned int ti_end;
|
||||
unsigned int ti_nblocks;
|
||||
unsigned int ti_quota;
|
||||
};
|
||||
#define TTYINQ_DATASIZE 128
|
||||
|
||||
/* Data output queue. */
|
||||
struct ttyoutq
|
||||
{
|
||||
struct ttyoutq_block *to_firstblock;
|
||||
struct ttyoutq_block *to_lastblock;
|
||||
unsigned int to_begin;
|
||||
unsigned int to_end;
|
||||
unsigned int to_nblocks;
|
||||
unsigned int to_quota;
|
||||
};
|
||||
#define TTYOUTQ_DATASIZE (256 - sizeof(struct ttyoutq_block *))
|
||||
|
||||
/* Input queue handling routines. */
|
||||
int ttyinq_setsize(struct ttyinq *ti, struct lwp_tty *tp, size_t len);
|
||||
void ttyinq_free(struct ttyinq *ti);
|
||||
int ttyinq_read_uio(struct ttyinq *ti, struct lwp_tty *tp, struct uio *uio,
|
||||
size_t readlen, size_t flushlen);
|
||||
size_t ttyinq_write(struct ttyinq *ti, const void *buf, size_t len, int quote);
|
||||
int ttyinq_write_nofrag(struct ttyinq *ti, const void *buf, size_t len,
|
||||
int quote);
|
||||
void ttyinq_canonicalize(struct ttyinq *ti);
|
||||
size_t ttyinq_findchar(struct ttyinq *ti, const char *breakc, size_t maxlen,
|
||||
char *lastc);
|
||||
void ttyinq_flush(struct ttyinq *ti);
|
||||
int ttyinq_peekchar(struct ttyinq *ti, char *c, int *quote);
|
||||
void ttyinq_unputchar(struct ttyinq *ti);
|
||||
void ttyinq_reprintpos_set(struct ttyinq *ti);
|
||||
void ttyinq_reprintpos_reset(struct ttyinq *ti);
|
||||
|
||||
rt_inline size_t ttyinq_getsize(struct ttyinq *ti)
|
||||
{
|
||||
return (ti->ti_nblocks * TTYINQ_DATASIZE);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyinq_getallocatedsize(struct ttyinq *ti)
|
||||
{
|
||||
return (ti->ti_quota * TTYINQ_DATASIZE);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyinq_bytesleft(struct ttyinq *ti)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* Make sure the usage never exceeds the length. */
|
||||
len = ti->ti_nblocks * TTYINQ_DATASIZE;
|
||||
MPASS(len >= ti->ti_end);
|
||||
|
||||
return (len - ti->ti_end);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyinq_bytescanonicalized(struct ttyinq *ti)
|
||||
{
|
||||
MPASS(ti->ti_begin <= ti->ti_linestart);
|
||||
|
||||
return (ti->ti_linestart - ti->ti_begin);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyinq_bytesline(struct ttyinq *ti)
|
||||
{
|
||||
MPASS(ti->ti_linestart <= ti->ti_end);
|
||||
|
||||
return (ti->ti_end - ti->ti_linestart);
|
||||
}
|
||||
|
||||
/* Input buffer iteration. */
|
||||
typedef void ttyinq_line_iterator_t(void *data, char c, int flags);
|
||||
void ttyinq_line_iterate_from_linestart(struct ttyinq *ti,
|
||||
ttyinq_line_iterator_t *iterator,
|
||||
void *data);
|
||||
void ttyinq_line_iterate_from_reprintpos(struct ttyinq *ti,
|
||||
ttyinq_line_iterator_t *iterator,
|
||||
void *data);
|
||||
|
||||
/* Output queue handling routines. */
|
||||
void ttyoutq_flush(struct ttyoutq *to);
|
||||
int ttyoutq_setsize(struct ttyoutq *to, struct lwp_tty *tp, size_t len);
|
||||
void ttyoutq_free(struct ttyoutq *to);
|
||||
size_t ttyoutq_read(struct ttyoutq *to, void *buf, size_t len);
|
||||
int ttyoutq_read_uio(struct ttyoutq *to, struct lwp_tty *tp, struct uio *uio);
|
||||
size_t ttyoutq_write(struct ttyoutq *to, const void *buf, size_t len);
|
||||
int ttyoutq_write_nofrag(struct ttyoutq *to, const void *buf, size_t len);
|
||||
|
||||
rt_inline size_t ttyoutq_getsize(struct ttyoutq *to)
|
||||
{
|
||||
return (to->to_nblocks * TTYOUTQ_DATASIZE);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyoutq_getallocatedsize(struct ttyoutq *to)
|
||||
{
|
||||
return (to->to_quota * TTYOUTQ_DATASIZE);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyoutq_bytesleft(struct ttyoutq *to)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* Make sure the usage never exceeds the length. */
|
||||
len = to->to_nblocks * TTYOUTQ_DATASIZE;
|
||||
MPASS(len >= to->to_end);
|
||||
|
||||
return (len - to->to_end);
|
||||
}
|
||||
|
||||
rt_inline size_t ttyoutq_bytesused(struct ttyoutq *to)
|
||||
{
|
||||
return (to->to_end - to->to_begin);
|
||||
}
|
||||
|
||||
#endif /* !_SYS_TTYQUEUE_H_ */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user