Fennix/Drivers/include/syscalls.h
EnderIce2 201ace7eec
refactor(userspace): build using cmake
Signed-off-by: EnderIce2 <enderice2@protonmail.com>
2025-03-15 23:05:17 +00:00

1813 lines
47 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
This file is part of Fennix Kernel.
Fennix Kernel is free software: you can redistribute it and/or
modify it under the terms of the GNU General Public License as
published by the Free Software Foundation, either version 3 of
the License, or (at your option) any later version.
Fennix Kernel is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with Fennix Kernel. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef __FENNIX_API_SYSTEM_CALLS_LIST_H__
#define __FENNIX_API_SYSTEM_CALLS_LIST_H__
#pragma region Syscall Wrappers
#define scarg __UINTPTR_TYPE__
#ifdef __arm__
#ifdef __thumb__
#define __thumb_r7
#define __arm_call(...)
#warning "arm thumb code not implemented"
#else /* __thumb__ */
#define __thumb_r7 __asm__("r7")
#define __arm_call(...) \
__asm__ __volatile__("svc 0" \
: "=r"(r0) \
: __VA_ARGS__ \
: "memory")
#endif /* __thumb__ */
#ifdef __thumb2__
#define __r7_operand "rI"(r7)
#else /* __thumb2__ */
#define __r7_operand "r"(r7)
#endif /* __thumb2__ */
#endif /* __arm__ */
/**
* @brief Syscall wrapper with 0 arguments
*
* @details This wrapper is used to call syscalls with 0 arguments
*
* @param syscall #syscalls_t
* @return The return value of the syscall
*/
static inline scarg syscall0(scarg syscall)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0");
__arm_call(__r7_operand);
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0");
__asm__ __volatile__("svc 0"
: "=r"(x0)
: "r"(x8)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 1 argument
*
* @details This wrapper is used to call syscalls with 1 argument
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @return The return value of the syscall
*/
static inline scarg syscall1(scarg syscall, scarg arg1)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
__arm_call(__r7_operand, "0"(r0));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 2 arguments
*
* @details This wrapper is used to call syscalls with 2 arguments
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @param arg2 Argument 2
* @return The return value of the syscall
*/
static inline scarg syscall2(scarg syscall, scarg arg1, scarg arg2)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1), "c"(arg2)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
register scarg r1 __asm__("r1") = arg2;
__arm_call(__r7_operand, "0"(r0), "r"(r1));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
register scarg x1 __asm__("x1") = arg2;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0), "r"(x1)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 3 arguments
*
* @details This wrapper is used to call syscalls with 3 arguments
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @param arg2 Argument 2
* @param arg3 Argument 3
* @return The return value of the syscall
*/
static inline scarg syscall3(scarg syscall, scarg arg1, scarg arg2, scarg arg3)
{
scarg ret;
#if defined(__amd64__)
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
register scarg r1 __asm__("r1") = arg2;
register scarg r2 __asm__("r2") = arg3;
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
register scarg x1 __asm__("x1") = arg2;
register scarg x2 __asm__("x2") = arg3;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0), "r"(x1), "r"(x2)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 4 arguments
*
* @details This wrapper is used to call syscalls with 4 arguments
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @param arg2 Argument 2
* @param arg3 Argument 3
* @param arg4 Argument 4
* @return The return value of the syscall
*/
static inline scarg syscall4(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
register scarg r1 __asm__("r1") = arg2;
register scarg r2 __asm__("r2") = arg3;
register scarg r3 __asm__("r3") = arg4;
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
register scarg x1 __asm__("x1") = arg2;
register scarg x2 __asm__("x2") = arg3;
register scarg x3 __asm__("x3") = arg4;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 5 arguments
*
* @details This wrapper is used to call syscalls with 5 arguments
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @param arg2 Argument 2
* @param arg3 Argument 3
* @param arg4 Argument 4
* @param arg5 Argument 5
* @return The return value of the syscall
*/
static inline scarg syscall5(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
register scarg r1 __asm__("r1") = arg2;
register scarg r2 __asm__("r2") = arg3;
register scarg r3 __asm__("r3") = arg4;
register scarg r4 __asm__("r4") = arg5;
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
register scarg x1 __asm__("x1") = arg2;
register scarg x2 __asm__("x2") = arg3;
register scarg x3 __asm__("x3") = arg4;
register scarg x4 __asm__("x4") = arg5;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
/**
* @brief Syscall wrapper with 6 arguments
*
* @details This wrapper is used to call syscalls with 6 arguments
*
* @param syscall #syscalls_t
* @param arg1 Argument 1
* @param arg2 Argument 2
* @param arg3 Argument 3
* @param arg4 Argument 4
* @param arg5 Argument 5
* @param arg6 Argument 6
* @return The return value of the syscall
*/
static inline scarg syscall6(scarg syscall, scarg arg1, scarg arg2, scarg arg3, scarg arg4, scarg arg5, scarg arg6)
{
scarg ret;
#if defined(__amd64__)
register scarg r10 __asm__("r10") = arg4;
register scarg r8 __asm__("r8") = arg5;
register scarg r9 __asm__("r9") = arg6;
__asm__ __volatile__("syscall"
: "=a"(ret)
: "a"(syscall), "D"(arg1), "S"(arg2), "d"(arg3), "r"(r10), "r"(r8), "r"(r9)
: "rcx", "r11", "memory");
#elif defined(__i386__)
__asm__ __volatile__("int $0x30"
: "=a"(ret)
: "a"(syscall), "b"(arg1), "c"(arg2), "d"(arg3), "S"(arg4), "D"(arg5), "g"(arg6)
: "memory");
#elif defined(__arm__)
register scarg r7 __thumb_r7 = syscall;
register scarg r0 __asm__("r0") = arg1;
register scarg r1 __asm__("r1") = arg2;
register scarg r2 __asm__("r2") = arg3;
register scarg r3 __asm__("r3") = arg4;
register scarg r4 __asm__("r4") = arg5;
register scarg r5 __asm__("r5") = arg6;
__arm_call(__r7_operand, "0"(r0), "r"(r1), "r"(r2), "r"(r3), "r"(r4), "r"(r5));
#elif defined(__aarch64__)
register scarg x8 __asm__("x8") = syscall;
register scarg x0 __asm__("x0") = arg1;
register scarg x1 __asm__("x1") = arg2;
register scarg x2 __asm__("x2") = arg3;
register scarg x3 __asm__("x3") = arg4;
register scarg x4 __asm__("x4") = arg5;
register scarg x5 __asm__("x5") = arg6;
__asm__ __volatile__("svc 0"
: "=r"(ret)
: "r"(x8), "0"(x0), "r"(x1), "r"(x2), "r"(x3), "r"(x4), "r"(x5)
: "memory", "cc");
#else
#error "Unsupported architecture"
#endif
return ret;
}
#pragma endregion Syscall Wrappers
/**
* @brief NULL pointer
*
* This is a pointer to address 0, which is reserved and cannot be dereferenced.
*
* @note This macro is defined only for this documentation.
*/
#define __SYS_NULL ((void *)0)
typedef enum
{
__SYS_PROT_READ = 0x1,
__SYS_PROT_WRITE = 0x2,
__SYS_PROT_EXEC = 0x4,
__SYS_PROT_NONE = 0x0,
__SYS_MAP_SHARED = 0x1,
__SYS_MAP_PRIVATE = 0x2,
__SYS_MAP_FIXED = 0x4,
__SYS_MAP_ANONYMOUS = 0x8,
__SYS_MAP_ANON = __SYS_MAP_ANONYMOUS
} syscall_mmap_flags_t;
typedef enum
{
__SYS_O_RDONLY = 0x1,
__SYS_O_WRONLY = 0x2,
__SYS_O_RDWR = 0x3,
__SYS_O_APPEND = 0x4,
__SYS_O_CREAT = 0x8,
__SYS_O_DSYNC = 0x10,
__SYS_O_EXCL = 0x20,
__SYS_O_NOCTTY = 0x40,
__SYS_O_NONBLOCK = 0x80,
__SYS_O_RSYNC = 0x100,
__SYS_O_SYNC = 0x200,
__SYS_O_TRUNC = 0x400
} syscall_open_flags_t;
typedef enum
{
__SYS_F_OK = 0,
__SYS_R_OK = 1,
__SYS_W_OK = 2,
__SYS_X_OK = 3
} syscall_access_flags_t;
typedef enum
{
__SYS_GET_GS = 0,
__SYS_SET_GS = 1,
__SYS_GET_FS = 2,
__SYS_SET_FS = 3,
} syscall_prctl_options_t;
#ifdef __kernel__
typedef syscall_prctl_options_t prctl_options_t;
#endif
typedef enum
{
__SYS_SEEK_SET = 0,
__SYS_SEEK_CUR = 1,
__SYS_SEEK_END = 2
} syscall_seek_whence_t;
typedef enum
{
__SYS_SIGNULL = 0,
/* Process abort signal. */
__SYS_SIGABRT = 1,
/* Alarm clock. */
__SYS_SIGALRM = 2,
/* Access to an undefined portion of a memory object. */
__SYS_SIGBUS = 3,
/* Child process terminated, stopped, or continued. */
__SYS_SIGCHLD = 4,
/* Continue executing, if stopped. */
__SYS_SIGCONT = 5,
/* Erroneous arithmetic operation. */
__SYS_SIGFPE = 6,
/* Hangup. */
__SYS_SIGHUP = 7,
/* Illegal instruction. */
__SYS_SIGILL = 8,
/* Terminal interrupt signal. */
__SYS_SIGINT = 9,
/* Kill (cannot be caught or ignored). */
__SYS_SIGKILL = 10,
/* Write on a pipe with no one to read it. */
__SYS_SIGPIPE = 11,
/* Terminal quit signal. */
__SYS_SIGQUIT = 12,
/* Invalid memory reference. */
__SYS_SIGSEGV = 13,
/* Stop executing (cannot be caught or ignored). */
__SYS_SIGSTOP = 14,
/* Termination signal. */
__SYS_SIGTERM = 15,
/* Terminal stop signal. */
__SYS_SIGTSTP = 16,
/* Background process attempting read. */
__SYS_SIGTTIN = 17,
/* Background process attempting write. */
__SYS_SIGTTOU = 18,
/* User-defined signal 1. */
__SYS_SIGUSR1 = 19,
/* User-defined signal 2. */
__SYS_SIGUSR2 = 20,
/* Pollable event. */
__SYS_SIGPOLL = 21,
/* Profiling timer expired. */
__SYS_SIGPROF = 22,
/* Bad system call. */
__SYS_SIGSYS = 23,
/* Trace/breakpoint trap. */
__SYS_SIGTRAP = 24,
/* High bandwidth data is available at a socket. */
__SYS_SIGURG = 25,
/* Virtual timer expired. */
__SYS_SIGVTALRM = 26,
/* CPU time limit exceeded. */
__SYS_SIGXCPU = 27,
/* File size limit exceeded. */
__SYS_SIGXFSZ = 28,
/**
* Reserved
* These are just to match Linux's signal numbers.
*/
__SYS_SIGCOMP1 = 29,
__SYS_SIGCOMP2 = 30,
__SYS_SIGCOMP3 = 31,
/* Real-time signals. */
__SYS_SIGRTMIN = 32,
__SYS_SIGRT_1 = 33,
__SYS_SIGRT_2 = 34,
__SYS_SIGRT_3 = 35,
__SYS_SIGRT_4 = 36,
__SYS_SIGRT_5 = 37,
__SYS_SIGRT_6 = 38,
__SYS_SIGRT_7 = 39,
__SYS_SIGRT_8 = 40,
__SYS_SIGRT_9 = 41,
__SYS_SIGRT_10 = 42,
__SYS_SIGRT_11 = 43,
__SYS_SIGRT_12 = 44,
__SYS_SIGRT_13 = 45,
__SYS_SIGRT_14 = 46,
__SYS_SIGRT_15 = 47,
__SYS_SIGRT_16 = 48,
__SYS_SIGRT_17 = 49,
__SYS_SIGRT_18 = 50,
__SYS_SIGRT_19 = 51,
__SYS_SIGRT_20 = 52,
__SYS_SIGRT_21 = 53,
__SYS_SIGRT_22 = 54,
__SYS_SIGRT_23 = 55,
__SYS_SIGRT_24 = 56,
__SYS_SIGRT_25 = 57,
__SYS_SIGRT_26 = 58,
__SYS_SIGRT_27 = 59,
__SYS_SIGRT_28 = 60,
__SYS_SIGRT_29 = 61,
__SYS_SIGRT_30 = 62,
__SYS_SIGRT_31 = 63,
__SYS_SIGRTMAX = 64,
/* Maximum signal number. */
__SYS_SIGNAL_MAX = __SYS_SIGRTMAX
} syscall_signal_t;
#ifdef __kernel__
typedef syscall_signal_t signal_t;
#endif
typedef enum
{
/** Terminate the process. */
__SYS_SIG_TERM = 0,
/** Ignore the signal. */
__SYS_SIG_IGN = 1,
/** Continue the process. */
__SYS_SIG_CONT = 2,
/** Stop the process. */
__SYS_SIG_STOP = 3,
/** Dump core. */
__SYS_SIG_CORE = 4
} syscall_signal_disposition_t;
#ifdef __kernel__
typedef syscall_signal_disposition_t signal_disposition_t;
#endif
typedef enum
{
__SYS_SIG_BLOCK = 0,
__SYS_SIG_UNBLOCK = 1,
__SYS_SIG_SETMASK = 2
} syscall_signal_actions_t;
typedef enum
{
__SYS_SA_NOCLDSTOP = 1,
__SYS_SA_ONSTACK = 0x08000000,
__SYS_SA_RESETHAND = 0x80000000,
__SYS_SA_RESTART = 0x10000000,
__SYS_SA_SIGINFO = 4,
__SYS_SA_NOCLDWAIT = 2,
__SYS_SA_NODEFER = 0x40000000,
} syscall_signal_action_flags_t;
typedef enum
{
__SYS_SIG_ERR = -1,
__SYS_SIG_DFL = 0,
___SYS_SIG_IGN = 1
} syscall_signal_action_disposition_t;
typedef enum
{
__SYS_CLOCK_MONOTONIC = 1,
__SYS_CLOCK_PROCESS_CPUTIME_ID = 2,
__SYS_CLOCK_REALTIME = 3,
__SYS_CLOCK_THREAD_CPUTIME_ID = 4,
} syscall_clockid_t;
#ifndef __cplusplus
_Static_assert((int)__SYS_SIG_IGN == (int)___SYS_SIG_IGN, "SIG_IGN values do not match");
#else
static_assert((int)__SYS_SIG_IGN == (int)___SYS_SIG_IGN, "SIG_IGN values do not match");
#endif
typedef int __SYS_clockid_t;
typedef unsigned int __SYS_socklen_t;
typedef struct FramebufferScreenInfo
{
__UINT32_TYPE__ Width;
__UINT32_TYPE__ Height;
__UINT32_TYPE__ Pitch;
__UINT32_TYPE__ Bpp;
__UINT32_TYPE__ Size;
} FramebufferScreenInfo;
/**
* @brief Get framebuffer screen info
*
* @code
* struct FramebufferScreenInfo info;
* int ioctl(fd, FBIOGET_SCREEN_INFO, &info);
* @endcode
*
* @param fd File descriptor of the framebuffer device
* @param info Pointer to the framebuffer screen info structure
*/
#define FBIOGET_SCREEN_INFO 0xf0
struct kutsname
{
char sysname[65];
char release[65];
char version[65];
char machine[65];
};
/**
* @brief List of syscalls
*
* @details This list contains all the syscalls of the Fennix Kernel API.
*
*/
typedef enum
{
/* Initialization */
/**
* @brief Set syscall version
*
* @code
* int api_version(int version);
* @endcode
*
* @details This syscall is used to set the version of the list.
* To prevent applications from breaking on major changes, this should
* be called at the very beginning of the program.
*
* @param version The version of the syscall list of which the program
* was compiled with
*
* @return
* - #EOK on success
* - #EINVAL if the requested version is invalid
*
* @note If this syscall is not used, the latest version will be used.
*/
SYS_API_VERSION = 0,
/* I/O */
/**
* @brief Read from a file descriptor
*
* @code
* ssize_t sys_read(int fildes, void *buf, size_t nbyte);
* @endcode
*
* @details Reads up to `count` bytes from the file descriptor `fd` into
* the buffer starting at `buf`.
*
* @param fd File descriptor to read from
* @param buf Buffer where data will be stored
* @param count Maximum number of bytes to read
*
* @return
* - Number of bytes read on success
* - 0 if the end of file is reached
* - #EFAULT if the buffer is outside accessible address space
* - #EBADF if `fd` is not a valid file descriptor
*/
SYS_READ = 100,
/**
* @brief Read from a file descriptor
*
* @code
* ssize_t sys_pread(int fildes, void *buf, size_t nbyte, off_t offset);
* @endcode
*
* @details Reads up to `count` bytes from the file descriptor `fd` into
* the buffer starting at `buf`.
*
* @param fd File descriptor to read from
* @param buf Buffer where data will be stored
* @param count Maximum number of bytes to read
* @param offset Offset in the file
*
* @return
* - Number of bytes read on success
* - 0 if the end of file is reached
* - #EFAULT if the buffer is outside accessible address space
* - #EBADF if `fd` is not a valid file descriptor
*/
SYS_PREAD,
/**
* @brief Write to a file descriptor
*
* @code
* ssize_t sys_write(int fildes, const void *buf, size_t nbyte);
* @endcode
*
* @details Writes up to `count` bytes from the buffer starting at `buf`
* to the file descriptor `fd`.
*
* @param fd File descriptor to write to
* @param buf Buffer containing data to write
* @param count Number of bytes to write
*
* @return
* - Number of bytes written on success
* - #EFAULT if the buffer is outside accessible address space
* - #EBADF if `fd` is not a valid file descriptor
* - #EPIPE if writing to a pipe with no reader
*/
SYS_WRITE,
/**
* @brief Write to a file descriptor
*
* @code
* ssize_t sys_pwrite(int fildes, const void *buf, size_t nbyte, off_t offset);
* @endcode
*
* @details Writes up to `count` bytes from the buffer starting at `buf`
* to the file descriptor `fd`.
*
* @param fd File descriptor to write to
* @param buf Buffer containing data to write
* @param count Number of bytes to write
* @param offset Offset in the file
*
* @return
* - Number of bytes written on success
* - #EFAULT if the buffer is outside accessible address space
* - #EBADF if `fd` is not a valid file descriptor
*/
SYS_PWRITE,
/**
* @brief Open a file
*
* @code
* int open(const char *pathname, int flags, mode_t mode);
* @endcode
*
* @details Opens the file specified by `pathname`.
*
* @param pathname Path to the file
* @param flags Flags for file access mode\n
* Supported values:
* - #__SYS_O_RDONLY: Open file for reading only.
* - #__SYS_O_WRONLY: Open file for writing only.
* - #__SYS_O_RDWR: Open file for reading and writing.
* - #__SYS_O_APPEND: Append data to the end of file.
* - #__SYS_O_CREAT: Create file if it does not exist.
* - #__SYS_O_DSYNC:
* - #__SYS_O_EXCL:
* - #__SYS_O_NOCTTY:
* - #__SYS_O_NONBLOCK:
* - #__SYS_O_RSYNC:
* - #__SYS_O_SYNC:
* - #__SYS_O_TRUNC: Truncate file to zero length.
* @param mode Permissions for newly created file (if applicable)
*
* @return
* - File descriptor on success
* - #ENOENT if the file does not exist
* - #EACCES if permissions are insufficient
*
* @see #syscall_open_flags_t
*/
SYS_OPEN,
/**
* @brief Close a file descriptor
*
* @code
* int close(int fd);
* @endcode
*
* @details Closes the file descriptor `fd`, releasing its resources.
*
* @param fd File descriptor to close
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not a valid file descriptor
*/
SYS_CLOSE,
/**
* @brief Control a device
*
* @code
* int ioctl(int fd, unsigned long request, void *argp);
* @endcode
*
* @details Manipulates the underlying parameters of a device.
*
* @param fd File descriptor referring to the device
* @param request Device-specific request code
* @param argp Argument for the request
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not valid
* - #EINVAL if the request is invalid
*/
SYS_IOCTL,
/* File Status */
/**
* @brief Retrieve file status
*
* @code
* int stat(const char *pathname, struct stat *statbuf);
* @endcode
*
* @details Gets the status of the file specified by `pathname`.
*
* @param pathname Path to the file
* @param statbuf Buffer to store file status
*
* @return
* - #EOK on success
* - #ENOENT if the file does not exist
* - #EACCES if permissions are insufficient
*/
SYS_STAT = 200,
/**
* @brief Retrieve file status for an open file descriptor
*
* @code
* int fstat(int fd, struct stat *statbuf);
* @endcode
*
* @details Gets the status of the file referred to by `fd`.
*
* @param fd File descriptor
* @param statbuf Buffer to store file status
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not a valid file descriptor
* - #EFAULT if `statbuf` is outside accessible address space
*/
SYS_FSTAT,
/**
* @brief Retrieve file status with symbolic link resolution
*
* @code
* int lstat(const char *pathname, struct stat *statbuf);
* @endcode
*
* @details Gets the status of the file specified by `pathname`,
* but does not follow symbolic links.
*
* @param pathname Path to the file
* @param statbuf Buffer to store file status
*
* @return
* - #EOK on success
* - #ENOENT if the file does not exist
* - #EACCES if permissions are insufficient
*/
SYS_LSTAT,
/**
* @brief Check a file's accessibility
*
* @code
* int access(const char *pathname, int mode);
* @endcode
*
* @details Checks if the calling process can access the file specified
* by `pathname` according to the specified `mode`.
*
* @param pathname Path to the file
* @param mode Accessibility check mode\n
* Supported values:
* - #__SYS_F_OK: Check if the file exists
* - #__SYS_R_OK: Check if the file is readable
* - #__SYS_W_OK: Check if the file is writable
* - #__SYS_X_OK: Check if the file is executable
*
* @return
* - #EOK on success
* - #EACCES if access is denied
* - #ENOENT if the file does not exist
*
* @see #syscall_access_flags_t
*/
SYS_ACCESS,
/**
* @brief Change the size of a file
*
* @code
* int truncate(const char *pathname, off_t length);
* @endcode
*
* @details Sets the size of the file specified by `pathname` to `length`.
* If the file is shorter, it is extended and the extended part is zero-filled.
*
* @param pathname Path to the file
* @param length Desired file length
*
* @return
* - #EOK on success
* - #EINVAL if `length` is invalid
* - #EACCES if permissions are insufficient
*/
SYS_TRUNCATE,
/**
* @brief Change the size of a file referred by a file descriptor
*
* @code
* int ftruncate(int fd, off_t length);
* @endcode
*
* @details Sets the size of the file referred to by `fd` to `length`.
*
* @param fd File descriptor
* @param length Desired file length
*
* @return
* - #EOK on success
* - #EBADF if `fd` is not valid
* - #EINVAL if `length` is invalid
*/
SYS_FTRUNCATE,
/**
* @brief Get the current file offset
*
* @code
* off_t tell(int fd);
* @endcode
*
* @details Returns the current file offset for the file referred to by `fd`.
*
* @param fd File descriptor
*
* @return
* - Current file offset on success
* - #EBADF if `fd` is not a valid file descriptor
*/
SYS_TELL,
/**
* @brief Set the file offset
*
* @code
* off_t seek(int fd, off_t offset, int whence);
* @endcode
*
* @details Sets the file offset for the file referred to by `fd` to the
* specified `offset` according to the directive `whence`.
*
* @param fd File descriptor
* @param offset Offset to set
* @param whence Directive for setting the offset\n
* Supported values:
* - #__SYS_SEEK_SET: Set the offset to `offset` bytes
* - #__SYS_SEEK_CUR: Set the offset to the current offset plus `offset`
* - #__SYS_SEEK_END: Set the offset to the size of the file plus `offset`
*
* @return
* - New file offset on success
* - #EBADF if `fd` is not a valid file descriptor
* - #EINVAL if `whence` is invalid
*/
SYS_SEEK,
/* Process Control */
/**
* @brief Terminate the calling process
*
* @code
* void exit(int status);
* @endcode
*
* @details Terminates the calling process with the specified `status`.
* The status code is made available to the parent process.
*
* @param status Exit status code
*
* @return This function does not return.
*/
SYS_EXIT = 300,
/**
* @brief Create a child process
*
* @code
* pid_t fork(void);
* @endcode
*
* @details Creates a new process by duplicating the calling process.
* The child process has its own copy of the parent's address space.
*
* @return
* - 0 to the child process
* - PID of the child to the parent process
* - #ENOMEM if memory is insufficient
*/
SYS_FORK,
/**
* @brief Execute a program
*
* @code
* int execve(const char *pathname, char *const argv[], char *const envp[]);
* @endcode
*
* @details Replaces the current process image with a new process image
* specified by `pathname`.
*
* @param pathname Path to the executable file
* @param argv Argument vector
* @param envp Environment variables
*
* @return
* - Does not return on success
* - #ENOENT if the file does not exist
* - #EACCES if permissions are insufficient
*/
SYS_EXECVE,
/**
* @brief Get the process ID of the calling process
*
* @code
* pid_t getpid(void);
* @endcode
*
* @details Returns the process ID of the calling process.
*
* @return
* - Process ID on success
*/
SYS_GETPID,
/**
* @brief Get the parent process ID
*
* @code
* pid_t getppid(void);
* @endcode
*
* @details Returns the parent process ID of the calling process.
*
* @return
* - Parent process ID on success
*/
SYS_GETPPID,
/**
* @brief Wait for a child process to change state
*
* @code
* pid_t waitpid(pid_t pid, int *wstatus, int options);
* @endcode
*
* @details Waits for the child process specified by `pid` to change state.
*
* @param pid Process ID to wait for
* @param wstatus Pointer to store the status information
* @param options Options for waiting behavior
*
* @return
* - Process ID of the child on success
* - #ECHILD if no child processes exist
*/
SYS_WAITPID,
/**
* @brief Send a signal to a process
*
* @code
* int kill(pid_t pid, int sig);
* @endcode
*
* @details Sends the signal `sig` to the process specified by `pid`.
*
* @param pid Process ID
* @param sig Signal to send
*
* @return
* - #EOK on success
* - #ESRCH if the process does not exist
* - #EINVAL if `sig` is invalid
*/
SYS_KILL,
/**
* @brief Process/Thread Control
*
* @code
* int prctl(syscall_prctl_options_t option, unsigned long arg1, unsigned long arg2, unsigned long arg3, unsigned long arg4);
* @endcode
*
* @details Perform various operations on a process or thread.
*
* @param option Operation to perform
* @param arg1 Argument 1
* @param arg2 Argument 2
* @param arg3 Argument 3
* @param arg4 Argument 4
*
* @return
* - #EOK on success
* - #EINVAL if the operation is invalid
* - #EFAULT if one of the arguments is invalid
*/
SYS_PRCTL,
/* Memory */
/**
* @brief Set the program break
*
* @code
* int brk(void *end_data);
* @endcode
*
* @details Increases or decreases the programs data space, ending at `end_data`.
*
* @param end_data New program break location
*
* @return
* - #EOK on success
* - #ENOMEM if memory allocation fails
*/
SYS_BRK = 400,
/**
* @brief Map files or devices into memory
*
* @code
* void *mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset);
* @endcode
*
* @details Maps a file or device into memory. This can be used for memory-mapped I/O or
* for sharing memory between processes.
*
* @param addr Desired starting address of the mapping (NULL for automatic allocation)
* @param length Length of the mapping
* @param prot Desired memory protection\n
* Supported values:
* - #__SYS_PROT_READ: Readable
* - #__SYS_PROT_WRITE: Writable
* - #__SYS_PROT_EXEC: Executable
* - #__SYS_PROT_NONE: No access
* @param flags Mapping options\n
* Supported values:
* - #__SYS_MAP_SHARED: Share memory with other processes
* - #__SYS_MAP_PRIVATE: Create a private copy of the file
* - #__SYS_MAP_FIXED: Use `addr` as the starting address of the mapping
* - #__SYS_MAP_ANONYMOUS: Create an anonymous mapping
* @param fd File descriptor for the file to map
* @param offset Offset in the file to start the mapping
*
* @return There are several possible return values:
* - Pointer to mapped area on success
* - #EACCES
* - #EAGAIN
* - #EBADF
* - #EINVAL
* - #EMFILE
* - #ENODEV
* - #ENOMEM
* - #ENOTSUP
* - #ENXIO
* - #EOVERFLOW
*
* @see #syscall_mmap_flags_t
*/
SYS_MMAP,
/**
* @brief Unmap a mapped memory region
*
* @code
* int munmap(void *addr, size_t length);
* @endcode
*
* @details Unmaps a previously mapped memory region, making the memory available for reuse.
*
* @param addr Start address of the memory region
* @param length Length of the memory region to unmap
*
* @return
* - #EOK on success
* - #EINVAL if the address or length is invalid
* - #EFAULT if the memory region is not currently mapped
*/
SYS_MUNMAP,
/**
* @brief Change memory protection
*
* @code
* int mprotect(void *addr, size_t length, int prot);
* @endcode
*
* @details Sets the protection on the memory region starting at `addr` for `length`.
*
* @param addr Start address of the memory region
* @param length Length of the memory region
* @param prot Desired memory protection (e.g., PROT_READ, PROT_WRITE)
*
* @return
* - #EOK on success
* - #EACCES if protection cannot be set
*/
SYS_MPROTECT,
/**
* @brief Provide advice about memory usage
*
* @code
* int madvise(void *addr, size_t length, int advice);
* @endcode
*
* @details Provides advice to the kernel about the expected behavior of the memory region
* starting at `addr` for `length`, such as whether it will be accessed randomly or sequentially.
*
* @param addr Start address of the memory region
* @param length Length of the memory region
* @param advice Desired advice (e.g., MADV_DONTNEED, MADV_SEQUENTIAL)
*
* @return
* - #EOK on success
* - #EINVAL if the parameters are invalid
*/
SYS_MADVISE,
/* Communication */
/**
* @brief Create a pipe
*
* @code
* int pipe(int pipefd[2]);
* @endcode
*
* @details Creates a pipe, returning two file descriptors in `pipefd`. One is for reading,
* and the other is for writing.
*
* @param pipefd Array to store the two file descriptors
*
* @return
* - #EOK on success
* - #EMFILE if the process has too many open file descriptors
*/
SYS_PIPE = 500,
/**
* @brief Duplicate a file descriptor
*
* @code
* int dup(int oldfd);
* @endcode
*
* @details Duplicates the file descriptor `oldfd`, returning the new file descriptor.
*
* @param oldfd File descriptor to duplicate
*
* @return
* - New file descriptor on success
* - #EBADF if `oldfd` is invalid
*/
SYS_DUP,
/**
* @brief Duplicate a file descriptor to a specific value
*
* @code
* int dup2(int oldfd, int newfd);
* @endcode
*
* @details Duplicates `oldfd` to `newfd`. If `newfd` is already open, it will be closed first.
*
* @param oldfd File descriptor to duplicate
* @param newfd File descriptor to duplicate `oldfd` to
*
* @return
* - `newfd` on success
* - #EBADF if `oldfd` is invalid
* - #EINVAL if `newfd` is invalid
*/
SYS_DUP2,
/**
* @brief Create an endpoint for communication
*
* @code
* int socket(int domain, int type, int protocol);
* @endcode
*
* @details Creates an endpoint for communication, returning a socket file descriptor.
*
* @param domain Communication domain (e.g., AF_INET for IPv4)
* @param type Type of socket (e.g., SOCK_STREAM for TCP)
* @param protocol Protocol to use (e.g., IPPROTO_TCP)
*
* @return
* - Socket file descriptor on success
* - #EINVAL if parameters are invalid
*/
SYS_SOCKET,
/**
* @brief Bind a socket to a local address
*
* @code
* int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
* @endcode
*
* @details Binds a socket to a local address so it can listen for incoming connections.
*
* @param sockfd Socket file descriptor
* @param addr Address to bind to
* @param addrlen Length of the address
*
* @return
* - #EOK on success
* - #EINVAL if the socket is invalid
*/
SYS_BIND,
/**
* @brief Connect to a remote address
*
* @code
* int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
* @endcode
*
* @details Connects a socket to a remote address.
*
* @param sockfd Socket file descriptor
* @param addr Remote address to connect to
* @param addrlen Length of the address
*
* @return
* - #EOK on success
* - #EINVAL if parameters are invalid
*/
SYS_CONNECT,
/**
* @brief Listen for incoming connections on a socket
*
* @code
* int listen(int sockfd, int backlog);
* @endcode
*
* @details Sets a socket to listen for incoming connections, specifying the backlog queue size.
*
* @param sockfd Socket file descriptor
* @param backlog Number of pending connections to allow
*
* @return
* - #EOK on success
* - #EINVAL if parameters are invalid
*/
SYS_LISTEN,
/**
* @brief Accept an incoming connection on a socket
*
* @code
* int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
* @endcode
*
* @details Accepts an incoming connection on a listening socket, creating a new socket for communication.
*
* @param sockfd Socket file descriptor
* @param addr Client address
* @param addrlen Length of the address
*
* @return
* - New socket file descriptor on success
* - #EINVAL if parameters are invalid
*/
SYS_ACCEPT,
/**
* @brief Send data on a socket
*
* @code
* ssize_t send(int sockfd, const void *buf, size_t len, int flags);
* @endcode
*
* @details Sends data through a socket.
*
* @param sockfd Socket file descriptor
* @param buf Data to send
* @param len Length of the data
* @param flags Flags for the send operation
*
* @return
* - Number of bytes sent on success
* - #EINVAL if parameters are invalid
*/
SYS_SEND,
/**
* @brief Receive data on a socket
*
* @code
* ssize_t recv(int sockfd, void *buf, size_t len, int flags);
* @endcode
*
* @details Receives data from a socket.
*
* @param sockfd Socket file descriptor
* @param buf Buffer to store received data
* @param len Maximum number of bytes to receive
* @param flags Flags for the receive operation
*
* @return
* - Number of bytes received on success
* - #EINVAL if parameters are invalid
*/
SYS_RECV,
/**
* @brief Shut down part of a full-duplex connection
*
* @code
* int shutdown(int sockfd, int how);
* @endcode
*
* @details Shuts down part of a full-duplex connection on a socket.
*
* @param sockfd Socket file descriptor
* @param how Determines which operations to shut down (e.g., SHUT_RD, SHUT_WR)
*
* @return
* - #EOK on success
* - #EINVAL if parameters are invalid
*/
SYS_SHUTDOWN,
/* Time */
/**
* @brief Get the current time
*
* @code
* time_t time(time_t *t);
* @endcode
*
* @details Retrieves the current calendar time as the number of seconds since the epoch.
*
* @param t Pointer to store the time (optional)
*
* @return
* - Current time in seconds on success
* - #__SYS_NULL if `t` is NULL
*/
SYS_TIME = 600,
/**
* @brief Get the current time of a specific clock
*
* @code
* int clock_gettime(clockid_t clockid, struct timespec *tp);
* @endcode
*
* @details Retrieves the current time for the specified clock (`CLOCK_REALTIME`, `CLOCK_MONOTONIC`, etc.).
*
* @param clockid Clock ID to query
* @param tp Pointer to store the time
*
* @return
* - #EOK on success
* - #EINVAL if parameters are invalid
*/
SYS_CLOCK_GETTIME,
/**
* @brief Set the current time of a specific clock
*
* @code
* int clock_settime(clockid_t clockid, const struct timespec *tp);
* @endcode
*
* @details Sets the time for the specified clock (`CLOCK_REALTIME`, `CLOCK_MONOTONIC`, etc.).
*
* @param clockid Clock ID to set
* @param tp Pointer to the time value
*
* @return
* - #EOK on success
* - #EINVAL if parameters are invalid
*/
SYS_CLOCK_SETTIME,
/**
* @brief Sleep for a specified time
*
* @code
* int nanosleep(const struct timespec *req, struct timespec *rem);
* @endcode
*
* @details Suspends the execution of the calling thread for the specified time duration.
*
* @param req Pointer to `timespec` specifying the time to sleep
* @param rem Pointer to store remaining time if interrupted
*
* @return
* - #EOK on success
* - #EINTR if interrupted by a signal
*/
SYS_NANOSLEEP,
/* Miscellaneous */
/**
* @brief Get the current working directory
*
* @code
* char *getcwd(char *buf, size_t size);
* @endcode
*
* @details Retrieves the current working directory.
*
* @param buf Buffer to store the directory path
* @param size Size of the buffer
*
* @return
* - Pointer to `buf` on success
* - #__SYS_NULL on error
*/
SYS_GETCWD = 700,
/**
* @brief Change the current working directory
*
* @code
* int chdir(const char *path);
* @endcode
*
* @details Changes the current working directory to the specified `path`.
*
* @param path New directory path
*
* @return
* - #EOK on success
* - #ENOENT if the directory does not exist
* - #EACCES if permission is denied
*/
SYS_CHDIR,
/**
* @brief Create a new directory
*
* @code
* int mkdir(const char *path, mode_t mode);
* @endcode
*
* @details Creates a new directory at `path` with the specified permissions.
*
* @param path Path to the new directory
* @param mode Directory permissions
*
* @return
* - #EOK on success
* - #EEXIST if the directory already exists
* - #EACCES if permission is denied
*/
SYS_MKDIR,
/**
* @brief Remove an empty directory
*
* @code
* int rmdir(const char *path);
* @endcode
*
* @details Removes the empty directory specified by `path`.
*
* @param path Path to the directory
*
* @return
* - #EOK on success
* - #ENOTEMPTY if the directory is not empty
*/
SYS_RMDIR,
/**
* @brief Remove a file
*
* @code
* int unlink(const char *pathname);
* @endcode
*
* @details Removes the file specified by `pathname`.
*
* @param pathname Path to the file
*
* @return
* - #EOK on success
* - #ENOENT if the file does not exist
* - #EACCES if permission is denied
*/
SYS_UNLINK,
/**
* @brief Rename a file or directory
*
* @code
* int rename(const char *oldpath, const char *newpath);
* @endcode
*
* @details Renames a file or directory from `oldpath` to `newpath`.
*
* @param oldpath Current name of the file or directory
* @param newpath New name of the file or directory
*
* @return
* - #EOK on success
* - #EEXIST if the target exists
* - #EACCES if permission is denied
*/
SYS_RENAME,
/**
* @brief Get unix name information
*
* @code
* int uname(struct kutsname *buf);
* @endcode
*
* @details Retrieves information about the operating system.
*
* @param buf Pointer to `kutsname` structure to store information
*
* @return
* - #EOK on success
* - #EFAULT if `buf` is outside accessible address space
*/
SYS_UNAME,
/**
* @brief Max number of syscalls
*
* @details This is used to determine the size of the `syscalls_t` array.
*
* @code
* syscalls_t syscalls[SYS_MAX];
* @endcode
*
* @note This must be the last element in the list
*/
SYS_MAX
} syscalls_t;
/* Initialization */
/** @copydoc SYS_API_VERSION */
#define call_api_version(version) syscall1(SYS_API_VERSION, (scarg)version)
/* I/O */
/** @copydoc SYS_READ */
#define call_read(fd, buf, count) syscall3(SYS_READ, (scarg)fd, (scarg)buf, (scarg)count)
/** @copydoc SYS_PREAD */
#define call_pread(fd, buf, count, offset) syscall4(SYS_PREAD, (scarg)fd, (scarg)buf, (scarg)count, (scarg)offset)
/** @copydoc SYS_WRITE */
#define call_write(fd, buf, count) syscall3(SYS_WRITE, (scarg)fd, (scarg)buf, (scarg)count)
/** @copydoc SYS_PWRITE */
#define call_pwrite(fd, buf, count, offset) syscall4(SYS_PWRITE, (scarg)fd, (scarg)buf, (scarg)count, (scarg)offset)
/** @copydoc SYS_OPEN */
#define call_open(pathname, flags, mode) syscall3(SYS_OPEN, (scarg)pathname, (scarg)flags, (scarg)mode)
/** @copydoc SYS_CLOSE */
#define call_close(fd) syscall1(SYS_CLOSE, fd)
/** @copydoc SYS_IOCTL */
#define call_ioctl(fd, request, argp) syscall3(SYS_IOCTL, (scarg)fd, (scarg)request, (scarg)argp)
/* File Status */
/** @copydoc SYS_STAT */
#define call_stat(pathname, statbuf) syscall2(SYS_STAT, (scarg)pathname, (scarg)statbuf)
/** @copydoc SYS_FSTAT */
#define call_fstat(fd, statbuf) syscall2(SYS_FSTAT, (scarg)fd, (scarg)statbuf)
/** @copydoc SYS_LSTAT */
#define call_lstat(pathname, statbuf) syscall2(SYS_LSTAT, (scarg)pathname, (scarg)statbuf)
/** @copydoc SYS_ACCESS */
#define call_access(pathname, mode) syscall2(SYS_ACCESS, (scarg)pathname, (scarg)mode)
/** @copydoc SYS_TRUNCATE */
#define call_truncate(pathname, length) syscall2(SYS_TRUNCATE, (scarg)pathname, (scarg)length)
/** @copydoc SYS_FTRUNCATE */
#define call_ftruncate(fd, length) syscall2(SYS_FTRUNCATE, (scarg)fd, (scarg)length)
/** @copydoc SYS_TELL */
#define call_tell(fd) syscall1(SYS_TELL, (scarg)fd)
/** @copydoc SYS_SEEK */
#define call_seek(fd, offset, whence) syscall3(SYS_SEEK, (scarg)fd, (scarg)offset, (scarg)whence)
/* Process Control */
/** @copydoc SYS_EXIT */
#define call_exit(status) syscall1(SYS_EXIT, (scarg)status)
/** @copydoc SYS_FORK */
#define call_fork() syscall0(SYS_FORK)
/** @copydoc SYS_EXECVE */
#define call_execve(pathname, argv, envp) syscall3(SYS_EXECVE, (scarg)pathname, (scarg)argv, (scarg)envp)
/** @copydoc SYS_GETPID */
#define call_getpid() syscall0(SYS_GETPID)
/** @copydoc SYS_GETPPID */
#define call_getppid() syscall0(SYS_GETPPID)
/** @copydoc SYS_WAITPID */
#define call_waitpid(pid, wstatus, options) syscall3(SYS_WAITPID, (scarg)pid, (scarg)wstatus, (scarg)options)
/** @copydoc SYS_KILL */
#define call_kill(pid, sig) syscall2(SYS_KILL, (scarg)pid, (scarg)sig)
/** @copydoc SYS_PRCTL */
#define call_prctl(option, arg1, arg2, arg3, arg4) syscall5(SYS_PRCTL, (scarg)option, (scarg)arg1, (scarg)arg2, (scarg)arg3, (scarg)arg4)
/* Memory */
/** @copydoc SYS_BRK */
#define call_brk(end_data) syscall1(SYS_BRK, (scarg)end_data)
/** @copydoc SYS_MMAP */
#define call_mmap(addr, length, prot, flags, fd, offset) syscall6(SYS_MMAP, (scarg)addr, (scarg)length, (scarg)prot, (scarg)flags, (scarg)fd, (scarg)offset)
/** @copydoc SYS_MUNMAP */
#define call_munmap(addr, length) syscall2(SYS_MUNMAP, (scarg)addr, (scarg)length)
/** @copydoc SYS_MPROTECT */
#define call_mprotect(addr, length, prot) syscall3(SYS_MPROTECT, (scarg)addr, (scarg)length, (scarg)prot)
/** @copydoc SYS_MADVISE */
#define call_madvise(addr, length, advice) syscall3(SYS_MADVISE, (scarg)addr, (scarg)length, (scarg)advice)
/* Communication */
/** @copydoc SYS_PIPE */
#define call_pipe(pipefd) syscall1(SYS_PIPE, (scarg)pipefd)
/** @copydoc SYS_DUP */
#define call_dup(oldfd) syscall1(SYS_DUP, (scarg)oldfd)
/** @copydoc SYS_DUP2 */
#define call_dup2(oldfd, newfd) syscall2(SYS_DUP2, (scarg)oldfd, (scarg)newfd)
/** @copydoc SYS_SOCKET */
#define call_socket(domain, type, protocol) syscall3(SYS_SOCKET, (scarg)domain, (scarg)type, (scarg)protocol)
/** @copydoc SYS_BIND */
#define call_bind(sockfd, addr, addrlen) syscall3(SYS_BIND, (scarg)sockfd, (scarg)addr, (scarg)addrlen)
/** @copydoc SYS_CONNECT */
#define call_connect(sockfd, addr, addrlen) syscall3(SYS_CONNECT, (scarg)sockfd, (scarg)addr, (scarg)addrlen)
/** @copydoc SYS_LISTEN */
#define call_listen(sockfd, backlog) syscall2(SYS_LISTEN, (scarg)sockfd, (scarg)backlog)
/** @copydoc SYS_ACCEPT */
#define call_accept(sockfd, addr, addrlen) syscall3(SYS_ACCEPT, (scarg)sockfd, (scarg)addr, (scarg)addrlen)
/** @copydoc SYS_SEND */
#define call_send(sockfd, buf, len, flags) syscall4(SYS_SEND, (scarg)sockfd, (scarg)buf, (scarg)len, (scarg)flags)
/** @copydoc SYS_RECV */
#define call_recv(sockfd, buf, len, flags) syscall4(SYS_RECV, (scarg)sockfd, (scarg)buf, (scarg)len, (scarg)flags)
/** @copydoc SYS_SHUTDOWN */
#define call_shutdown(sockfd, how) syscall2(SYS_SHUTDOWN, (scarg)sockfd, (scarg)how)
/* Time */
/** @copydoc SYS_TIME */
#define call_time(t) syscall1(SYS_TIME, t)
/** @copydoc SYS_CLOCK_GETTIME */
#define call_clock_gettime(clockid, tp) syscall2(SYS_CLOCK_GETTIME, (scarg)clockid, (scarg)tp)
/** @copydoc SYS_CLOCK_SETTIME */
#define call_clock_settime(clockid, tp) syscall2(SYS_CLOCK_SETTIME, (scarg)clockid, (scarg)tp)
/** @copydoc SYS_NANOSLEEP */
#define call_nanosleep(req, rem) syscall2(SYS_NANOSLEEP, (scarg)req, (scarg)rem)
/* Miscellaneous */
/** @copydoc SYS_GETCWD */
#define call_getcwd(buf, size) syscall2(SYS_GETCWD, (scarg)buf, (scarg)size)
/** @copydoc SYS_CHDIR */
#define call_chdir(path) syscall1(SYS_CHDIR, (scarg)path)
/** @copydoc SYS_MKDIR */
#define call_mkdir(path, mode) syscall2(SYS_MKDIR, (scarg)path, (scarg)mode)
/** @copydoc SYS_RMDIR */
#define call_rmdir(path) syscall1(SYS_RMDIR, (scarg)path)
/** @copydoc SYS_UNLINK */
#define call_unlink(pathname) syscall1(SYS_UNLINK, (scarg)pathname)
/** @copydoc SYS_RENAME */
#define call_rename(oldpath, newpath) syscall2(SYS_RENAME, (scarg)oldpath, (scarg)newpath)
/** @copydoc SYS_UNAME */
#define call_uname(buf) syscall1(SYS_UNAME, (scarg)buf)
#endif // !__FENNIX_API_SYSTEM_CALLS_LIST_H__