Skip to content

Commit 944f3d0

Browse files
polarvidRbb666
authored andcommitted
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 <[email protected]>
1 parent 972931c commit 944f3d0

File tree

8 files changed

+117
-7
lines changed

8 files changed

+117
-7
lines changed

components/dfs/dfs_v2/include/dfs_mnt.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ rt_bool_t dfs_mnt_has_child_mnt(struct dfs_mnt *mnt, const char* fullpath);
6464

6565
int dfs_mnt_foreach(struct dfs_mnt* (*func)(struct dfs_mnt *mnt, void *parameter), void *parameter);
6666

67+
typedef void (*dfs_mnt_umnt_cb_t)(struct dfs_mnt *mnt);
68+
RT_OBJECT_HOOKLIST_DECLARE(dfs_mnt_umnt_cb_t, dfs_mnt_umnt);
69+
6770
#ifdef __cplusplus
6871
}
6972
#endif

components/dfs/dfs_v2/src/dfs_mnt.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121

2222
static struct dfs_mnt *_root_mnt = RT_NULL;
2323

24+
RT_OBJECT_HOOKLIST_DEFINE(dfs_mnt_umnt);
25+
2426
/*
2527
* mnt tree structure
2628
*
@@ -257,6 +259,8 @@ int dfs_mnt_unref(struct dfs_mnt* mnt)
257259
if (mnt->flags & MNT_IS_UMOUNT)
258260
{
259261
mnt->fs_ops->umount(mnt);
262+
263+
RT_OBJECT_HOOKLIST_CALL(dfs_mnt_umnt, (mnt));
260264
}
261265

262266
/* free full path */

components/lwp/libc_musl.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,15 @@
1111
#ifndef __LIBC_MUSL_H__
1212
#define __LIBC_MUSL_H__
1313

14+
/* from reboot.h */
15+
#define RB_AUTOBOOT 0x01234567
16+
#define RB_HALT_SYSTEM 0xcdef0123
17+
#define RB_ENABLE_CAD 0x89abcdef
18+
#define RB_DISABLE_CAD 0
19+
#define RB_POWER_OFF 0x4321fedc
20+
#define RB_SW_SUSPEND 0xd000fce2
21+
#define RB_KEXEC 0x45584543
22+
1423
/* from internal/futex.h */
1524

1625
#define FUTEX_WAIT 0

components/lwp/lwp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,8 @@ int lwp_session_set_foreground(rt_session_t session, pid_t pgid);
340340
/* complete the job control related bussiness on process exit */
341341
void lwp_jobctrl_on_exit(struct rt_lwp *lwp);
342342

343+
sysret_t lwp_teardown(struct rt_lwp *lwp, void (*cb)(void));
344+
343345
#ifdef __cplusplus
344346
}
345347
#endif

components/lwp/lwp_pid.c

Lines changed: 33 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,30 @@ static int lwp_pid_ary_alloced = 0;
6969
static struct lwp_avl_struct *lwp_pid_root = RT_NULL;
7070
static pid_t current_pid = 0;
7171
static struct rt_mutex pid_mtx;
72+
static struct rt_wqueue _pid_emptyq;
7273

7374
int lwp_pid_init(void)
7475
{
76+
rt_wqueue_init(&_pid_emptyq);
7577
rt_mutex_init(&pid_mtx, "pidmtx", RT_IPC_FLAG_PRIO);
7678
return 0;
7779
}
7880

81+
int lwp_pid_wait_for_empty(int wait_flags, rt_tick_t to)
82+
{
83+
int error;
84+
85+
if (wait_flags == RT_INTERRUPTIBLE)
86+
{
87+
error = rt_wqueue_wait_interruptible(&_pid_emptyq, 0, to);
88+
}
89+
else
90+
{
91+
error = rt_wqueue_wait_killable(&_pid_emptyq, 0, to);
92+
}
93+
return error;
94+
}
95+
7996
void lwp_pid_lock_take(void)
8097
{
8198
LWP_DEF_RETURN_CODE(rc);
@@ -211,7 +228,15 @@ void lwp_pid_put(struct rt_lwp *lwp)
211228

212229
lwp_pid_lock_take();
213230
lwp_pid_put_locked(lwp->pid);
214-
lwp_pid_lock_release();
231+
if (lwp_pid_root == AVL_EMPTY)
232+
{
233+
rt_wqueue_wakeup_all(&_pid_emptyq, RT_NULL);
234+
/* refuse any new pid allocation now */
235+
}
236+
else
237+
{
238+
lwp_pid_lock_release();
239+
}
215240

216241
/* reset pid field */
217242
lwp->pid = 0;
@@ -1539,6 +1564,7 @@ static void _notify_parent(rt_lwp_t lwp)
15391564

15401565
static void _resr_cleanup(struct rt_lwp *lwp)
15411566
{
1567+
int need_cleanup_pid = RT_FALSE;
15421568
lwp_jobctrl_on_exit(lwp);
15431569

15441570
LWP_LOCK(lwp);
@@ -1608,7 +1634,7 @@ static void _resr_cleanup(struct rt_lwp *lwp)
16081634
* if process is orphan, it doesn't have parent to do the recycling.
16091635
* Otherwise, its parent had setup a flag to mask out recycling event
16101636
*/
1611-
lwp_pid_put(lwp);
1637+
need_cleanup_pid = RT_TRUE;
16121638
}
16131639

16141640
LWP_LOCK(lwp);
@@ -1628,6 +1654,11 @@ static void _resr_cleanup(struct rt_lwp *lwp)
16281654
{
16291655
LWP_UNLOCK(lwp);
16301656
}
1657+
1658+
if (need_cleanup_pid)
1659+
{
1660+
lwp_pid_put(lwp);
1661+
}
16311662
}
16321663

16331664
static int _lwp_setaffinity(int tid, int cpu)

components/lwp/lwp_pid.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ struct rt_lwp;
2626

2727
struct lwp_avl_struct *lwp_get_pid_ary(void);
2828
int lwp_pid_init(void);
29-
29+
int lwp_pid_wait_for_empty(int wait_flags, rt_tick_t to);
3030
int lwp_pid_for_each(int (*cb)(pid_t pid, void *data), void *data);
3131
void lwp_pid_put(struct rt_lwp *lwp);
3232
void lwp_pid_lock_take(void);

components/lwp/lwp_runtime.c

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,53 @@ static int lwp_startup(void)
109109
return error;
110110
}
111111
INIT_APP_EXPORT(lwp_startup);
112+
113+
/* don't use heap for safety */
114+
static struct rt_work _teardown_work;
115+
116+
#define INIT_PID 1
117+
static void _teardown_entry(struct rt_work *work, void *work_data)
118+
{
119+
int error;
120+
void (*cb_on_reboot)(void) = work_data;
121+
122+
/* cleanup of process */
123+
do
124+
{
125+
error = lwp_pid_wait_for_empty(RT_KILLABLE, RT_WAITING_FOREVER);
126+
}
127+
while (error);
128+
LOG_I("All processes exited");
129+
130+
cb_on_reboot();
131+
return;
132+
}
133+
134+
static int _get_parent_pid(struct rt_lwp *lwp)
135+
{
136+
return lwp->parent ? lwp->parent->pid : 0;
137+
}
138+
139+
/* reverse operation of lwp_startup() */
140+
sysret_t lwp_teardown(struct rt_lwp *lwp, void (*cb)(void))
141+
{
142+
struct rt_work *work;
143+
144+
if (lwp->pid != INIT_PID && _get_parent_pid(lwp) != INIT_PID)
145+
{
146+
/* The calling process has insufficient privilege */
147+
return -EPERM;
148+
}
149+
150+
work = &_teardown_work;
151+
rt_work_init(work, _teardown_entry, cb);
152+
153+
#define SOME_DELAY (RT_TICK_PER_SECOND / 10) /* allow idle to cleanup resource */
154+
rt_work_submit(work, SOME_DELAY);
155+
156+
lwp_exit(lwp, LWP_CREATE_STAT_EXIT(EXIT_SUCCESS));
157+
158+
/* never return */
159+
RT_ASSERT(0);
160+
return 0;
161+
}

components/lwp/lwp_syscall.c

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6171,16 +6171,27 @@ sysret_t sys_chown(const char *pathname, uid_t owner, gid_t group)
61716171
return (ret < 0 ? GET_ERRNO() : ret);
61726172
}
61736173

6174-
#include <sys/reboot.h>
6175-
sysret_t sys_reboot(int magic, int magic2, int type)
6174+
#ifndef LWP_USING_RUNTIME
6175+
sysret_t lwp_teardown(struct rt_lwp *lwp, void (*cb)(void))
6176+
{
6177+
/* if no LWP_USING_RUNTIME configured */
6178+
return -ENOSYS;
6179+
}
6180+
#endif
6181+
6182+
sysret_t sys_reboot(int magic, int magic2, int type, void *arg)
61766183
{
61776184
sysret_t rc;
61786185
switch (type)
61796186
{
6180-
/* TODO add software poweroff protocols */
6187+
/* Hardware reset */
61816188
case RB_AUTOBOOT:
6189+
rc = lwp_teardown(lwp_self(), rt_hw_cpu_reset);
6190+
break;
6191+
6192+
/* Stop system and switch power off */
61826193
case RB_POWER_OFF:
6183-
rt_hw_cpu_reset();
6194+
rc = lwp_teardown(lwp_self(), rt_hw_cpu_shutdown);
61846195
break;
61856196
default:
61866197
rc = -ENOSYS;

0 commit comments

Comments
 (0)