POSIX 2024 Changes
Jonas 'Sortie' Termansen on 2024-06-28POSIX.1-2024 has just been released with a lot of exciting and interesting
improvements and removals compared to POSIX-1.2008. The html version of the
standard has not been uploaded yet as of this writing. The official list of new
functions in the standard itself is very incomplete, so I combed through the
CHANGE HISTORY
sections in the official pdf, and I present you with the most
accurate list of the changes so far.
Sortix is among the very first operating systems to implement most of the new interfaces. I had already implemented much of POSIX 2024 several years ago, and I just implemented a lot of the remaining interfaces in a weekend hackathon, with a few things still missing. Although Sortix only implements most parts of POSIX so far, the POSIX 2024 aspects are largely implemented or has been explicitly rejected.
If you want to try out the new POSIX 2024 features in practice, why not try out the latest Sortix nightly build?
#define _POSIX_C_SOURCE 202405L /* to use the new POSIX */ #define _XOPEN_SOURCE 800 /* to use the new XSI option */
Overview
New Functions | New Features | New Utilities | Removed |
---|---|---|---|
_Fork() | ABALTMON_x, ALTMON_x | set -o pipefail | asctime_r() |
accept4() | bind() port 0 | awk features | ctime_r() |
aligned_alloc (C11) | CMSG_LEN, CMSG_SPACE | cd -e | fattach() |
asprintf() | ESOCKTNOSUPPORT | dd iflags=fullblock | fdetach() |
dladdr() | FD_CLOEXEC, F_DUPFD_CLOFORK | find -print0 | ftw() |
dup3() | FNM_CASEFOLD, FNM_IGNORECASE | find -iname -mount | getitimer() |
<endian.h> | F_OFD_GETLK, F_OFD_SETLK, F_OFD_SETLKW | gettext | getmsg() |
ffsl(), ffsll() (XSI) | fopen() "ex" | head -c | getpmsg() |
getentropy() | f_owner_ex, F_OWNER_PGRP, F_OWNER_PID | logger -fipt | gets() |
getlocalename_l() | FTW_XDEV (XSI) | mailx -E | gettimeofday() |
getresgid() (XSI) | GETENTROPY_MAX | make features | ioctl() |
getresuid() (XSI) | LC_GLOBAL_LOCALE | msgfmt | isascii() |
<libintl.h> | LOG_UPTO (XSI) | ngettext | isastream() |
memmem() [1] | M_1_SQRTPI, M_EGAMMA, M_PHI | ps -w | _longjmp() |
mkostemp() | MAP_ANONYMOUS | readlink | posix_trace_*() |
pipe2() | M_*l <math.h> | realpath | pthread_getconcurrency() |
posix_close() | MSG_CMSG_CLOEXEC, MSG_CMSG_CLOFORK | realpath -Ee | pthread_setconcurrency() |
posix_devctl() (DC) | M_SQRT1_3, M_SQRT3 | read -d | putmsg() |
posix_getdents() | NSIG_MAX | rm -d | putpmsg() |
posix_spawn_file_actions_addchdir() (SPN) | O_CLOFORK | rm -v | rand_r() |
posix_spawn_file_actions_addfchdir() (SPN) | _PC_FALLOC | sed -E s///i | setitimer() |
ppoll() | _PC_TEXTDOMAIN_MAX | stty rows cols | _setjmp() |
pthread_cond_clockwait() | POSIX_CLOSE_RESTART | ssty size | setpgrp() |
pthread_mutex_clocklock() | _POSIX_DEVICE_CONTROL (DC) | tail -r | sighold() |
pthread_rwlock_clockrdlock() | _POSIX_FALLOC | test -ef -nt -ot > < | sigignore() |
pthread_rwlock_clockwrlock() | POSIX_SPAWN_SETSID (SPN) | timeout | siginterrupt() |
ptsname_r() (XSI) | PTHREAD_NULL | ulimit -HSacdnstvf | sigpause() |
qsort_r() | posix_tnode (XSI) | xargs -r0 | sigrelse() |
quick_exit() (C11) | reclen_t | xgettext | sigset() |
reallocarray() | REG_MINIMAL | tempnam() | |
secure_getenv() | _SC_DEVICE_CONTROL (DC) | test -a -o ( ) | |
sem_clockwait() | _SC_NPROCESSORS_CONF | toascii() | |
setresgid() (XSI) | _SC_NPROCESSORS_ONLN | _tolower() | |
setresuid() (XSI) | _SC_NSIG | _toupper() | |
sig2str() | SEEK_DATA, SEEK_HOLE | ulimit() | |
<stdalign.h> | SHM_FAILED (XSI) | utime() | |
<stdatomic.h> | SOCK_CLOEXEC, SOCK_CLOFORK, SOCK_NONBLOCK | fort77(1) | |
<stdnoreturn.h> | SO_DOMAIN, SO_PROTOCOL | qmove(1) | |
str2sig() | strftime %s %Ob %OB | qselect(1) | |
strlcat() | strptime %s %Ob %OB %Oh %F %g %G %u %V %z %Z | qalter(1) | |
strlcpy() | struct winsize | qmsg(1) | |
tcgetwinsize() | TEXTDOMAIN_MAX | qsig(1) | |
tcsetwinsize() | time_t 64-bit | qdel(1) | |
<threads.h> (C11) | tm_gmtoff, tm_zone | qrerun(1) | |
vasprintf() | WCOREDUMP | qstat(1) | |
<uchar.h> (C11) | qhold(1) | ||
wcslcat() | qrls(1) | ||
wcslcpy() | qsub(1) |
Green additions means the interface is implemented in Sortix.
Red additions means the interface will not be implemented in Sortix.
Orange additions means the interface is optional and will not be implemented in Sortix.
Black additions means the interface still needs to be implemented in Sortix.
Green removals means the interfaced was never implemented in Sortix.
Orange removals means the interface remains implemented in Sortix as extensions.
[1] The implementation has not yet merged to master and is not in the nigtly build.
Last updated: 2024-06-30
New Functions
_Fork()
Status: Austin Group Bug #62 implemented 2024-06-23 in Sortix.
#include <unistd.h> pid_t _Fork(void);
_Fork
is an async signal safe version of fork
that doesn't call
pthread_at_fork
handlers. Sortix doesn't have pthread_at_fork
and fork
just invokes _Fork
directly.
accept4()
Status: Austin Group Bug #62 implemented 2013-03-19 in Sortix.
#include <sys/socket.h> int accept4(int socket, struct sockaddr *restrict address, socklen_t *restrict address_len, int flag);
accept4
is like accept
but has a flags parameter that lets one set
SOCK_NONBLOCK
, SOCK_CLOEXEC
, and CLO_CLOFORK
.
aligned_alloc()
Status: C11 feature not yet implemented in Sortix.
#include <stdlib.h> void *aligned_alloc(size_t alignment, size_t size);
aligned_alloc
is a C11 function that allocates memory with the specified
alignment. This interface is not yet implemented in Sortix because the malloc
implementation does not yet support arbitrary alignment.
asprintf()
Status: Austin Group Bug #1496 implemented 2014-01-20 in Sortix.
#include <stdio.h> int asprintf(char **restrict ptr, const char *restrict format, ...); int vasprintf(char **restrict ptr, const char *restrict format, va_list ap);
asprintf
formats the string and allocates the appropriate memory with
malloc
.
dladdr()
Status: Austin Group Bug #993 implemented 2024-06-23 in Sortix.
#include <dlfcn.h> typedef struct { const char *dli_fname; void *dli_fbase; const char *dli_sname; void *dli_saddr; } Dl_info_t; int dladdr(const void *restrict addr, Dl_info_t *restrict dlip);
dladdr
resolves an address to the shared object containing that address. It's
unclear what value the Open Group saw in this interface since it only seems
useful for debugging. I wonder if it adds constraints on the dynamic linking
implementation. I can't think of anything useful a portable POSIX application
can do with this information, although the austin group bug suggests it can be
open files relative to the shared object (which seems a bit hacky).
Sortix does not have dynamic linking yet, but a stub dladdr
has been added
that fails at runtime.
dup3()
Status: Austin Group Bug #411 implemented 2013-09-23 in Sortix.
#include <unistd.h> int dup3(int fildes, int fildes2, int flag);
dup3
duplicates a file descriptor and optionally sets the FD_NONBOCK
,
FD_CLOEXEC
, and FD_CLOFORK
flags on the new file descriptor.
<endian.h>
Status: Austin Group Bug #162 implemented 2013-02-14 in Sortix.
#include <endian.h> #define BYTE_ORDER [LITTLE_ENDIAN or BIG_ENDIAN] #define LITTLE_ENDIAN [...] #define BIG_ENDIAN [...] int16_t htobe16(uint16_t host_16bits); uint32_t htobe32(uint32_t host_32bits); uint64_t htobe64(uint64_t host_64bits); uint16_t htole16(uint16_t host_16bits); uint32_t htole32(uint32_t host_32bits); uint64_t htole64(uint64_t host_64bits);
<endian.h>
solves all of your endian conversion needs.
ffsl(), ffsll()
Status: Austin Group Bug #617 implemented 2013-07-12 in Sortix.
#include <strings.h> int ffsl(long i); int ffsll(long long i);
ffsl()
and ffsll()
are long and long long variants of ffs
that returns
the index of the first set bit (counting from the least significant bit starting
from 1).
getentropy()
Status: Austin Group Bug #1134 implemented 2014-07-14 in Sortix.
#include <limits.h> #define GETENTROPY_MAX [...] #include <unistd.h> int getentropy(void *buffer, size_t length);
getentropy
returns up to GETENTROPY_MAX
of cryptographically secure
randomness, useful to initialize a random number generator.
Sortix has all the kernel facilities to supply random numbers, but it does not yet have a method for gathering entropy, and the randomness is only secure if you manually seeded your operating system entropy.
getlocalename_l()
Status: Austin Group Bug #1220 implemented 2024-06-23 in Sortix.
#include <locale.h> #define LC_GLOBAL_LOCALE [...] const char *getlocalename_l(int category, locale_t locobj);
getlocalename_l
returns the name of the locale specified by the category and
locale object (or LC_GLOBAL_LOCALE
for the global locale).
Sortix doesn't fully implement locales but the function behaves appropriately for the default C / POSIX locale.
getresgid(), getresuid(), setresgid(), setresuid() (XSI)
Status: Austin Group Bug #1344 & #1666 optionally not implemented in Sortix.
#include <unistd.h> int getresgid(gid_t *restrict rgid, gid_t *restrict egid, gid_t *restrict sgid); int getresuid(uid_t *restrict ruid, uid_t *restrict euid, uid_t *restrict suid); int setresgid(gid_t rgid, gid_t egid, gid_t sgid); int setresuid(uid_t ruid, uid_t euid, uid_t suid);
These are optional XSI extensions for getting and setting the user and group values atomically for the process.
Sortix is not yet secure for multi-user uses and intentionally does not have the concept of setuid/setgid executables, and therefore does not have the concept of the saved uid/gids. For these reasons, implementing these optional system calls has been postponed.
<libintl.h>
Status: Austin Group Bug #1122 implemented a long time in Sortix by porting gettext.
#include <libintl.h> char *bindtextdomain(const char *, const char *); char *bind_textdomain_codeset(const char *, const char *); char *dcgettext(const char *, const char *, int); char *dcgettext_l(const char *, const char *, int, locale_t); char *dcngettext(const char *, const char *, const char *, unsigned long int, int); char *dcngettext_l(const char *, const char *, const char *, unsigned long int, int, locale_t); char *dgettext(const char *, const char *); char *dgettext_l(const char *, const char *, locale_t); char *dngettext(const char *, const char *, const char *, unsigned long int); char *dngettext_l(const char *, const char *, const char *, unsigned long int, locale_t); char *gettext(const char *); char *gettext_l(const char *, locale_t); char *ngettext(const char *, const char *, unsigned long int); char *ngettext_l(const char *, const char *, unsigned long int, locale_t); char *textdomain(const char *);
POSIX has standardized the key interfaces in libintl from gettext, which Sortix has had a port of for a long time.
memmem()
Status: Austin Group Bug #1061 implemented in the Sortix volatile build and is not merged to master yet.
#include <string.h> void *memmem(const void *haystack, size_t haystacklen, const void *needle, size_t needlelen);
This interface has not yet been merged to Sortix master and is not available in the nightly builds, but is available in the volatile builds.
I still need to remember the fast algorithm for memmem
which I learned in
university and I'm having fun figuring it out from first principles, but I
didn't solve it fully yet, and decided to focus on the rest of POSIX 2024.
No spoilers please but come back later. :)
mkostemp()
Status: Austin Group Bug #411 & #1318 & #1350 implemented 2015-02-06 in Sortix.
#include <stdlib.h> int mkostemp(char *template, int flag);
mkostemp()
creates a temporary file like mkstemp
but allows one to set
additional O_
flags on the open()
call.
pipe2()
Status: Austin Group Bug #411 implemented 2024-01-15 in Sortix.
#include <unistd.h> int pipe2(int fildes[2], int flag);
pipe2()
creates a pair of file descriptors constituting a pipe like pipe()
but lets one set the O_NONBLOCK
, O_CLOEXEC
, and O_CLOFORK
flags.
posix_close()
Status: Austin Group Bug #529 will not be implemented in Sortix.
#include <unistd.h> #define POSIX_CLOSE_RESTART [...] int posix_close(int fildes, int flag);
close()
should be used instead. POSIX 2024 defined this replacement interface
because some broken legacy operating systems could fail with EINTR
in
close()
on slow devices, instead of returning 0 and either completing the
operation in the background or aborting it.
However, this means most programs need to be updated to use the more complicated
alternative function instead for no practical gain, which isn't going to happen.
The standard has added a lot of complexity where none needs to exist, which is
rejected in Sortix. I don't want to contribute to this mess. close()
never
fails with EINTR
on Sortix.
posix_devctl() (DC)
Status: Austin Group Bug #729 is optional and will not be implemented in Sortix.
#include <devctl.h> int posix_devctl(int fildes, int dcmd, void *restrict dev_data_ptr, size_t nbyte, int *restrict dev_info_ptr);
ioctl()
should be used instead. POSIX 2024 defined this optional function as a
replacement for ioctl()
but never defined any way for portable applications to
actually use it. I tend to like explicitly specifying the size of the input
object. The dev_info_ptr
parameter is especially useless as its semantics are
not defined, and often the desired output does not necessarily fit in an int
type.
The ioctl()
interface is fine and this alternative function is rejected in
Sortix as it is optional in POSIX 2024.
posix_getdents()
Status: Austin Group Bug #697 won't be implemented for now in Sortix.
#include <dirent.h> typedef [...] reclen_t; struct posix_dent { ino_t d_ino; reclen_t d_reclen; unsigned char d_type; char d_name[]; }; ssize_t posix_getdents(int fildes, void *buf, size_t nbyte, int flags);
readdir()
should be used instead. readdirents()
is a similar Sortix-specific
system call that will likely be replaced with something else in the future. This
new posix_getdents
function is due to a mess of divergent getdents()
functions. It is unfortunate they used struct posix_dent
instead of
struct dirent
as they did not want to mandate the addition of the common
d_type
field in struct dirent
. However, posix_getdents
is decent and may
be implemented in the future in Sortix.
posix_spawn_file_actions_addchdir(), posix_spawn_file_actions_addfchdir() (SPN)
Status: Austin Group Bug #1208 is optional and is not implemented in Sortix.
#include <spawn.h> int posix_spawn_file_actions_addchdir(posix_spawn_file_actions_t *restrict file_actions, const char *restrict path); int posix_spawn_file_actions_addfchdir(posix_spawn_file_actions_t *file_actions, int fildes);
These optional new interfaces set the working directory for the new process
when using posix_spawn
. Sortix does not implement the optional posix_spawn
interface at this time.
ppoll()
Status: Austin Group Bug #1263 implemented 2012-12-29 in Sortix.
#include <poll.h> int ppoll(struct pollfd fds[], nfds_t nfds, const struct timespec *restrict timeout, const sigset_t *restrict sigmask);
ppoll
is like poll
but atomically applies another signal mask while waiting
for the requested conditions to occur. Importantly ppoll
makes it possible to
safely handle signals in the main loop without race conditions. All signals can
be blocked by default and then unblocked in the ppoll
invocation, where the
signal handlers run without racing with other code at a safe point, and the
ppoll
loop will wake afterwards so the signal can be fully handled.
pthread_cond_clockwait(), pthread_mutex_clocklock(), pthread_rwlock_clockrdlock(), pthread_rwlock_clockwrlock(), sem_clockwait()
Status: Austin Group Bug #1216 implemented 2024-06-23 in Sortix.
#include <pthread.h> int pthread_cond_clockwait(pthread_cond_t *restrict cond, pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); int pthread_mutex_clocklock(pthread_mutex_t *restrict mutex, clockid_t clock_id, const struct timespec *restrict abstime); int pthread_rwlock_clockrdlock(pthread_rwlock_t *restrict rwlock, clockid_t clock_id, const struct timespec *restrict abstime); int pthread_rwlock_clockwrlock(pthread_rwlock_t *restrict rwlock, clockid_t clock_id, const struct timespec *restrict abstime); #include <semaphore.h> int sem_clockwait(sem_t *restrict sem, clockid_t clock_id, const struct timespec *restrict abstime);
These interfaces wait for a thread operation with an absolute timeout, but allow
one to specify which clock to use. Importantly this lets one specify the
newly-mandatory CLOCK_MONOTONIC
which lets one calculate the correct time to
wake, without worrying about CLOCk_REALTIME
moving backwards or forwards.
ptsname_r() (XSI)
Status: Austin Group Bug #508 implemented 2016-11-29 in Sortix.
#include <stdlib.h> int ptsname_r(int fildes, char *name, size_t namesize);
ptsname_r
is a thread-safe version of ptsname
that lets one obtain the name
of an allocated pseudo-terminal.
qsort_r()
Status: Austin Group Bug #900 implemented 2024-03-09 in Sortix.
#include <stdlib.h> void qsort_r(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *, void *), void *arg);
qsort_r
is a version of qsort
that lets one provide a context pointer to the
comparison function, which is a thread-safe way to provide additional data to
the comparison function
reallocarray()
Status: Austin Group Bug #1218 implemented 2014-06-20 in Sortix.
#include <stdlib.h> void *reallocarray(void *ptr, size_t nelem, size_t elsize);
reallocarray
reallocates an array with a multiplication check to catch
overflows, much like how calloc
provides a multiplication check for malloc
.
reallocarray
can also be used for the initial allocation without the zeroing
semantics of calloc
.
secure_getenv()
Status: Austin Group Bug #922 implemented 2024-06-23 in Sortix.
#include <stdlib.h> char *secure_getenv(const char *name);
secure_getenv
is like getenv
but returns NULL if the program is a setuid
or setgid
executable where the environment is not trusted. Sortix
intentionally does not the setuid
/setgid
executable concept as a security
improvement and secure_getenv
is an alias for getenv
.
sig2str(), str2sig()
Status: Austin Group Bug #1138 implemented 2024-06-23 in Sortix.
#include <signal.h> int sig2str(int signum, char *str); int str2sig(const char *restrict str, int *restrict pnum);
sig2str
provides the symbolic "FOO"
string name of the SIGFOO
value, and
str2sig
returns the value of the SIGFOO
signal by its symbolic "FOO"
string name.
I love this. We need it for errno
too. Bonus points if we're able to enumerate
all the available signal and errno values.
<stdalign.h> (C11)
Status: C11 feature implemented LONG AGO in Sortix.
#include <stdalign.h> #define alignas _Alignas #define alignof _Alignof #define __alignas_is_defined 1 #define __alignof_is_defined 1
This header adds the new alignas
and alignof
keywords in C11. Sortix gets
this header via GCC.
<stdatomic.h> (C11)
Status: C11 feature implemented LONG AGO in Sortix.
#include <stdatomic.h> struct atomic_flag { ... }; typedef atomic_foo _Atomic foo; enum memory_order { memory_order_relaxed, memory_order_consume, memory_order_acquire, memory_order_release, memory_order_acq_rel, memory_order_seq_cst }; #define ATOMIC_{BOOL,CHAR,CHAR16_T,CHAR32_T,WCHAR_T,SHORT,INT,LONG,LLONG,POINTER}_LOCK_FREE [...] #define ATOMIC_FLAG_INIT [...] #define ATOMIC_VAR_INIT(value) [...] /* Obsolescent */ #define kill_dependency() [...] _Bool atomic_compare_exchange_strong(volatile A *, C *, C); _Bool atomic_compare_exchange_strong_explicit(volatile A *, C *, C, memory_order, memory_order); _Bool atomic_compare_exchange_weak(volatile A *, C *, C); _Bool atomic_compare_exchange_weak_explicit(volatile A *, C *, C, memory_order, memory_order); C atomic_exchange(volatile A *, C); C atomic_exchange_explicit(volatile A *, C, memory_order); C atomic_fetch_add(volatile A *, M); C atomic_fetch_add_explicit(volatile A *, M, memory_order); C atomic_fetch_and(volatile A *, M); C atomic_fetch_and_explicit(volatile A *, M, memory_order); C atomic_fetch_or(volatile A *, M); C atomic_fetch_or_explicit(volatile A *, M, memory_order); C atomic_fetch_sub(volatile A *, M); C atomic_fetch_sub_explicit(volatile A *, M, memory_order); C atomic_fetch_xor(volatile A *, M); C atomic_fetch_xor_explicit(volatile A *, M, memory_order); void atomic_init(volatile A *, C); _Bool atomic_is_lock_free(const volatile A *); C atomic_load(const volatile A *); C atomic_load_explicit(const volatile A *, memory_order); void atomic_store(volatile A *, C); void atomic_store_explicit(volatile A *, C, memory_order); void atomic_flag_clear(volatile atomic_flag *); void atomic_flag_clear_explicit(volatile atomic_flag *, memory_order); _Bool atomic_flag_test_and_set(volatile atomic_flag *); _Bool atomic_flag_test_and_set_explicit( volatile atomic_flag *, memory_order); void atomic_signal_fence(memory_order); void atomic_thread_fence(memory_order);
This header provides the C11 atomic operations. Sortix gets this header via GCC.
<stdnoreturn.h> (C11)
Status: C11 feature implemented LONG AGO in Sortix.
#include <sdtdnoreturn.h> #define noreturn _Noreturn
This header adds the new noreturn
keyword in C11 that marks a function as
never returning, allowing compiler optimizations. Sortix gets this header via
GCC.
strlcat(), strlcpy(), wcslcat(), wcslcpy()
Status: Austin Group Bug #986 implemented 2013-07-11 in Sortix.
#include <string.h> size_t strlcat(char *restrict dst, const char *restrict src, size_t dstsize); size_t strlcpy(char *restrict dst, const char *restrict src, size_t dstsize); #include <wchar.h> size_t wcslcat(wchar_t *restrict dst, const wchar_t *restrict src, size_t dstsize); size_t wcslcpy(wchar_t *restrict dst, const wchar_t *restrict src, size_t dstsize);
These are alternatives to strcpy
and strcat
that truncates the string if it
does not fit in the destination buffer, returning the originally intended string
length which lets one catch the overflow. These are useful for formatting
strings into fixed sized buffers, as opposed to strncpy
that might not null
terminate the string. Unbounded allocations should prefer strdup
, asprintf
,
or open_memstream
to ensure the allocation is done as part of the string
creation to avoid buffer overflows.
tcgetwinsize(), tcsetwinsize()
Status: Austin Group Bug #1151 implemented in the Sortix volatile build and is not merged to master yet.
#include <termios.h> struct winsize { unsigned short ws_row; unsigned short ws_col; }; int tcgetwinsize(int fildes, struct winsize *winsize_p); int tcsetwinsize(int fildes, const struct winsize *winsize_p);
These allow one to get and set the window size of a terminal, which is
especially useful for pseudo-terminals. tcgetwinsize
is implemented in
Sortix
but tcsetwinsize
has not been merged to master yet. It will be
merged as soon as an overnight volatile test build has completed without issue.
The Sortix struct winsize
uses size_t
instead of unsigned short and also
has the size_t ws_xpixel
and size_t ws_ypixel
fields. The structure should
probably be aligned with POSIX's data types in a future incompatible ABI change.
<threads.h> (C11)
Status: C11 feature not yet implemented in Sortix.
#include <threads.h> #define thread_local _Thread_local #define ONCE_FLAG_INIT [..] #define TSS_DTOR_ITERATIONS [...] typedef [...] cnd_t; typedef [...] mtx_t; typedef [...] once_flag; typedef [...] thrd_t; typedef [...] tss_t; typedef int (*thrd_start_t)(void*); enum { mtx_plain, mtx_recursive, mtx_timed, thrd_busy, thrd_error, thrd_nomem, thrd_success, thrd_timedout }; void call_once(once_flag *, void (*)(void)); int cnd_broadcast(cnd_t *); void cnd_destroy(cnd_t *); int cnd_init(cnd_t *); int cnd_signal(cnd_t *); int cnd_timedwait(cnd_t * restrict, mtx_t * restrict, int const struct timespec * restrict); int cnd_wait(cnd_t *, mtx_t *); void mtx_destroy(mtx_t *); int mtx_init(mtx_t *, int); int mtx_lock(mtx_t *); int mtx_timedlock(mtx_t * restrict, const struct timespec * restrict); int mtx_trylock(mtx_t *); int mtx_unlock(mtx_t *); int thrd_create(thrd_t *, thrd_start_t, void *); thrd_t thrd_current(void); int thrd_detach(thrd_t); int thrd_equal(thrd_t, thrd_t); _Noreturn void thrd_exit(int); int thrd_join(thrd_t, int *); int thrd_sleep(const struct timespec *, struct timespec *); void thrd_yield(void); int tss_create(tss_t *, tss_dtor_t); void tss_delete(tss_t); void *tss_get(tss_t); int tss_set(tss_t, void *);
This header adds the new C11 threads API. Sortix does not yet implement this API as nothing needs it yet but Sortix has the pthread API.
<uchar.h> (C11)
Status: C11 feature not yet implemented in Sortix.
#include <uchar.h> typedef uint_least16_t char16_t; typedef uint_least32_t char32_t; size_t c16rtomb(char *restrict, char16_t, mbstate_t *restrict); size_t c32rtomb(char *restrict, char32_t, mbstate_t *restrict); size_t mbrtoc16(char16_t *restrict, const char *restrict, size_t, mbstate_t *restrict); size_t mbrtoc32(char32_t *restrict, const char *restrict, size_t, mbstate_t *restrict);
These functions convert multibyte strings to and from 16-bit and 32-bit unicode
values. These functions don't seem particular useful as there are no APIs using
the char16_t
and char32_t
types. These are not yet implemented in Sortix
as nothing needs them.
New Features
A lot of new features have been added to the existing functions.
I'm yet to write sections for each of these features as I implement them in Sortix, but you can see their status in the above table. Please check back later as I'll update this page with the latest information as I continue to study POSIX.1-2024.
A few quick highlights:
bind() port 0
The bind()
system call is now defined to allocate a random available port when
the port number is set to 0.
FNMCASEFOLD, FNMIGNORECASE
The new fnmatch()
flags FNM_CASEFOLD
aka FNM_IGNORECASE
compares the
string case insensitively with the pattern.
F_OFD_GETLK, F_OFD_SETLK, F_OFD_SETLKW
POSIX has finally added per-file-descriptor advisory locks! POSIX has only ever
had process-scope advisory locks with broken semantics on close()
, which
I refused to implement in Sortix.
MAP_ANONYMOUS
The MAP_ANONYMOUS
aka MAP_ANON
flag is now standardized and lets one
allocate memory directly with mmap
without a backing file.
O_CLOFORK
The O_CLOFORK
open flag sets the FD_CLOFORK
file descriptor flag which
closes the file descriptor on fork()
in the new process.
Sortix has had this feature fully implemented since 2013 and nothing had to change to implement the POSIX 2024 specification of this feature. Curiously it appears that Linux is refusing to implement this feature and I never actually used it in Sortix.
SEEK_DATA, SEEK_HOLE
These constants let lseek
seek across unitialized sections of the file, which
exposes the ability for implementations to omit storing default-zero-initialized
sections of files.
time_t 64-bit
The 2038 32-bit time_t
apocalypse has been canceled to contain
SCP-8601.
New Utilities
A bunch of new utilities have been added along with a bunch of new options to existing utilities.
I'm yet to write sections for each of these features as I implement them in Sortix, but you can see their status in the above table. Please check back later as I'll update this page with the latest information as I continue to study POSIX.1-2024.
Removals
A lot of functions, features, and features have been declared obsolete and removed from the standard. This is a healthy part of the standard lifecycle where we gain a leaner standard and simpler future implementations. Sortix has benefited massively from not needing to implement legacy interfaces, which is why most of the removed interfaces were never implemented in Sortix in the first place.
Notably the removal of gettimeofday()
essentially completes the many year long
migration from the microsecond-precision struct timeval
to the new
nanosecond-precision struct timespec
. Meanwhile the removal of many old
signal functions completes the migration to the new real time signal function
family and sigset_t
.
A number of interfaces remain implemented in Sortix for various reasons:
asctime_r
,ctime_r
: The functions are considered deprecated and problematic in Sortix as they are poorly designed and the output format isn't very useful and they suffer from year 10000 problems. However, ports continue to rely too much on them rather than the C89strftime
and they cannot be removed at this time.gettimeofday
: Sortix uses exclusively nanosecond-precisionstruct timespec
in the system call API andclock_gettime()
is the modern replacement, butgettimeofday
remains extremely popular in the ports collection and removing it is impossible and counterproductive.ioctl
: It's positive news that POSIX is getting out of theioctl
business as they never defined any ways to actually use the API. Sortix retains the API as Sortix heavily relies on it to provide access to driver facilities and other purposes as extensions. POSIX instead inventedposix_devctl
without defining any ways to actually use it, instead of realizing they probably should just let implementations innovate and standardize the resulting consensus.rand_r
: This interface is part of the conspiracy against good randomness and you should usearc4random
instead (which POSIX failed to standardize but at at least we didn't get aposix_random
mess). Unfortunately this function cannot be removed as the ports tree relies too much on it, but Sortix libc will issue a warning whenever it is used.test -a -o ( )
: Honestly I was shocked to learn these features were removed from thetest
program in the shell (aka[
]
) as my scripts heavily rely on them. Sortix will continue to provide them as they are useful and are very much needed for compatibility with the ports collection.utime
: This second-precision interface has been replaced by the nanosecond precisionutimensat
interface, however it remains heavily used by the ports collection and cannot be removed at this time.