mirror of
https://github.com/RT-Thread/rt-thread.git
synced 2025-02-22 03:55:24 +08:00
Add the system call signalfd (#8001)
This commit is contained in:
parent
e8e980879e
commit
7c3d966df6
15
components/libc/posix/io/signalfd/SConscript
Normal file
15
components/libc/posix/io/signalfd/SConscript
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# RT-Thread building script for component
|
||||||
|
|
||||||
|
from building import *
|
||||||
|
|
||||||
|
cwd = GetCurrentDir()
|
||||||
|
src = []
|
||||||
|
CPPPATH = [cwd]
|
||||||
|
|
||||||
|
if GetDepend('RT_USING_DFS'):
|
||||||
|
if GetDepend('RT_USING_MUSLLIBC'):
|
||||||
|
src += ['signalfd.c']
|
||||||
|
|
||||||
|
group = DefineGroup('POSIX', src, depend = ['RT_USING_SMART'], CPPPATH = CPPPATH)
|
||||||
|
|
||||||
|
Return('group')
|
302
components/libc/posix/io/signalfd/signalfd.c
Normal file
302
components/libc/posix/io/signalfd/signalfd.c
Normal file
@ -0,0 +1,302 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2006-2023, RT-Thread Development Team
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*
|
||||||
|
* Change Logs:
|
||||||
|
* Date Author Notes
|
||||||
|
* 2023-08-29 zmq810150896 first version
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <rtthread.h>
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#include <dfs_file.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <rthw.h>
|
||||||
|
#include <sys/time.h>
|
||||||
|
#include <lwp_signal.h>
|
||||||
|
#include <lwp.h>
|
||||||
|
#include <poll.h>
|
||||||
|
|
||||||
|
#define SIGNALFD_MUTEX_NAME "signalfd"
|
||||||
|
#define SIGNALFD_SHART_MAX 10
|
||||||
|
|
||||||
|
static int is_head_init = 0;
|
||||||
|
|
||||||
|
struct rt_signalfd_ctx
|
||||||
|
{
|
||||||
|
sigset_t sigmask;
|
||||||
|
struct rt_mutex lock;
|
||||||
|
siginfo_t info;
|
||||||
|
int tick;
|
||||||
|
rt_wqueue_t signalfd_queue;
|
||||||
|
struct rt_lwp *lwp[SIGNALFD_SHART_MAX];
|
||||||
|
};
|
||||||
|
|
||||||
|
static int signalfd_close(struct dfs_file *file);
|
||||||
|
static int signalfd_poll(struct dfs_file *file, struct rt_pollreq *req);
|
||||||
|
#ifndef RT_USING_DFS_V2
|
||||||
|
static ssize_t signalfd_read(struct dfs_file *file, void *buf, size_t count);
|
||||||
|
#else
|
||||||
|
static ssize_t signalfd_read(struct dfs_file *file, void *buf, size_t count, off_t *pos);
|
||||||
|
#endif
|
||||||
|
static int signalfd_add_notify(struct rt_signalfd_ctx *sfd);
|
||||||
|
|
||||||
|
static const struct dfs_file_ops signalfd_fops =
|
||||||
|
{
|
||||||
|
.close = signalfd_close,
|
||||||
|
.poll = signalfd_poll,
|
||||||
|
.read = signalfd_read,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int signalfd_close(struct dfs_file *file)
|
||||||
|
{
|
||||||
|
struct rt_signalfd_ctx *sfd;
|
||||||
|
|
||||||
|
if (file->vnode->ref_count != 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
sfd = file->vnode->data;
|
||||||
|
|
||||||
|
if (sfd)
|
||||||
|
{
|
||||||
|
rt_mutex_detach(&sfd->lock);
|
||||||
|
rt_free(sfd);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int signalfd_poll(struct dfs_file *file, struct rt_pollreq *req)
|
||||||
|
{
|
||||||
|
struct rt_signalfd_ctx *sfd;
|
||||||
|
int events = 0;
|
||||||
|
|
||||||
|
if (file->vnode)
|
||||||
|
{
|
||||||
|
sfd = file->vnode->data;
|
||||||
|
|
||||||
|
rt_poll_add(&sfd->signalfd_queue, req);
|
||||||
|
signalfd_add_notify(sfd);
|
||||||
|
|
||||||
|
rt_mutex_take(&sfd->lock, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
|
if (sfd->tick)
|
||||||
|
events |= POLLIN;
|
||||||
|
|
||||||
|
sfd->tick = 0;
|
||||||
|
rt_mutex_release(&sfd->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
return events;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifndef RT_USING_DFS_V2
|
||||||
|
static ssize_t signalfd_read(struct dfs_file *file, void *buf, size_t count)
|
||||||
|
#else
|
||||||
|
static ssize_t signalfd_read(struct dfs_file *file, void *buf, size_t count, off_t *pos)
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
struct rt_signalfd_ctx *sfd;
|
||||||
|
struct signalfd_siginfo *buffer;
|
||||||
|
rt_err_t ret = -1;
|
||||||
|
|
||||||
|
if (sizeof(struct signalfd_siginfo) > count)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
buffer = (struct signalfd_siginfo *)buf;
|
||||||
|
|
||||||
|
if (file->vnode)
|
||||||
|
{
|
||||||
|
sfd = file->vnode->data;
|
||||||
|
|
||||||
|
signalfd_add_notify(sfd);
|
||||||
|
|
||||||
|
rt_wqueue_wait(&sfd->signalfd_queue, 0, RT_WAITING_FOREVER);
|
||||||
|
rt_mutex_take(&sfd->lock, RT_WAITING_FOREVER);
|
||||||
|
sfd->tick = 1;
|
||||||
|
rt_mutex_release(&sfd->lock);
|
||||||
|
|
||||||
|
buffer->ssi_signo = sfd->info.si_signo;
|
||||||
|
buffer->ssi_code = sfd->info.si_code;
|
||||||
|
|
||||||
|
ret = sizeof(struct signalfd_siginfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void signalfd_callback(rt_wqueue_t *signalfd_queue, int signum)
|
||||||
|
{
|
||||||
|
struct rt_signalfd_ctx *sfd;
|
||||||
|
|
||||||
|
sfd = rt_container_of(signalfd_queue, struct rt_signalfd_ctx, signalfd_queue);
|
||||||
|
|
||||||
|
if (sfd)
|
||||||
|
{
|
||||||
|
for (int sig = 1; sig < NSIG; sig++)
|
||||||
|
{
|
||||||
|
if (sigismember(&sfd->sigmask, signum))
|
||||||
|
{
|
||||||
|
rt_mutex_take(&sfd->lock, RT_WAITING_FOREVER);
|
||||||
|
sfd->tick = 1;
|
||||||
|
sfd->info.si_signo = signum;
|
||||||
|
rt_mutex_release(&sfd->lock);
|
||||||
|
rt_wqueue_wakeup(signalfd_queue, (void*)POLLIN);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int signalfd_add_notify(struct rt_signalfd_ctx *sfd)
|
||||||
|
{
|
||||||
|
struct rt_lwp_notify *lwp_notify;
|
||||||
|
rt_err_t ret = -1;
|
||||||
|
rt_slist_t *node;
|
||||||
|
int is_lwp = 0;
|
||||||
|
|
||||||
|
rt_mutex_take(&sfd->lock, RT_WAITING_FOREVER);
|
||||||
|
|
||||||
|
for (int i = 0; i < is_head_init; i++)
|
||||||
|
{
|
||||||
|
if (sfd->lwp[i])
|
||||||
|
{
|
||||||
|
if (sfd->lwp[i] == lwp_self())
|
||||||
|
{
|
||||||
|
is_lwp = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_lwp == 0)
|
||||||
|
{
|
||||||
|
sfd->lwp[is_head_init] = lwp_self();
|
||||||
|
|
||||||
|
if (is_head_init == 0)
|
||||||
|
{
|
||||||
|
rt_slist_init(&sfd->lwp[is_head_init]->signalfd_notify_head);
|
||||||
|
}
|
||||||
|
|
||||||
|
lwp_notify = (struct rt_lwp_notify *)rt_malloc(sizeof(struct rt_lwp_notify));
|
||||||
|
if (lwp_notify)
|
||||||
|
{
|
||||||
|
lwp_notify->notify = signalfd_callback;
|
||||||
|
lwp_notify->signalfd_queue = &sfd->signalfd_queue;
|
||||||
|
rt_slist_append(&sfd->lwp[is_head_init]->signalfd_notify_head, &(lwp_notify->list_node));
|
||||||
|
|
||||||
|
is_head_init ++;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_slist_for_each(node, &sfd->lwp[is_head_init]->signalfd_notify_head)
|
||||||
|
{
|
||||||
|
struct rt_lwp_notify *n = rt_slist_entry(node, struct rt_lwp_notify, list_node);
|
||||||
|
rt_slist_remove(&sfd->lwp[is_head_init]->signalfd_notify_head, &n->list_node);
|
||||||
|
rt_free(n);
|
||||||
|
}
|
||||||
|
rt_set_errno(ENOMEM);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rt_mutex_release(&sfd->lock);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int signalfd_do(int fd, const sigset_t *mask, int flags)
|
||||||
|
{
|
||||||
|
struct dfs_file *df;
|
||||||
|
struct rt_signalfd_ctx *sfd;
|
||||||
|
rt_err_t ret = 0;
|
||||||
|
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
fd = fd_new();
|
||||||
|
if (fd < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
ret = fd;
|
||||||
|
df = fd_get(fd);
|
||||||
|
|
||||||
|
if (df)
|
||||||
|
{
|
||||||
|
sfd = (struct rt_signalfd_ctx *)rt_malloc(sizeof(struct rt_signalfd_ctx));
|
||||||
|
if (sfd)
|
||||||
|
{
|
||||||
|
df->vnode = (struct dfs_vnode *)rt_malloc(sizeof(struct dfs_vnode));
|
||||||
|
if (df->vnode)
|
||||||
|
{
|
||||||
|
dfs_vnode_init(df->vnode, FT_REGULAR, &signalfd_fops);
|
||||||
|
df->vnode->data = sfd;
|
||||||
|
|
||||||
|
for (int i = 0; i < is_head_init; i++)
|
||||||
|
{
|
||||||
|
sfd->lwp[i] = RT_NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
sigemptyset(&sfd->sigmask);
|
||||||
|
memcpy(&sfd->sigmask, mask, sizeof(sigset_t));
|
||||||
|
|
||||||
|
rt_mutex_init(&sfd->lock, SIGNALFD_MUTEX_NAME, RT_IPC_FLAG_FIFO);
|
||||||
|
rt_wqueue_init(&sfd->signalfd_queue);
|
||||||
|
|
||||||
|
if (signalfd_add_notify(sfd) < 0)
|
||||||
|
{
|
||||||
|
is_head_init = 0;
|
||||||
|
fd_release(fd);
|
||||||
|
rt_free(sfd);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
sfd->tick = 0;
|
||||||
|
|
||||||
|
df->flags |= flags;
|
||||||
|
|
||||||
|
#ifdef RT_USING_DFS_V2
|
||||||
|
df->fops = &signalfd_fops;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd_release(fd);
|
||||||
|
rt_free(sfd);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd_release(fd);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fd_release(fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
df = fd_get(fd);
|
||||||
|
if (df)
|
||||||
|
{
|
||||||
|
sfd = df->vnode->data;
|
||||||
|
df->flags = flags;
|
||||||
|
sigemptyset(&sfd->sigmask);
|
||||||
|
memcpy(&sfd->sigmask, mask, sizeof(sigset_t));
|
||||||
|
ret = fd;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
rt_set_errno(EBADF);
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int signalfd(int fd, const sigset_t *mask, int flags)
|
||||||
|
{
|
||||||
|
return signalfd_do(fd, mask, flags);
|
||||||
|
}
|
@ -68,6 +68,13 @@ struct rt_lwp_objs
|
|||||||
struct rt_mem_obj mem_obj;
|
struct rt_mem_obj mem_obj;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct rt_lwp_notify
|
||||||
|
{
|
||||||
|
void (*notify)(rt_wqueue_t *signalfd_queue, int signo);
|
||||||
|
rt_wqueue_t *signalfd_queue;
|
||||||
|
rt_slist_t list_node;
|
||||||
|
};
|
||||||
|
|
||||||
struct rt_lwp
|
struct rt_lwp
|
||||||
{
|
{
|
||||||
#ifdef ARCH_MM_MMU
|
#ifdef ARCH_MM_MMU
|
||||||
@ -131,6 +138,8 @@ struct rt_lwp
|
|||||||
int debug;
|
int debug;
|
||||||
uint32_t bak_first_ins;
|
uint32_t bak_first_ins;
|
||||||
|
|
||||||
|
rt_slist_t signalfd_notify_head;
|
||||||
|
|
||||||
#ifdef LWP_ENABLE_ASID
|
#ifdef LWP_ENABLE_ASID
|
||||||
uint64_t generation;
|
uint64_t generation;
|
||||||
unsigned int asid;
|
unsigned int asid;
|
||||||
|
@ -392,6 +392,20 @@ void lwp_sigqueue_clear(lwp_sigqueue_t sigq)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lwp_signal_notify(rt_slist_t *list_head, lwp_siginfo_t siginfo)
|
||||||
|
{
|
||||||
|
rt_slist_t *node;
|
||||||
|
|
||||||
|
rt_slist_for_each(node, list_head)
|
||||||
|
{
|
||||||
|
struct rt_lwp_notify *n = rt_slist_entry(node, struct rt_lwp_notify, list_node);
|
||||||
|
if (n->notify)
|
||||||
|
{
|
||||||
|
n->notify(n->signalfd_queue, siginfo->ksiginfo.signo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rt_err_t lwp_signal_init(struct lwp_signal *sig)
|
rt_err_t lwp_signal_init(struct lwp_signal *sig)
|
||||||
{
|
{
|
||||||
rt_err_t rc;
|
rt_err_t rc;
|
||||||
@ -704,6 +718,7 @@ rt_err_t lwp_signal_kill(struct rt_lwp *lwp, long signo, long code, long value)
|
|||||||
{
|
{
|
||||||
need_schedule = _siginfo_deliver_to_lwp(lwp, siginfo);
|
need_schedule = _siginfo_deliver_to_lwp(lwp, siginfo);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
lwp_signal_notify(&lwp->signalfd_notify_head, siginfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -856,6 +871,7 @@ rt_err_t lwp_thread_signal_kill(rt_thread_t thread, long signo, long code, long
|
|||||||
{
|
{
|
||||||
need_schedule = _siginfo_deliver_to_thread(thread, siginfo);
|
need_schedule = _siginfo_deliver_to_thread(thread, siginfo);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
lwp_signal_notify(&lwp->signalfd_notify_head, siginfo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -53,6 +53,10 @@
|
|||||||
#include <stdio.h> /* rename() */
|
#include <stdio.h> /* rename() */
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <sys/statfs.h> /* statfs() */
|
#include <sys/statfs.h> /* statfs() */
|
||||||
|
#include <sys/timerfd.h>
|
||||||
|
#ifdef RT_USING_MUSLLIBC
|
||||||
|
#include <sys/signalfd.h>
|
||||||
|
#endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mqueue.h"
|
#include "mqueue.h"
|
||||||
@ -5416,6 +5420,15 @@ sysret_t sys_epoll_pwait(int fd,
|
|||||||
return (ret < 0 ? GET_ERRNO() : ret);
|
return (ret < 0 ? GET_ERRNO() : ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sysret_t sys_ftruncate(int fd, off_t length)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = ftruncate(fd, length);
|
||||||
|
|
||||||
|
return (ret < 0 ? GET_ERRNO() : ret);
|
||||||
|
}
|
||||||
|
|
||||||
sysret_t sys_chmod(const char *fileName, mode_t mode)
|
sysret_t sys_chmod(const char *fileName, mode_t mode)
|
||||||
{
|
{
|
||||||
char *copy_fileName;
|
char *copy_fileName;
|
||||||
@ -5563,6 +5576,54 @@ ssize_t sys_pwrite64(int fd, void *buf, int size, off_t offset)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
sysret_t sys_timerfd_create(int clockid, int flags)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysret_t sys_timerfd_settime(int fd, int flags, const struct itimerspec *new, struct itimerspec *old)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysret_t sys_timerfd_gettime(int fd, struct itimerspec *cur)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
sysret_t sys_signalfd(int fd, const sigset_t *mask, int flags)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
sigset_t *kmask = RT_NULL;
|
||||||
|
|
||||||
|
#ifdef RT_USING_MUSLLIBC
|
||||||
|
if (mask == RT_NULL)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!lwp_user_accessable((void *)mask, sizeof(struct itimerspec)))
|
||||||
|
{
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
|
||||||
|
kmask = kmem_get(sizeof(*kmask));
|
||||||
|
|
||||||
|
if (kmask)
|
||||||
|
{
|
||||||
|
lwp_get_from_user(kmask, (void *)mask, sizeof(*kmask));
|
||||||
|
ret = signalfd(fd, mask, flags);
|
||||||
|
lwp_put_to_user((void *)mask, kmask, sizeof(*kmask));
|
||||||
|
kmem_put(kmask);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return (ret < 0 ? GET_ERRNO() : ret);
|
||||||
|
}
|
||||||
|
|
||||||
|
sysret_t sys_memfd_create()
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
const static struct rt_syscall_def func_table[] =
|
const static struct rt_syscall_def func_table[] =
|
||||||
{
|
{
|
||||||
SYSCALL_SIGN(sys_exit), /* 01 */
|
SYSCALL_SIGN(sys_exit), /* 01 */
|
||||||
@ -5798,6 +5859,13 @@ const static struct rt_syscall_def func_table[] =
|
|||||||
SYSCALL_SIGN(sys_epoll_create1),
|
SYSCALL_SIGN(sys_epoll_create1),
|
||||||
SYSCALL_SIGN(sys_epoll_ctl),
|
SYSCALL_SIGN(sys_epoll_ctl),
|
||||||
SYSCALL_SIGN(sys_epoll_pwait),
|
SYSCALL_SIGN(sys_epoll_pwait),
|
||||||
|
SYSCALL_SIGN(sys_notimpl), /* 195 */
|
||||||
|
SYSCALL_SIGN(sys_timerfd_create),
|
||||||
|
SYSCALL_SIGN(sys_timerfd_settime),
|
||||||
|
SYSCALL_SIGN(sys_timerfd_gettime),
|
||||||
|
SYSCALL_SIGN(sys_signalfd),
|
||||||
|
SYSCALL_SIGN(sys_memfd_create), /* 200 */
|
||||||
|
SYSCALL_SIGN(sys_ftruncate),
|
||||||
};
|
};
|
||||||
|
|
||||||
const void *lwp_get_sys_api(rt_uint32_t number)
|
const void *lwp_get_sys_api(rt_uint32_t number)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user