Serenity Operating System
1/*
2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org>
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice, this
9 * list of conditions and the following disclaimer.
10 *
11 * 2. Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26
27#ifdef __serenity__
28#include <Kernel/Syscall.h>
29#endif
30#include <errno.h>
31#include <serenity.h>
32
33#ifdef __OpenBSD__
34#include <AK/Assertions.h>
35#include <err.h>
36#include <limits.h>
37#include <sys/shm.h>
38#include <sys/mman.h>
39
40#define EMAXERRNO ELAST
41#endif
42
43extern "C" {
44
45#ifdef __serenity__
46int module_load(const char* path, size_t path_length)
47{
48 int rc = syscall(SC_module_load, path, path_length);
49 __RETURN_WITH_ERRNO(rc, rc, -1);
50}
51
52int module_unload(const char* name, size_t name_length)
53{
54 int rc = syscall(SC_module_unload, name, name_length);
55 __RETURN_WITH_ERRNO(rc, rc, -1);
56}
57
58int profiling_enable(pid_t pid)
59{
60 int rc = syscall(SC_profiling_enable, pid);
61 __RETURN_WITH_ERRNO(rc, rc, -1);
62}
63
64int profiling_disable(pid_t pid)
65{
66 int rc = syscall(SC_profiling_disable, pid);
67 __RETURN_WITH_ERRNO(rc, rc, -1);
68}
69
70int set_thread_boost(int tid, int amount)
71{
72 int rc = syscall(SC_set_thread_boost, tid, amount);
73 __RETURN_WITH_ERRNO(rc, rc, -1);
74}
75
76int set_process_boost(int tid, int amount)
77{
78 int rc = syscall(SC_set_process_boost, tid, amount);
79 __RETURN_WITH_ERRNO(rc, rc, -1);
80}
81
82int futex(int32_t* userspace_address, int futex_op, int32_t value, const struct timespec* timeout)
83{
84 Syscall::SC_futex_params params { userspace_address, futex_op, value, timeout };
85 int rc = syscall(SC_futex, ¶ms);
86 __RETURN_WITH_ERRNO(rc, rc, -1);
87}
88
89int purge(int mode)
90{
91 int rc = syscall(SC_purge, mode);
92 __RETURN_WITH_ERRNO(rc, rc, -1);
93}
94
95#else
96
97int module_load(const char* path, size_t path_length)
98{
99 (void)path;
100 (void)path_length;
101 return -ENOTSUP;
102}
103
104int module_unload(const char* name, size_t name_length)
105{
106 (void)name;
107 (void)name_length;
108 return -ENOTSUP;
109}
110
111int profiling_enable(pid_t pid)
112{
113 (void)pid;
114 return -ENOTSUP;
115}
116
117int profiling_disable(pid_t pid)
118{
119 (void)pid;
120 return -ENOTSUP;
121}
122
123int set_process_boost(int tid, int amount)
124{
125 /* TODO: use nice(3)? */
126 (void)tid;
127 (void)amount;
128 return 0;
129}
130
131int shbuf_create(int size, void** buffer)
132{
133 int key, id = -1;
134
135 for (key = 1; key < INT_MAX; key++) {
136 id = shmget(key, size, IPC_CREAT | IPC_EXCL | 0600);
137 if (id != -1) {
138 *buffer = shmat(id, 0, 0);
139 if (*buffer == (void *)-1) {
140 perror("shmat");
141 ASSERT_NOT_REACHED();
142 }
143 warnx("%d: shbuf_create = shm key %d, id %d", getpid(), key, id);
144 break;
145 }
146 }
147
148 if (id == -1) {
149 perror("shmget: exhausted");
150 ASSERT_NOT_REACHED();
151 }
152
153 return key;
154}
155
156int shbuf_allow_pid(int shbuf_id, pid_t peer_pid)
157{
158 // XXX: non-serenity doesn't support this, but processes expect to be able
159 // to read once this is called
160 warnx("%d: %s(%d, %d) not implemented, allowing all", getpid(), __func__,
161 shbuf_id, peer_pid);
162 shbuf_allow_all(shbuf_id);
163 return 0;
164}
165
166int shbuf_allow_all(int shbuf_id)
167{
168 struct shmid_ds ds;
169 int id = shmget(shbuf_id, 0, 0);
170 if (id == -1)
171 return -1;
172 if (shmctl(id, IPC_STAT, &ds) == -1)
173 return -1;
174 ds.shm_perm.mode = 0666;
175 return shmctl(id, IPC_SET, &ds);
176}
177
178void* shbuf_get(int shbuf_id, __attribute__((unused)) size_t *size)
179{
180 int id = shmget(shbuf_id, 0, 0);
181 if (id == -1) {
182 warn("%d: shbuf_get(%d) failed", getpid(), shbuf_id);
183 errno = -id;
184 return (void*)-1;
185 }
186 void *j = shmat(id, 0, 0);
187 if (j == (void *)-1)
188 warn("%d: shmget(%d) = %d, but shmat failed", getpid(), shbuf_id, id);
189 return j;
190}
191
192int shbuf_release(int shbuf_id)
193{
194 int id = shmget(shbuf_id, 0, 0);
195 if (id == -1)
196 return -1;
197 return shmctl(id, IPC_RMID, NULL);
198}
199
200int shbuf_get_size(int shbuf_id)
201{
202 struct shmid_ds ds;
203 int id = shmget(shbuf_id, 0, 0);
204 if (id == -1)
205 return -1;
206 if (shmctl(id, IPC_STAT, &ds) == -1)
207 return 0;
208 return ds.shm_segsz;
209}
210
211int shbuf_seal(int shbuf_id)
212{
213 struct shmid_ds ds;
214 int id = shmget(shbuf_id, 0, 0);
215 if (id == -1)
216 return -1;
217 if (shmctl(id, IPC_STAT, &ds) == -1)
218 return -1;
219 ds.shm_perm.mode &= 0755; // remove group/world write
220 return shmctl(id, IPC_SET, &ds);
221}
222
223
224#endif
225
226
227}