lwp_signal.c 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. /*
  2. * Copyright (c) 2006-2020, RT-Thread Development Team
  3. *
  4. * SPDX-License-Identifier: Apache-2.0
  5. *
  6. * Change Logs:
  7. * Date Author Notes
  8. * 2019-11-12 Jesven first version
  9. */
  10. #include <rthw.h>
  11. #include <rtthread.h>
  12. #include "lwp.h"
  13. #include "lwp_arch.h"
  14. #include "sys/signal.h"
  15. rt_inline void lwp_sigaddset(lwp_sigset_t *set, int _sig)
  16. {
  17. unsigned long sig = _sig - 1;
  18. if (_LWP_NSIG_WORDS == 1)
  19. {
  20. set->sig[0] |= 1UL << sig;
  21. }
  22. else
  23. {
  24. set->sig[sig / _LWP_NSIG_BPW] |= 1UL << (sig % _LWP_NSIG_BPW);
  25. }
  26. }
  27. rt_inline void lwp_sigdelset(lwp_sigset_t *set, int _sig)
  28. {
  29. unsigned long sig = _sig - 1;
  30. if (_LWP_NSIG_WORDS == 1)
  31. {
  32. set->sig[0] &= ~(1UL << sig);
  33. }
  34. else
  35. {
  36. set->sig[sig / _LWP_NSIG_BPW] &= ~(1UL << (sig % _LWP_NSIG_BPW));
  37. }
  38. }
  39. rt_inline int lwp_sigisemptyset(lwp_sigset_t *set)
  40. {
  41. switch (_LWP_NSIG_WORDS)
  42. {
  43. case 4:
  44. return (set->sig[3] | set->sig[2] |
  45. set->sig[1] | set->sig[0]) == 0;
  46. case 2:
  47. return (set->sig[1] | set->sig[0]) == 0;
  48. case 1:
  49. return set->sig[0] == 0;
  50. default:
  51. return 1;
  52. }
  53. }
  54. rt_inline int lwp_sigismember(lwp_sigset_t *set, int _sig)
  55. {
  56. unsigned long sig = _sig - 1;
  57. if (_LWP_NSIG_WORDS == 1)
  58. {
  59. return 1 & (set->sig[0] >> sig);
  60. }
  61. else
  62. {
  63. return 1 & (set->sig[sig / _LWP_NSIG_BPW] >> (sig % _LWP_NSIG_BPW));
  64. }
  65. }
  66. rt_inline int next_signal(lwp_sigset_t *pending, lwp_sigset_t *mask)
  67. {
  68. unsigned long i, *s, *m, x;
  69. int sig = 0;
  70. s = pending->sig;
  71. m = mask->sig;
  72. x = *s & ~*m;
  73. if (x)
  74. {
  75. sig = rt_hw_ffz(~x) + 1;
  76. return sig;
  77. }
  78. switch (_LWP_NSIG_WORDS)
  79. {
  80. default:
  81. for (i = 1; i < _LWP_NSIG_WORDS; ++i)
  82. {
  83. x = *++s &~ *++m;
  84. if (!x)
  85. continue;
  86. sig = rt_hw_ffz(~x) + i*_LWP_NSIG_BPW + 1;
  87. break;
  88. }
  89. break;
  90. case 2:
  91. x = s[1] &~ m[1];
  92. if (!x)
  93. break;
  94. sig = rt_hw_ffz(~x) + _LWP_NSIG_BPW + 1;
  95. break;
  96. case 1:
  97. /* Nothing to do */
  98. break;
  99. }
  100. return sig;
  101. }
  102. int lwp_suspend_sigcheck(rt_thread_t thread, int suspend_flag)
  103. {
  104. struct rt_lwp *lwp = (struct rt_lwp*)thread->lwp;
  105. int ret = 0;
  106. switch (suspend_flag)
  107. {
  108. case RT_INTERRUPTIBLE:
  109. if (!lwp_sigisemptyset(&thread->signal))
  110. {
  111. break;
  112. }
  113. if (thread->lwp && !lwp_sigisemptyset(&lwp->signal))
  114. {
  115. break;
  116. }
  117. ret = 1;
  118. break;
  119. case RT_KILLABLE:
  120. if (lwp_sigismember(&thread->signal, SIGKILL))
  121. {
  122. break;
  123. }
  124. if (thread->lwp && lwp_sigismember(&lwp->signal, SIGKILL))
  125. {
  126. break;
  127. }
  128. ret = 1;
  129. break;
  130. case RT_UNINTERRUPTIBLE:
  131. ret = 1;
  132. break;
  133. default:
  134. RT_ASSERT(0);
  135. break;
  136. }
  137. return ret;
  138. }
  139. int lwp_signal_check(void)
  140. {
  141. rt_base_t level;
  142. struct rt_thread *thread;
  143. struct rt_lwp *lwp;
  144. uint32_t have_signal = 0;
  145. level = rt_hw_interrupt_disable();
  146. thread = rt_thread_self();
  147. if (thread->signal_in_process)
  148. {
  149. goto out;
  150. }
  151. lwp = (struct rt_lwp*)thread->lwp;
  152. if (lwp->signal_in_process)
  153. {
  154. goto out;
  155. }
  156. have_signal = !lwp_sigisemptyset(&thread->signal);
  157. if (have_signal)
  158. {
  159. thread->signal_in_process = 1;
  160. goto out;
  161. }
  162. have_signal = !lwp_sigisemptyset(&lwp->signal);
  163. if (have_signal)
  164. {
  165. lwp->signal_in_process = 1;
  166. }
  167. out:
  168. rt_hw_interrupt_enable(level);
  169. return have_signal;
  170. }
  171. int lwp_signal_backup(void *user_sp, void *user_pc, void* user_flag)
  172. {
  173. rt_base_t level;
  174. struct rt_thread *thread;
  175. struct rt_lwp *lwp;
  176. int signal;
  177. level = rt_hw_interrupt_disable();
  178. thread = rt_thread_self();
  179. if (thread->signal_in_process)
  180. {
  181. thread->user_ctx.sp = user_sp;
  182. thread->user_ctx.pc = user_pc;
  183. thread->user_ctx.flag = user_flag;
  184. signal = next_signal(&thread->signal, &thread->signal_mask);
  185. RT_ASSERT(signal != 0);
  186. lwp_sigaddset(&thread->signal_mask, signal);
  187. thread->signal_mask_bak = signal;
  188. lwp_sigdelset(&thread->signal, signal);
  189. }
  190. else
  191. {
  192. lwp = (struct rt_lwp*)thread->lwp;
  193. lwp->user_ctx.sp = user_sp;
  194. lwp->user_ctx.pc = user_pc;
  195. lwp->user_ctx.flag = user_flag;
  196. signal = next_signal(&lwp->signal, &lwp->signal_mask);
  197. RT_ASSERT(signal != 0);
  198. lwp_sigaddset(&lwp->signal_mask, signal);
  199. lwp->signal_mask_bak = signal;
  200. lwp_sigdelset(&lwp->signal, signal);
  201. }
  202. rt_hw_interrupt_enable(level);
  203. return signal;
  204. }
  205. struct rt_user_context *lwp_signal_restore(void)
  206. {
  207. rt_base_t level;
  208. struct rt_thread *thread;
  209. struct rt_lwp *lwp;
  210. struct rt_user_context *ctx;
  211. level = rt_hw_interrupt_disable();
  212. thread = rt_thread_self();
  213. if (thread->signal_in_process)
  214. {
  215. ctx = &thread->user_ctx;
  216. thread->signal_in_process = 0;
  217. lwp_sigdelset(&thread->signal_mask, thread->signal_mask_bak);
  218. thread->signal_mask_bak = 0;
  219. }
  220. else
  221. {
  222. lwp = (struct rt_lwp*)thread->lwp;
  223. ctx = &lwp->user_ctx;
  224. RT_ASSERT(lwp->signal_in_process != 0);
  225. lwp->signal_in_process = 0;
  226. lwp_sigdelset(&lwp->signal_mask, lwp->signal_mask_bak);
  227. lwp->signal_mask_bak = 0;
  228. }
  229. rt_hw_interrupt_enable(level);
  230. return ctx;
  231. }
  232. rt_inline int _lwp_check_ignore(int sig)
  233. {
  234. if (sig == SIGCHLD || sig == SIGCONT)
  235. {
  236. return 1;
  237. }
  238. return 0;
  239. }
  240. void sys_exit(int value);
  241. lwp_sighandler_t lwp_sighandler_get(int sig)
  242. {
  243. lwp_sighandler_t func = RT_NULL;
  244. struct rt_lwp *lwp;
  245. rt_thread_t thread;
  246. rt_base_t level;
  247. if (sig == 0 || sig > _LWP_NSIG)
  248. {
  249. return func;
  250. }
  251. level = rt_hw_interrupt_disable();
  252. thread = rt_thread_self();
  253. #ifndef ARCH_MM_MMU
  254. if (thread->signal_in_process)
  255. {
  256. func = thread->signal_handler[sig - 1];
  257. goto out;
  258. }
  259. #endif
  260. lwp = (struct rt_lwp*)thread->lwp;
  261. func = lwp->signal_handler[sig - 1];
  262. if (!func)
  263. {
  264. if (_lwp_check_ignore(sig))
  265. {
  266. goto out;
  267. }
  268. if (lwp->signal_in_process)
  269. {
  270. lwp_terminate(lwp);
  271. }
  272. sys_exit(0);
  273. }
  274. out:
  275. rt_hw_interrupt_enable(level);
  276. if (func == (lwp_sighandler_t)SIG_IGN)
  277. {
  278. func = RT_NULL;
  279. }
  280. return func;
  281. }
  282. void lwp_sighandler_set(int sig, lwp_sighandler_t func)
  283. {
  284. rt_base_t level;
  285. if (sig == 0 || sig > _LWP_NSIG)
  286. return;
  287. if (sig == SIGKILL || sig == SIGSTOP)
  288. return;
  289. level = rt_hw_interrupt_disable();
  290. ((struct rt_lwp*)rt_thread_self()->lwp)->signal_handler[sig - 1] = func;
  291. rt_hw_interrupt_enable(level);
  292. }
  293. #ifndef ARCH_MM_MMU
  294. void lwp_thread_sighandler_set(int sig, lwp_sighandler_t func)
  295. {
  296. rt_base_t level;
  297. if (sig == 0 || sig > _LWP_NSIG)
  298. return;
  299. level = rt_hw_interrupt_disable();
  300. rt_thread_self()->signal_handler[sig - 1] = func;
  301. rt_hw_interrupt_enable(level);
  302. }
  303. #endif
  304. int lwp_sigaction(int sig, const struct lwp_sigaction *act,
  305. struct lwp_sigaction *oact, size_t sigsetsize)
  306. {
  307. rt_base_t level;
  308. struct rt_lwp *lwp;
  309. int ret = -RT_EINVAL;
  310. lwp_sigset_t newset;
  311. level = rt_hw_interrupt_disable();
  312. lwp = (struct rt_lwp*)rt_thread_self()->lwp;
  313. if (!lwp)
  314. {
  315. goto out;
  316. }
  317. if (sigsetsize != sizeof(lwp_sigset_t))
  318. {
  319. goto out;
  320. }
  321. if (!act && !oact)
  322. {
  323. goto out;
  324. }
  325. if (oact)
  326. {
  327. oact->sa_flags = lwp->sa_flags;
  328. oact->sa_mask = lwp->signal_mask;
  329. oact->sa_restorer = RT_NULL;
  330. oact->__sa_handler._sa_handler = lwp->signal_handler[sig - 1];
  331. }
  332. if (act)
  333. {
  334. lwp->sa_flags = act->sa_flags;
  335. newset = act->sa_mask;
  336. lwp_sigdelset(&newset, SIGKILL);
  337. lwp_sigdelset(&newset, SIGSTOP);
  338. lwp->signal_mask = newset;
  339. lwp_sighandler_set(sig, act->__sa_handler._sa_handler);
  340. }
  341. ret = 0;
  342. out:
  343. rt_hw_interrupt_enable(level);
  344. return ret;
  345. }
  346. rt_inline void sigorsets(lwp_sigset_t *dset, const lwp_sigset_t *set0, const lwp_sigset_t *set1)
  347. {
  348. switch (_LWP_NSIG_WORDS)
  349. {
  350. case 4:
  351. dset->sig[3] = set0->sig[3] | set1->sig[3];
  352. dset->sig[2] = set0->sig[2] | set1->sig[2];
  353. case 2:
  354. dset->sig[1] = set0->sig[1] | set1->sig[1];
  355. case 1:
  356. dset->sig[0] = set0->sig[0] | set1->sig[0];
  357. default:
  358. return;
  359. }
  360. }
  361. rt_inline void sigandsets(lwp_sigset_t *dset, const lwp_sigset_t *set0, const lwp_sigset_t *set1)
  362. {
  363. switch (_LWP_NSIG_WORDS)
  364. {
  365. case 4:
  366. dset->sig[3] = set0->sig[3] & set1->sig[3];
  367. dset->sig[2] = set0->sig[2] & set1->sig[2];
  368. case 2:
  369. dset->sig[1] = set0->sig[1] & set1->sig[1];
  370. case 1:
  371. dset->sig[0] = set0->sig[0] & set1->sig[0];
  372. default:
  373. return;
  374. }
  375. }
  376. int lwp_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset)
  377. {
  378. int ret = -1;
  379. rt_base_t level;
  380. struct rt_lwp *lwp;
  381. struct rt_thread *thread;
  382. lwp_sigset_t newset;
  383. level = rt_hw_interrupt_disable();
  384. thread = rt_thread_self();
  385. lwp = (struct rt_lwp*)thread->lwp;
  386. if (!lwp)
  387. {
  388. goto out;
  389. }
  390. if (oset)
  391. {
  392. rt_memcpy(oset, &lwp->signal_mask, sizeof(lwp_sigset_t));
  393. }
  394. if (sigset)
  395. {
  396. switch (how)
  397. {
  398. case SIG_BLOCK:
  399. sigorsets(&newset, &lwp->signal_mask, sigset);
  400. break;
  401. case SIG_UNBLOCK:
  402. sigandsets(&newset, &lwp->signal_mask, sigset);
  403. break;
  404. case SIG_SETMASK:
  405. newset = *sigset;
  406. break;
  407. default:
  408. ret = -RT_EINVAL;
  409. goto out;
  410. }
  411. lwp_sigdelset(&newset, SIGKILL);
  412. lwp_sigdelset(&newset, SIGSTOP);
  413. lwp->signal_mask = newset;
  414. }
  415. ret = 0;
  416. out:
  417. rt_hw_interrupt_enable(level);
  418. return ret;
  419. }
  420. int lwp_thread_sigprocmask(int how, const lwp_sigset_t *sigset, lwp_sigset_t *oset)
  421. {
  422. rt_base_t level;
  423. struct rt_thread *thread;
  424. lwp_sigset_t newset;
  425. level = rt_hw_interrupt_disable();
  426. thread = rt_thread_self();
  427. if (oset)
  428. {
  429. rt_memcpy(oset, &thread->signal_mask, sizeof(lwp_sigset_t));
  430. }
  431. if (sigset)
  432. {
  433. switch (how)
  434. {
  435. case SIG_BLOCK:
  436. sigorsets(&newset, &thread->signal_mask, sigset);
  437. break;
  438. case SIG_UNBLOCK:
  439. sigandsets(&newset, &thread->signal_mask, sigset);
  440. break;
  441. case SIG_SETMASK:
  442. newset = *sigset;
  443. break;
  444. default:
  445. goto out;
  446. }
  447. lwp_sigdelset(&newset, SIGKILL);
  448. lwp_sigdelset(&newset, SIGSTOP);
  449. thread->signal_mask = newset;
  450. }
  451. out:
  452. rt_hw_interrupt_enable(level);
  453. return 0;
  454. }
  455. static void _do_signal_wakeup(rt_thread_t thread, int sig)
  456. {
  457. if ((thread->stat & RT_THREAD_SUSPEND_MASK) == RT_THREAD_SUSPEND_MASK)
  458. {
  459. int need_schedule = 1;
  460. if ((thread->stat & RT_SIGNAL_COMMON_WAKEUP_MASK) != RT_SIGNAL_COMMON_WAKEUP_MASK)
  461. {
  462. rt_thread_wakeup(thread);
  463. }
  464. else if ((sig == SIGKILL) && ((thread->stat & RT_SIGNAL_KILL_WAKEUP_MASK) != RT_SIGNAL_KILL_WAKEUP_MASK))
  465. {
  466. rt_thread_wakeup(thread);
  467. }
  468. else
  469. {
  470. need_schedule = 0;
  471. }
  472. /* do schedule */
  473. if (need_schedule)
  474. {
  475. rt_schedule();
  476. }
  477. }
  478. }
  479. int lwp_kill(pid_t pid, int sig)
  480. {
  481. rt_base_t level;
  482. struct rt_lwp *lwp;
  483. int ret = -1;
  484. rt_thread_t thread;
  485. if (sig < 0 || sig >= _LWP_NSIG)
  486. {
  487. rt_set_errno(EINVAL);
  488. return ret;
  489. }
  490. level = rt_hw_interrupt_disable();
  491. lwp = lwp_from_pid(pid);
  492. if (!lwp || lwp->finish)
  493. {
  494. rt_set_errno(ESRCH);
  495. goto out;
  496. }
  497. if (sig)
  498. {
  499. /* check main thread */
  500. thread = rt_list_entry(lwp->t_grp.prev, struct rt_thread, sibling);
  501. if (!lwp_sigismember(&lwp->signal_mask, sig)) /* if signal masked */
  502. {
  503. lwp_sigaddset(&lwp->signal, sig);
  504. _do_signal_wakeup(thread, sig);
  505. }
  506. }
  507. ret = 0;
  508. out:
  509. rt_hw_interrupt_enable(level);
  510. return ret;
  511. }
  512. int lwp_thread_kill(rt_thread_t thread, int sig)
  513. {
  514. rt_base_t level;
  515. int ret = -RT_EINVAL;
  516. if (!thread)
  517. {
  518. rt_set_errno(ESRCH);
  519. return ret;
  520. }
  521. if (sig < 0 || sig >= _LWP_NSIG)
  522. {
  523. rt_set_errno(EINVAL);
  524. return ret;
  525. }
  526. level = rt_hw_interrupt_disable();
  527. if (!thread->lwp)
  528. {
  529. rt_set_errno(EPERM);
  530. goto out;
  531. }
  532. if (!lwp_sigismember(&thread->signal_mask, sig)) /* if signal masked */
  533. {
  534. lwp_sigaddset(&thread->signal, sig);
  535. _do_signal_wakeup(thread, sig);
  536. }
  537. ret = 0;
  538. out:
  539. rt_hw_interrupt_enable(level);
  540. return ret;
  541. }