Skip to content

Commit 0f4dd06

Browse files
authored
Merge pull request managarm#1729 from no92/aio
2 parents 816e80c + 242f7de commit 0f4dd06

30 files changed

Lines changed: 1569 additions & 6 deletions

File tree

.github/workflows/ci.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ jobs:
1818
compiler: clang
1919
name: Build mlibc
2020
runs-on: ubuntu-latest
21-
container: debian:trixie
21+
container:
22+
image: debian:trixie
23+
options: --security-opt seccomp=unconfined --privileged
2224
steps:
2325
- name: Setup
2426
run: |

abis/ironclad/aio.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef _ABIBITS_AIO_H
2+
#define _ABIBITS_AIO_H
3+
4+
#include <abi-bits/sigevent.h>
5+
#include <bits/off_t.h>
6+
#include <bits/size_t.h>
7+
#include <bits/ssize_t.h>
8+
9+
#define AIO_CANCELED 0
10+
#define AIO_NOTCANCELED 1
11+
#define AIO_ALLDONE 2
12+
13+
#define LIO_READ 0
14+
#define LIO_WRITE 1
15+
#define LIO_NOP 2
16+
17+
#define LIO_WAIT 0
18+
#define LIO_NOWAIT 1
19+
20+
struct aiocb {
21+
int aio_fildes;
22+
off_t aio_offset;
23+
volatile void *aio_buf;
24+
size_t aio_nbytes;
25+
int aio_reqprio;
26+
struct sigevent aio_sigevent;
27+
int aio_lio_opcode;
28+
int __state;
29+
ssize_t __res;
30+
int __err;
31+
void *__ctx;
32+
}
33+
#if defined(__m68k__)
34+
__attribute__((aligned(4)))
35+
#endif /* defined(__m68k__) */
36+
;
37+
38+
#endif /* _ABIBITS_AIO_H */

abis/linux/aio.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
#ifndef _ABIBITS_AIO_H
2+
#define _ABIBITS_AIO_H
3+
4+
#include <abi-bits/sigevent.h>
5+
#include <bits/off_t.h>
6+
#include <bits/size_t.h>
7+
#include <bits/ssize_t.h>
8+
9+
#define AIO_CANCELED 0
10+
#define AIO_NOTCANCELED 1
11+
#define AIO_ALLDONE 2
12+
13+
#define LIO_READ 0
14+
#define LIO_WRITE 1
15+
#define LIO_NOP 2
16+
17+
#define LIO_WAIT 0
18+
#define LIO_NOWAIT 1
19+
20+
struct aiocb {
21+
int aio_fildes;
22+
off_t aio_offset;
23+
volatile void *aio_buf;
24+
size_t aio_nbytes;
25+
int aio_reqprio;
26+
struct sigevent aio_sigevent;
27+
int aio_lio_opcode;
28+
int __state;
29+
ssize_t __res;
30+
int __err;
31+
void *__ctx;
32+
}
33+
#if defined(__m68k__)
34+
__attribute__((aligned(4)))
35+
#endif /* defined(__m68k__) */
36+
;
37+
38+
#endif /* _ABIBITS_AIO_H */

options/internal/include/mlibc/sysdep-signatures.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,14 @@ SYSDEP_FUNC(MqUnlink, const char *name);
266266
SYSDEP_FUNC(MqReceive, mqd_t mqdes, char *msg_ptr, size_t msg_len, unsigned *msg_prio);
267267
SYSDEP_FUNC(MqGetAttr, mqd_t mqdes, mq_attr *mqstat);
268268
SYSDEP_FUNC(MqSetAttr, mqd_t mqdes, const mq_attr *mqstat, mq_attr *omqstat);
269+
SYSDEP_FUNC(AioRead, struct aiocb *cb);
270+
SYSDEP_FUNC(AioWrite, struct aiocb *cb);
271+
SYSDEP_FUNC(AioFsync, int op, struct aiocb *cb);
272+
SYSDEP_FUNC(AioListio, int mode, struct aiocb *__restrict const list[], int n, struct sigevent *__restrict sevp);
273+
SYSDEP_FUNC(AioSuspend, const struct aiocb *const list[], int n, const struct timespec *ts);
274+
SYSDEP_FUNC(AioCancel, int fildes, struct aiocb *cb, int *result);
275+
SYSDEP_FUNC(AioError, const struct aiocb *cb, int *out);
276+
SYSDEP_FUNC(AioReturn, struct aiocb *cb, ssize_t *out);
269277
#endif // __MLIBC_POSIX_OPTION
270278

271279
#if __MLIBC_LINUX_OPTION

options/internal/include/mlibc/sysdep-tags.hpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,7 @@ struct RiscvFlushIcache {};
188188
#include <abi-bits/seek-whence.h>
189189
#include <abi-bits/socklen_t.h>
190190
#include <abi-bits/vm-flags.h>
191+
#include <abi-bits/aio.h>
191192
#include <bits/off_t.h>
192193
#include <bits/posix/stat.h>
193194
#include <bits/ssize_t.h>
@@ -556,6 +557,22 @@ struct MqReceive {};
556557
struct MqGetAttr {};
557558
// int sys_mq_set_attr(mqd_t mqdes, mq_attr *mqstat, mq_attr *omqstat);
558559
struct MqSetAttr {};
560+
// int sys_aio_read(struct aiocb *cb);
561+
struct AioRead {};
562+
// int sys_aio_write(struct aiocb *cb);
563+
struct AioWrite {};
564+
// int sys_aio_fsync(int op, struct aiocb *cb);
565+
struct AioFsync {};
566+
// int sys_aio_listio(int mode, struct aiocb *__restrict const list[], int n, struct sigevent *__restrict sevp);
567+
struct AioListio {};
568+
// int sys_aio_suspend(const struct aiocb *const list[], int n, const struct timespec *ts);
569+
struct AioSuspend {};
570+
// int sys_aio_cancel(int fildes, struct aiocb *cb, int *result);
571+
struct AioCancel {};
572+
// int sys_aio_error(const struct aiocb *cb, int *out);
573+
struct AioError {};
574+
// int sys_aio_return(struct aiocb *cb, ssize_t *out);
575+
struct AioReturn {};
559576
#endif // __MLIBC_POSIX_OPTION
560577

561578
#if __MLIBC_LINUX_OPTION

options/internal/include/mlibc/time-helpers.hpp

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#include <abi-bits/clockid_t.h>
44
#include <bits/ansi/timespec.h>
55
#include <bits/ensure.h>
6+
#include <frg/safe_int.hpp>
67
#include <mlibc/all-sysdeps.hpp>
78
#include <mlibc/debug.hpp>
89
#include <time.h>
@@ -16,7 +17,7 @@ inline bool time_absolute_to_relative(const clockid_t clock, const struct timesp
1617
constexpr long nanos_per_second = 1'000'000'000;
1718

1819
if (clock != CLOCK_REALTIME && clock != CLOCK_MONOTONIC) {
19-
mlibc::infoLogger() << "mlibc: time_relative_to_absolute() only supports CLOCK_REALTIME and CLOCK_MONOTONIC"
20+
mlibc::infoLogger() << "mlibc: time_absolute_to_relative() only supports CLOCK_REALTIME and CLOCK_MONOTONIC"
2021
<< frg::endlog;
2122
return false;
2223
}
@@ -25,8 +26,10 @@ inline bool time_absolute_to_relative(const clockid_t clock, const struct timesp
2526
if (mlibc::sysdep<ClockGet>(clock, &now.tv_sec, &now.tv_nsec))
2627
__ensure(!"sys_clock_get() failed");
2728

28-
reltime->tv_sec = abstime->tv_sec - now.tv_sec;
29-
reltime->tv_nsec = abstime->tv_nsec - now.tv_nsec;
29+
if (!frg::checked_sub(abstime->tv_sec, now.tv_sec, reltime->tv_sec))
30+
return false;
31+
if (!frg::checked_sub(abstime->tv_nsec, now.tv_nsec, reltime->tv_nsec))
32+
return false;
3033

3134
// Check if abstime has already passed.
3235
if (reltime->tv_sec < 0 || (reltime->tv_sec == 0 && reltime->tv_nsec < 0)) {
@@ -35,17 +38,64 @@ inline bool time_absolute_to_relative(const clockid_t clock, const struct timesp
3538
return true;
3639
} else if (reltime->tv_nsec >= nanos_per_second) {
3740
reltime->tv_nsec -= nanos_per_second;
38-
reltime->tv_sec++;
41+
if (!frg::checked_add(reltime->tv_sec, time_t{1}, reltime->tv_sec))
42+
return false;
3943
if (reltime->tv_nsec >= nanos_per_second)
4044
return false;
4145
} else if (reltime->tv_nsec < 0) {
4246
reltime->tv_nsec += nanos_per_second;
43-
reltime->tv_sec--;
47+
if (!frg::checked_sub(reltime->tv_sec, time_t{1}, reltime->tv_sec))
48+
return false;
4449
if (reltime->tv_nsec < 0)
4550
return false;
4651
}
4752

4853
return true;
4954
}
5055

56+
// Converts the relative time `reltime` to an absolute time `abstime`.
57+
// Returns false if the conversion failed (e.g. due to over-/underflow).
58+
inline bool time_relative_to_absolute(
59+
const clockid_t clock, const struct timespec *__restrict reltime, struct timespec *abstime
60+
) {
61+
constexpr long nanos_per_second = 1'000'000'000;
62+
63+
if (clock != CLOCK_REALTIME && clock != CLOCK_MONOTONIC) {
64+
mlibc::infoLogger()
65+
<< "mlibc: time_relative_to_absolute() only supports CLOCK_REALTIME and CLOCK_MONOTONIC"
66+
<< frg::endlog;
67+
return false;
68+
}
69+
70+
struct timespec now;
71+
if (mlibc::sysdep<ClockGet>(clock, &now.tv_sec, &now.tv_nsec))
72+
__ensure(!"sys_clock_get() failed");
73+
74+
// Add relative time to current time
75+
if (!frg::checked_add(now.tv_sec, reltime->tv_sec, abstime->tv_sec))
76+
return false;
77+
if (!frg::checked_add(now.tv_nsec, reltime->tv_nsec, abstime->tv_nsec))
78+
return false;
79+
80+
// Normalize nanoseconds
81+
if (abstime->tv_nsec >= nanos_per_second) {
82+
abstime->tv_nsec -= nanos_per_second;
83+
if (!frg::checked_add(abstime->tv_sec, time_t{1}, abstime->tv_sec))
84+
return false;
85+
if (abstime->tv_nsec >= nanos_per_second)
86+
return false;
87+
} else if (abstime->tv_nsec < 0) {
88+
abstime->tv_nsec += nanos_per_second;
89+
if (!frg::checked_sub(abstime->tv_sec, time_t{1}, abstime->tv_sec))
90+
return false;
91+
if (abstime->tv_nsec < 0)
92+
return false;
93+
}
94+
95+
if (now.tv_sec > 0 && reltime->tv_sec > 0 && abstime->tv_sec < 0)
96+
return false;
97+
98+
return true;
99+
}
100+
51101
} // namespace mlibc

options/posix/generic/aio.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
#include <aio.h>
2+
#include <bits/ensure.h>
3+
#include <errno.h>
4+
#include <limits.h>
5+
6+
#include <mlibc/all-sysdeps.hpp>
7+
8+
int aio_read(struct aiocb *cb) {
9+
if (cb->aio_nbytes > SSIZE_MAX) {
10+
errno = EINVAL;
11+
return -1;
12+
}
13+
14+
if (int e = mlibc::sysdep_or_enosys<AioRead>(cb); e) {
15+
errno = e;
16+
return -1;
17+
}
18+
return 0;
19+
}
20+
21+
int aio_write(struct aiocb *cb) {
22+
if (cb->aio_nbytes > SSIZE_MAX) {
23+
errno = EINVAL;
24+
return -1;
25+
}
26+
27+
if (int e = mlibc::sysdep_or_enosys<AioWrite>(cb); e) {
28+
errno = e;
29+
return -1;
30+
}
31+
return 0;
32+
}
33+
34+
int aio_fsync(int op, struct aiocb *cb) {
35+
if (int e = mlibc::sysdep_or_enosys<AioFsync>(op, cb); e) {
36+
errno = e;
37+
return -1;
38+
}
39+
return 0;
40+
}
41+
42+
int lio_listio(
43+
int mode, struct aiocb *__restrict const list[], int n, struct sigevent *__restrict sevp
44+
) {
45+
if (mode != LIO_WAIT && mode != LIO_NOWAIT) {
46+
errno = EINVAL;
47+
return -1;
48+
}
49+
50+
if (int e = mlibc::sysdep_or_enosys<AioListio>(mode, list, n, sevp); e) {
51+
errno = e;
52+
return -1;
53+
}
54+
return 0;
55+
}
56+
57+
int aio_suspend(const struct aiocb *const list[], int n, const struct timespec *ts) {
58+
if (int e = mlibc::sysdep_or_enosys<AioSuspend>(list, n, ts); e) {
59+
errno = e;
60+
return -1;
61+
}
62+
return 0;
63+
}
64+
65+
ssize_t aio_return(struct aiocb *cb) {
66+
ssize_t result = 0;
67+
if (int e = mlibc::sysdep_or_enosys<AioReturn>(cb, &result); e) {
68+
errno = e;
69+
return -1;
70+
}
71+
return result;
72+
}
73+
74+
int aio_error(const struct aiocb *cb) {
75+
int result = 0;
76+
if (int e = mlibc::sysdep_or_enosys<AioError>(cb, &result); e) {
77+
errno = e;
78+
return -1;
79+
}
80+
return result;
81+
}
82+
83+
int aio_cancel(int fildes, struct aiocb *cb) {
84+
if (cb && fildes != cb->aio_fildes) {
85+
errno = EINVAL;
86+
return -1;
87+
}
88+
89+
int result = 0;
90+
if (int e = mlibc::sysdep_or_enosys<AioCancel>(fildes, cb, &result); e) {
91+
errno = e;
92+
return -1;
93+
}
94+
return result;
95+
}

options/posix/include/aio.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#ifndef _AIO_H
2+
#define _AIO_H
3+
4+
#include <abi-bits/aio.h>
5+
#include <abi-bits/signal.h>
6+
#include <bits/ansi/timespec.h>
7+
#include <bits/off_t.h>
8+
#include <bits/posix/pthread_attr_t.h>
9+
#include <bits/size_t.h>
10+
#include <bits/ssize_t.h>
11+
12+
#ifdef __cplusplus
13+
extern "C" {
14+
#endif
15+
16+
#ifndef __MLIBC_ABI_ONLY
17+
18+
int aio_read(struct aiocb *__cb);
19+
int aio_write(struct aiocb *__cb);
20+
int aio_fsync(int __op, struct aiocb *__cb);
21+
22+
int lio_listio(int __mode, struct aiocb *__restrict const __list[], int __n, struct sigevent *__restrict __sevp);
23+
24+
ssize_t aio_return(struct aiocb *__cb);
25+
int aio_suspend(const struct aiocb *const __list[], int __nent, const struct timespec *__timeout);
26+
int aio_error(const struct aiocb *__cb);
27+
int aio_cancel(int __fildes, struct aiocb *__cb);
28+
29+
#endif /* !__MLIBC_ABI_ONLY */
30+
31+
#ifdef __cplusplus
32+
}
33+
#endif
34+
35+
#endif /* _AIO_H */
36+

options/posix/meson.build

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,7 @@ libc_sources += files(
6060
'generic/mqueue.cpp',
6161
'generic/utmpx.cpp',
6262
'generic/monetary.cpp',
63+
'generic/aio.cpp',
6364
)
6465

6566
if not headers_only
@@ -114,6 +115,7 @@ if not no_headers
114115
'include/tar.h',
115116
'include/cpio.h',
116117
'include/monetary.h',
118+
'include/aio.h',
117119
)
118120
install_headers(
119121
'include/arpa/inet.h',

scripts/header-abi-compare-config.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@ ignored_structs:
6666
- cmsghdr
6767

6868
# libc-level constructs that are allowed to differ, and probably do
69+
- aiocb
6970
- ifaddrs
7071
- lastlog
7172
- regmatch_t

0 commit comments

Comments
 (0)