feat: add system reboot and process teardown support

The patch introduces support for system reboot functionality and process teardown,
allowing for a clean shutdown and unmounting of the root filesystem. This is
necessary for ensuring a proper system shutdown process, especially when dealing
with resource cleanup and ensuring that all processes have exited before system
shutdown.

Changes:
- Added `lwp_teardown()` function to handle process cleanup and system teardown.
- Introduced `lwp_pid_wait_for_empty()` to wait for process ID table emptiness
  before proceeding with shutdown.
- Updated `dfs_mnt_unref()` to trigger callbacks when unmounting a filesystem.
- Added new reboot types (`RB_AUTOBOOT`, `RB_POWER_OFF`) and implemented their
  corresponding actions, including cleanup of processes and unmounting root
  filesystem.
- Extended `sys_reboot()` to handle reboot and power off types with appropriate
  callbacks for process and filesystem teardown.
- Introduced callback mechanism for root filesystem unmount notifications.

Signed-off-by: Shell <smokewood@qq.com>
This commit is contained in:
Shell
2024-11-12 17:47:51 +08:00
committed by Rbb666
parent 972931c991
commit 944f3d05b5
8 changed files with 117 additions and 7 deletions

View File

@@ -69,13 +69,30 @@ static int lwp_pid_ary_alloced = 0;
static struct lwp_avl_struct *lwp_pid_root = RT_NULL;
static pid_t current_pid = 0;
static struct rt_mutex pid_mtx;
static struct rt_wqueue _pid_emptyq;
int lwp_pid_init(void)
{
rt_wqueue_init(&_pid_emptyq);
rt_mutex_init(&pid_mtx, "pidmtx", RT_IPC_FLAG_PRIO);
return 0;
}
int lwp_pid_wait_for_empty(int wait_flags, rt_tick_t to)
{
int error;
if (wait_flags == RT_INTERRUPTIBLE)
{
error = rt_wqueue_wait_interruptible(&_pid_emptyq, 0, to);
}
else
{
error = rt_wqueue_wait_killable(&_pid_emptyq, 0, to);
}
return error;
}
void lwp_pid_lock_take(void)
{
LWP_DEF_RETURN_CODE(rc);
@@ -211,7 +228,15 @@ void lwp_pid_put(struct rt_lwp *lwp)
lwp_pid_lock_take();
lwp_pid_put_locked(lwp->pid);
lwp_pid_lock_release();
if (lwp_pid_root == AVL_EMPTY)
{
rt_wqueue_wakeup_all(&_pid_emptyq, RT_NULL);
/* refuse any new pid allocation now */
}
else
{
lwp_pid_lock_release();
}
/* reset pid field */
lwp->pid = 0;
@@ -1539,6 +1564,7 @@ static void _notify_parent(rt_lwp_t lwp)
static void _resr_cleanup(struct rt_lwp *lwp)
{
int need_cleanup_pid = RT_FALSE;
lwp_jobctrl_on_exit(lwp);
LWP_LOCK(lwp);
@@ -1608,7 +1634,7 @@ static void _resr_cleanup(struct rt_lwp *lwp)
* if process is orphan, it doesn't have parent to do the recycling.
* Otherwise, its parent had setup a flag to mask out recycling event
*/
lwp_pid_put(lwp);
need_cleanup_pid = RT_TRUE;
}
LWP_LOCK(lwp);
@@ -1628,6 +1654,11 @@ static void _resr_cleanup(struct rt_lwp *lwp)
{
LWP_UNLOCK(lwp);
}
if (need_cleanup_pid)
{
lwp_pid_put(lwp);
}
}
static int _lwp_setaffinity(int tid, int cpu)