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