1 /*
2 * Copyright (c) 2023 Meta
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6 #include "posix/strsignal_table.h"
7
8 #include <errno.h>
9 #include <stdio.h>
10
11 #include <zephyr/posix/pthread.h>
12 #include <zephyr/posix/signal.h>
13
14 #define SIGNO_WORD_IDX(_signo) (_signo / BITS_PER_LONG)
15 #define SIGNO_WORD_BIT(_signo) (_signo & BIT_MASK(LOG2(BITS_PER_LONG)))
16
17 BUILD_ASSERT(CONFIG_POSIX_RTSIG_MAX >= 0);
18
signo_valid(int signo)19 static inline bool signo_valid(int signo)
20 {
21 return ((signo > 0) && (signo < _NSIG));
22 }
23
signo_is_rt(int signo)24 static inline bool signo_is_rt(int signo)
25 {
26 return ((signo >= SIGRTMIN) && (signo <= SIGRTMAX));
27 }
28
sigemptyset(sigset_t * set)29 int sigemptyset(sigset_t *set)
30 {
31 *set = (sigset_t){0};
32 return 0;
33 }
34
sigfillset(sigset_t * set)35 int sigfillset(sigset_t *set)
36 {
37 for (int i = 0; i < ARRAY_SIZE(set->sig); i++) {
38 set->sig[i] = -1;
39 }
40
41 return 0;
42 }
43
sigaddset(sigset_t * set,int signo)44 int sigaddset(sigset_t *set, int signo)
45 {
46 if (!signo_valid(signo)) {
47 errno = EINVAL;
48 return -1;
49 }
50
51 WRITE_BIT(set->sig[SIGNO_WORD_IDX(signo)], SIGNO_WORD_BIT(signo), 1);
52
53 return 0;
54 }
55
sigdelset(sigset_t * set,int signo)56 int sigdelset(sigset_t *set, int signo)
57 {
58 if (!signo_valid(signo)) {
59 errno = EINVAL;
60 return -1;
61 }
62
63 WRITE_BIT(set->sig[SIGNO_WORD_IDX(signo)], SIGNO_WORD_BIT(signo), 0);
64
65 return 0;
66 }
67
sigismember(const sigset_t * set,int signo)68 int sigismember(const sigset_t *set, int signo)
69 {
70 if (!signo_valid(signo)) {
71 errno = EINVAL;
72 return -1;
73 }
74
75 return 1 & (set->sig[SIGNO_WORD_IDX(signo)] >> SIGNO_WORD_BIT(signo));
76 }
77
strsignal(int signum)78 char *strsignal(int signum)
79 {
80 /* Using -INT_MAX here because compiler resolves INT_MIN to (-2147483647 - 1) */
81 static char buf[sizeof("RT signal -" STRINGIFY(INT_MAX))];
82
83 if (!signo_valid(signum)) {
84 errno = EINVAL;
85 return "Invalid signal";
86 }
87
88 if (signo_is_rt(signum)) {
89 snprintf(buf, sizeof(buf), "RT signal %d", signum - SIGRTMIN);
90 return buf;
91 }
92
93 if (IS_ENABLED(CONFIG_POSIX_SIGNAL_STRING_DESC)) {
94 if (strsignal_list[signum] != NULL) {
95 return (char *)strsignal_list[signum];
96 }
97 }
98
99 snprintf(buf, sizeof(buf), "Signal %d", signum);
100
101 return buf;
102 }
103
sigprocmask(int how,const sigset_t * ZRESTRICT set,sigset_t * ZRESTRICT oset)104 int sigprocmask(int how, const sigset_t *ZRESTRICT set, sigset_t *ZRESTRICT oset)
105 {
106 if (!IS_ENABLED(CONFIG_MULTITHREADING)) {
107 return pthread_sigmask(how, set, oset);
108 }
109
110 /*
111 * Until Zephyr supports processes and specifically querying the number of active threads in
112 * a process For more information, see
113 * https://pubs.opengroup.org/onlinepubs/9699919799/functions/pthread_sigmask.html
114 */
115 __ASSERT(false, "In multi-threaded environments, please use pthread_sigmask() instead of "
116 "%s()", __func__);
117
118 errno = ENOSYS;
119 return -1;
120 }
121
122 /*
123 * The functions below are provided so that conformant POSIX applications and libraries can still
124 * link.
125 */
126
alarm(unsigned int seconds)127 unsigned int alarm(unsigned int seconds)
128 {
129 ARG_UNUSED(seconds);
130 return 0;
131 }
132
kill(pid_t pid,int sig)133 int kill(pid_t pid, int sig)
134 {
135 ARG_UNUSED(pid);
136 ARG_UNUSED(sig);
137 errno = ENOSYS;
138 return -1;
139 }
140 #ifdef CONFIG_POSIX_SIGNALS_ALIAS_KILL
141 FUNC_ALIAS(kill, _kill, int);
142 #endif /* CONFIG_POSIX_SIGNALS_ALIAS_KILL */
143
pause(void)144 int pause(void)
145 {
146 errno = ENOSYS;
147 return -1;
148 }
149
sigaction(int sig,const struct sigaction * ZRESTRICT act,struct sigaction * ZRESTRICT oact)150 int sigaction(int sig, const struct sigaction *ZRESTRICT act, struct sigaction *ZRESTRICT oact)
151 {
152 ARG_UNUSED(sig);
153 ARG_UNUSED(act);
154 ARG_UNUSED(oact);
155 errno = ENOSYS;
156 return -1;
157 }
158
sigpending(sigset_t * set)159 int sigpending(sigset_t *set)
160 {
161 ARG_UNUSED(set);
162 errno = ENOSYS;
163 return -1;
164 }
165
sigsuspend(const sigset_t * sigmask)166 int sigsuspend(const sigset_t *sigmask)
167 {
168 ARG_UNUSED(sigmask);
169 errno = ENOSYS;
170 return -1;
171 }
172
sigwait(const sigset_t * ZRESTRICT set,int * ZRESTRICT sig)173 int sigwait(const sigset_t *ZRESTRICT set, int *ZRESTRICT sig)
174 {
175 ARG_UNUSED(set);
176 ARG_UNUSED(sig);
177 errno = ENOSYS;
178 return -1;
179 }
180