]> git.proxmox.com Git - rustc.git/blob - vendor/hermit-abi/src/lib.rs
New upstream version 1.61.0+dfsg1
[rustc.git] / vendor / hermit-abi / src / lib.rs
1 //! `hermit-abi` is small interface to call functions from the unikernel
2 //! [RustyHermit](https://github.com/hermitcore/libhermit-rs).
3
4 #![no_std]
5 #![allow(clippy::missing_safety_doc)]
6 #![allow(clippy::result_unit_err)]
7
8 extern crate libc;
9
10 pub mod tcplistener;
11 pub mod tcpstream;
12
13 use libc::c_void;
14
15 // sysmbols, which are part of the library operating system
16
17 extern "Rust" {
18 fn sys_secure_rand64() -> Option<u64>;
19 fn sys_secure_rand32() -> Option<u32>;
20 }
21
22 extern "C" {
23 fn sys_rand() -> u32;
24 fn sys_srand(seed: u32);
25 fn sys_get_processor_count() -> usize;
26 fn sys_malloc(size: usize, align: usize) -> *mut u8;
27 fn sys_realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8;
28 fn sys_free(ptr: *mut u8, size: usize, align: usize);
29 fn sys_init_queue(ptr: usize) -> i32;
30 fn sys_notify(id: usize, count: i32) -> i32;
31 fn sys_add_queue(id: usize, timeout_ns: i64) -> i32;
32 fn sys_wait(id: usize) -> i32;
33 fn sys_destroy_queue(id: usize) -> i32;
34 fn sys_read(fd: i32, buf: *mut u8, len: usize) -> isize;
35 fn sys_write(fd: i32, buf: *const u8, len: usize) -> isize;
36 fn sys_close(fd: i32) -> i32;
37 fn sys_sem_init(sem: *mut *const c_void, value: u32) -> i32;
38 fn sys_sem_destroy(sem: *const c_void) -> i32;
39 fn sys_sem_post(sem: *const c_void) -> i32;
40 fn sys_sem_trywait(sem: *const c_void) -> i32;
41 fn sys_sem_timedwait(sem: *const c_void, ms: u32) -> i32;
42 fn sys_recmutex_init(recmutex: *mut *const c_void) -> i32;
43 fn sys_recmutex_destroy(recmutex: *const c_void) -> i32;
44 fn sys_recmutex_lock(recmutex: *const c_void) -> i32;
45 fn sys_recmutex_unlock(recmutex: *const c_void) -> i32;
46 fn sys_getpid() -> u32;
47 fn sys_exit(arg: i32) -> !;
48 fn sys_abort() -> !;
49 fn sys_usleep(usecs: u64);
50 fn sys_spawn(
51 id: *mut Tid,
52 func: extern "C" fn(usize),
53 arg: usize,
54 prio: u8,
55 core_id: isize,
56 ) -> i32;
57 fn sys_spawn2(
58 func: extern "C" fn(usize),
59 arg: usize,
60 prio: u8,
61 stack_size: usize,
62 core_id: isize,
63 ) -> Tid;
64 fn sys_join(id: Tid) -> i32;
65 fn sys_yield();
66 fn sys_clock_gettime(clock_id: u64, tp: *mut timespec) -> i32;
67 fn sys_open(name: *const i8, flags: i32, mode: i32) -> i32;
68 fn sys_unlink(name: *const i8) -> i32;
69 fn sys_network_init() -> i32;
70 fn sys_block_current_task();
71 fn sys_wakeup_task(tid: Tid);
72 fn sys_get_priority() -> u8;
73 }
74
75 /// A thread handle type
76 pub type Tid = u32;
77
78 /// Maximum number of priorities
79 pub const NO_PRIORITIES: usize = 31;
80
81 /// Priority of a thread
82 #[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
83 pub struct Priority(u8);
84
85 impl Priority {
86 pub const fn into(self) -> u8 {
87 self.0
88 }
89
90 pub const fn from(x: u8) -> Self {
91 Priority(x)
92 }
93 }
94
95 pub const HIGH_PRIO: Priority = Priority::from(3);
96 pub const NORMAL_PRIO: Priority = Priority::from(2);
97 pub const LOW_PRIO: Priority = Priority::from(1);
98
99 /// A handle, identifying a socket
100 #[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Default, Hash)]
101 pub struct Handle(usize);
102
103 pub const NSEC_PER_SEC: u64 = 1_000_000_000;
104 pub const CLOCK_REALTIME: u64 = 1;
105 pub const CLOCK_MONOTONIC: u64 = 4;
106 pub const STDIN_FILENO: libc::c_int = 0;
107 pub const STDOUT_FILENO: libc::c_int = 1;
108 pub const STDERR_FILENO: libc::c_int = 2;
109 pub const O_RDONLY: i32 = 0o0;
110 pub const O_WRONLY: i32 = 0o1;
111 pub const O_RDWR: i32 = 0o2;
112 pub const O_CREAT: i32 = 0o100;
113 pub const O_EXCL: i32 = 0o200;
114 pub const O_TRUNC: i32 = 0o1000;
115 pub const O_APPEND: i32 = 0o2000;
116
117 /// returns true if file descriptor `fd` is a tty
118 pub fn isatty(_fd: libc::c_int) -> bool {
119 false
120 }
121
122 /// initialize the network stack
123 pub fn network_init() -> i32 {
124 unsafe { sys_network_init() }
125 }
126
127 /// `timespec` is used by `clock_gettime` to retrieve the
128 /// current time
129 #[derive(Copy, Clone, Debug)]
130 #[repr(C)]
131 pub struct timespec {
132 /// seconds
133 pub tv_sec: i64,
134 /// nanoseconds
135 pub tv_nsec: i64,
136 }
137
138 /// Internet protocol version.
139 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
140 pub enum Version {
141 Unspecified,
142 Ipv4,
143 Ipv6,
144 }
145
146 /// A four-octet IPv4 address.
147 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
148 pub struct Ipv4Address(pub [u8; 4]);
149
150 /// A sixteen-octet IPv6 address.
151 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default)]
152 pub struct Ipv6Address(pub [u8; 16]);
153
154 /// An internetworking address.
155 #[derive(Debug, Hash, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)]
156 pub enum IpAddress {
157 /// An unspecified address.
158 /// May be used as a placeholder for storage where the address is not assigned yet.
159 Unspecified,
160 /// An IPv4 address.
161 Ipv4(Ipv4Address),
162 /// An IPv6 address.
163 Ipv6(Ipv6Address),
164 }
165
166 /// determines the number of activated processors
167 #[inline(always)]
168 pub unsafe fn get_processor_count() -> usize {
169 sys_get_processor_count()
170 }
171
172 #[doc(hidden)]
173 #[inline(always)]
174 pub unsafe fn malloc(size: usize, align: usize) -> *mut u8 {
175 sys_malloc(size, align)
176 }
177
178 #[doc(hidden)]
179 #[inline(always)]
180 pub unsafe fn realloc(ptr: *mut u8, size: usize, align: usize, new_size: usize) -> *mut u8 {
181 sys_realloc(ptr, size, align, new_size)
182 }
183
184 #[doc(hidden)]
185 #[inline(always)]
186 pub unsafe fn free(ptr: *mut u8, size: usize, align: usize) {
187 sys_free(ptr, size, align)
188 }
189
190 #[inline(always)]
191 pub unsafe fn notify(id: usize, count: i32) -> i32 {
192 sys_notify(id, count)
193 }
194
195 #[doc(hidden)]
196 #[inline(always)]
197 pub unsafe fn add_queue(id: usize, timeout_ns: i64) -> i32 {
198 sys_add_queue(id, timeout_ns)
199 }
200
201 #[doc(hidden)]
202 #[inline(always)]
203 pub unsafe fn wait(id: usize) -> i32 {
204 sys_wait(id)
205 }
206
207 #[doc(hidden)]
208 #[inline(always)]
209 pub unsafe fn init_queue(id: usize) -> i32 {
210 sys_init_queue(id)
211 }
212
213 #[doc(hidden)]
214 #[inline(always)]
215 pub unsafe fn destroy_queue(id: usize) -> i32 {
216 sys_destroy_queue(id)
217 }
218
219 /// read from a file descriptor
220 ///
221 /// read() attempts to read `len` bytes of data from the object
222 /// referenced by the descriptor `fd` into the buffer pointed
223 /// to by `buf`.
224 #[inline(always)]
225 pub unsafe fn read(fd: i32, buf: *mut u8, len: usize) -> isize {
226 sys_read(fd, buf, len)
227 }
228
229 /// write to a file descriptor
230 ///
231 /// write() attempts to write `len` of data to the object
232 /// referenced by the descriptor `fd` from the
233 /// buffer pointed to by `buf`.
234 #[inline(always)]
235 pub unsafe fn write(fd: i32, buf: *const u8, len: usize) -> isize {
236 sys_write(fd, buf, len)
237 }
238
239 /// close a file descriptor
240 ///
241 /// The close() call deletes a file descriptor `fd` from the object
242 /// reference table.
243 #[inline(always)]
244 pub unsafe fn close(fd: i32) -> i32 {
245 sys_close(fd)
246 }
247
248 /// sem_init() initializes the unnamed semaphore at the address
249 /// pointed to by `sem`. The `value` argument specifies the
250 /// initial value for the semaphore.
251 #[inline(always)]
252 pub unsafe fn sem_init(sem: *mut *const c_void, value: u32) -> i32 {
253 sys_sem_init(sem, value)
254 }
255
256 /// sem_destroy() frees the unnamed semaphore at the address
257 /// pointed to by `sem`.
258 #[inline(always)]
259 pub unsafe fn sem_destroy(sem: *const c_void) -> i32 {
260 sys_sem_destroy(sem)
261 }
262
263 /// sem_post() increments the semaphore pointed to by `sem`.
264 /// If the semaphore's value consequently becomes greater
265 /// than zero, then another thread blocked in a sem_wait call
266 /// will be woken up and proceed to lock the semaphore.
267 #[inline(always)]
268 pub unsafe fn sem_post(sem: *const c_void) -> i32 {
269 sys_sem_post(sem)
270 }
271
272 /// try to decrement a semaphore
273 ///
274 /// sem_trywait() is the same as sem_timedwait(), except that
275 /// if the decrement cannot be immediately performed, then call
276 /// returns a negative value instead of blocking.
277 #[inline(always)]
278 pub unsafe fn sem_trywait(sem: *const c_void) -> i32 {
279 sys_sem_trywait(sem)
280 }
281
282 /// decrement a semaphore
283 ///
284 /// sem_timedwait() decrements the semaphore pointed to by `sem`.
285 /// If the semaphore's value is greater than zero, then the
286 /// the function returns immediately. If the semaphore currently
287 /// has the value zero, then the call blocks until either
288 /// it becomes possible to perform the decrement of the time limit
289 /// to wait for the semaphore is expired. A time limit `ms` of
290 /// means infinity waiting time.
291 #[inline(always)]
292 pub unsafe fn sem_timedwait(sem: *const c_void, ms: u32) -> i32 {
293 sys_sem_timedwait(sem, ms)
294 }
295
296 #[doc(hidden)]
297 #[inline(always)]
298 pub unsafe fn recmutex_init(recmutex: *mut *const c_void) -> i32 {
299 sys_recmutex_init(recmutex)
300 }
301
302 #[doc(hidden)]
303 #[inline(always)]
304 pub unsafe fn recmutex_destroy(recmutex: *const c_void) -> i32 {
305 sys_recmutex_destroy(recmutex)
306 }
307
308 #[doc(hidden)]
309 #[inline(always)]
310 pub unsafe fn recmutex_lock(recmutex: *const c_void) -> i32 {
311 sys_recmutex_lock(recmutex)
312 }
313
314 #[doc(hidden)]
315 #[inline(always)]
316 pub unsafe fn recmutex_unlock(recmutex: *const c_void) -> i32 {
317 sys_recmutex_unlock(recmutex)
318 }
319
320 /// Determines the id of the current thread
321 #[inline(always)]
322 pub unsafe fn getpid() -> u32 {
323 sys_getpid()
324 }
325
326 /// cause normal termination and return `arg`
327 /// to the host system
328 #[inline(always)]
329 pub unsafe fn exit(arg: i32) -> ! {
330 sys_exit(arg)
331 }
332
333 /// cause abnormal termination
334 #[inline(always)]
335 pub unsafe fn abort() -> ! {
336 sys_abort()
337 }
338
339 /// suspend execution for microsecond intervals
340 ///
341 /// The usleep() function suspends execution of the calling
342 /// thread for (at least) `usecs` microseconds.
343 #[inline(always)]
344 pub unsafe fn usleep(usecs: u64) {
345 sys_usleep(usecs)
346 }
347
348 /// spawn a new thread
349 ///
350 /// spawn() starts a new thread. The new thread starts execution
351 /// by invoking `func(usize)`; `arg` is passed as the argument
352 /// to `func`. `prio` defines the priority of the new thread,
353 /// which can be between `LOW_PRIO` and `HIGH_PRIO`.
354 /// `core_id` defines the core, where the thread is located.
355 /// A negative value give the operating system the possibility
356 /// to select the core by its own.
357 #[inline(always)]
358 pub unsafe fn spawn(
359 id: *mut Tid,
360 func: extern "C" fn(usize),
361 arg: usize,
362 prio: u8,
363 core_id: isize,
364 ) -> i32 {
365 sys_spawn(id, func, arg, prio, core_id)
366 }
367
368 /// spawn a new thread with user-specified stack size
369 ///
370 /// spawn2() starts a new thread. The new thread starts execution
371 /// by invoking `func(usize)`; `arg` is passed as the argument
372 /// to `func`. `prio` defines the priority of the new thread,
373 /// which can be between `LOW_PRIO` and `HIGH_PRIO`.
374 /// `core_id` defines the core, where the thread is located.
375 /// A negative value give the operating system the possibility
376 /// to select the core by its own.
377 /// In contrast to spawn(), spawn2() is able to define the
378 /// stack size.
379 #[inline(always)]
380 pub unsafe fn spawn2(
381 func: extern "C" fn(usize),
382 arg: usize,
383 prio: u8,
384 stack_size: usize,
385 core_id: isize,
386 ) -> Tid {
387 sys_spawn2(func, arg, prio, stack_size, core_id)
388 }
389
390 /// join with a terminated thread
391 ///
392 /// The join() function waits for the thread specified by `id`
393 /// to terminate.
394 #[inline(always)]
395 pub unsafe fn join(id: Tid) -> i32 {
396 sys_join(id)
397 }
398
399 /// yield the processor
400 ///
401 /// causes the calling thread to relinquish the CPU. The thread
402 /// is moved to the end of the queue for its static priority.
403 #[inline(always)]
404 pub unsafe fn yield_now() {
405 sys_yield()
406 }
407
408 /// get current time
409 ///
410 /// The clock_gettime() functions allow the calling thread
411 /// to retrieve the value used by a clock which is specified
412 /// by `clock_id`.
413 ///
414 /// `CLOCK_REALTIME`: the system's real time clock,
415 /// expressed as the amount of time since the Epoch.
416 ///
417 /// `CLOCK_MONOTONIC`: clock that increments monotonically,
418 /// tracking the time since an arbitrary point
419 #[inline(always)]
420 pub unsafe fn clock_gettime(clock_id: u64, tp: *mut timespec) -> i32 {
421 sys_clock_gettime(clock_id, tp)
422 }
423
424 /// open and possibly create a file
425 ///
426 /// The open() system call opens the file specified by `name`.
427 /// If the specified file does not exist, it may optionally
428 /// be created by open().
429 #[inline(always)]
430 pub unsafe fn open(name: *const i8, flags: i32, mode: i32) -> i32 {
431 sys_open(name, flags, mode)
432 }
433
434 /// delete the file it refers to `name`
435 #[inline(always)]
436 pub unsafe fn unlink(name: *const i8) -> i32 {
437 sys_unlink(name)
438 }
439
440 /// The largest number `rand` will return
441 pub const RAND_MAX: u64 = 2_147_483_647;
442
443 /// The function computes a sequence of pseudo-random integers
444 /// in the range of 0 to RAND_MAX
445 #[inline(always)]
446 pub unsafe fn rand() -> u32 {
447 sys_rand()
448 }
449
450 /// The function sets its argument as the seed for a new sequence
451 /// of pseudo-random numbers to be returned by `rand`
452 #[inline(always)]
453 pub unsafe fn srand(seed: u32) {
454 sys_srand(seed);
455 }
456
457 /// Create a cryptographicly secure 32bit random number with the support of
458 /// the underlying hardware. If the required hardware isn't available,
459 /// the function returns `None`.
460 #[inline(always)]
461 pub unsafe fn secure_rand32() -> Option<u32> {
462 sys_secure_rand32()
463 }
464
465 /// Create a cryptographicly secure 64bit random number with the support of
466 /// the underlying hardware. If the required hardware isn't available,
467 /// the function returns `None`.
468 #[inline(always)]
469 pub unsafe fn secure_rand64() -> Option<u64> {
470 sys_secure_rand64()
471 }
472
473 /// Add current task to the queue of blocked tasl. After calling `block_current_task`,
474 /// call `yield_now` to switch to another task.
475 #[inline(always)]
476 pub unsafe fn block_current_task() {
477 sys_block_current_task();
478 }
479
480 /// Wakeup task with the thread id `tid`
481 #[inline(always)]
482 pub unsafe fn wakeup_task(tid: Tid) {
483 sys_wakeup_task(tid);
484 }
485
486 /// Determine the priority of the current thread
487 #[inline(always)]
488 pub unsafe fn get_priority() -> Priority {
489 Priority::from(sys_get_priority())
490 }