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