diff --git mlibc-clean/options/glibc/generic/stdio_ext.cpp mlibc-workdir/options/glibc/generic/stdio_ext.cpp index ccb37257..3dfa27af 100644 --- mlibc-clean/options/glibc/generic/stdio_ext.cpp +++ mlibc-workdir/options/glibc/generic/stdio_ext.cpp @@ -71,14 +71,38 @@ size_t __freadahead(FILE *file_base) { return file_base->__valid_limit - file_base->__offset; } -const char *__freadptr(FILE *, size_t *) { - __ensure(!"Not implemented"); - __builtin_unreachable(); +const char *__freadptr(FILE *file_base, size_t *size) { + if(file_base->__io_mode != 0) { + mlibc::infoLogger() << "mlibc: __freadptr() called but file is not open for reading" << frg::endlog; + *size = 0; + return nullptr; + } + + if(file_base->__unget_ptr != file_base->__buffer_ptr) { + *size = file_base->__buffer_ptr - file_base->__unget_ptr; + return file_base->__unget_ptr; + } + + if(file_base->__offset == file_base->__valid_limit) { + *size = 0; + return nullptr; + } + + *size = file_base->__valid_limit - file_base->__offset; + return file_base->__buffer_ptr + file_base->__offset; } -void __freadptrinc(FILE *, size_t) { - __ensure(!"Not implemented"); - __builtin_unreachable(); +void __freadptrinc(FILE *file_base, size_t increment) { + size_t unget_size = file_base->__buffer_ptr ? file_base->__buffer_ptr - file_base->__unget_ptr : 0; + if(increment <= unget_size) { + file_base->__unget_ptr += increment; + return; + } + + increment -= unget_size; + file_base->__unget_ptr = file_base->__buffer_ptr; + __ensure(file_base->__offset + increment <= file_base->__valid_limit); + file_base->__offset += increment; } void __fseterr(FILE *file_base) { @@ -87,4 +111,3 @@ void __fseterr(FILE *file_base) { // set the error indicator for the stream file->__status_bits |= __MLIBC_ERROR_BIT; } - diff --git mlibc-clean/options/internal/generic/threads.cpp mlibc-workdir/options/internal/generic/threads.cpp index 2b9abbc0..0be01957 100644 --- mlibc-clean/options/internal/generic/threads.cpp +++ mlibc-workdir/options/internal/generic/threads.cpp @@ -269,11 +269,16 @@ int thread_mutex_destroy(struct __mlibc_mutex *mutex) { int thread_mutex_timedlock(struct __mlibc_mutex *mutex, const struct timespec *__restrict abstime, clockid_t clockid) { unsigned int this_tid = mlibc::this_tid(); unsigned int expected = 0; + bool contended = false; while(true) { if(!expected) { // Try to take the mutex here. + unsigned int desired = this_tid; + // Preserve the waiters bit after contention, as other waiters may still be asleep. + if(contended) + desired |= __mlibc_mutex::mutex_waiters_bit; if(__atomic_compare_exchange_n(&mutex->__mlibc_state, - &expected, this_tid | __mlibc_mutex::mutex_waiters_bit, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { + &expected, desired, false, __ATOMIC_ACQUIRE, __ATOMIC_ACQUIRE)) { __ensure(!mutex->__mlibc_recursion); mutex->__mlibc_recursion = 1; return 0; @@ -289,6 +294,8 @@ int thread_mutex_timedlock(struct __mlibc_mutex *mutex, const struct timespec *_ } } + contended = true; + // Wait on the futex if the waiters flag is set. if(expected & __mlibc_mutex::mutex_waiters_bit) { int e; diff --git mlibc-clean/options/internal/include/mlibc/allocator.hpp mlibc-workdir/options/internal/include/mlibc/allocator.hpp index d5496df8..4dac6dbd 100644 --- mlibc-clean/options/internal/include/mlibc/allocator.hpp +++ mlibc-workdir/options/internal/include/mlibc/allocator.hpp @@ -11,6 +11,8 @@ struct VirtualAllocator { public: + static constexpr size_t num_buckets = 14; + uintptr_t map(size_t length); void unmap(uintptr_t address, size_t length); diff --git mlibc-clean/options/linux/generic/malloc.cpp mlibc-workdir/options/linux/generic/malloc.cpp index 065de6c1..10c73955 100644 --- mlibc-clean/options/linux/generic/malloc.cpp +++ mlibc-workdir/options/linux/generic/malloc.cpp @@ -1,7 +1,13 @@ -#include +#include #include +#include -void *memalign(size_t, size_t) { - __ensure(!"Not implemented"); - __builtin_unreachable(); +void *memalign(size_t alignment, size_t size) { + void *ptr; + int ret = posix_memalign(&ptr, alignment, size); + if(ret) { + errno = ret; + return nullptr; + } + return ptr; } diff --git mlibc-clean/options/posix/generic/monetary.cpp mlibc-workdir/options/posix/generic/monetary.cpp index 55a567aa..d1d77873 100644 --- mlibc-clean/options/posix/generic/monetary.cpp +++ mlibc-workdir/options/posix/generic/monetary.cpp @@ -389,6 +389,8 @@ ssize_t strfmon_internal(char *__restrict s, size_t maxsize, mlibc::localeinfo * false, false, false, + false, + false, opts ); diff --git mlibc-clean/options/posix/include/bits/posix/posix_stdio.h mlibc-workdir/options/posix/include/bits/posix/posix_stdio.h index f0d6edd1..ab57b6b1 100644 --- mlibc-clean/options/posix/include/bits/posix/posix_stdio.h +++ mlibc-workdir/options/posix/include/bits/posix/posix_stdio.h @@ -63,6 +63,7 @@ char *fgetln(FILE *__stream, size_t *__size); #endif /* !__MLIBC_ABI_ONLY */ #if defined(_GNU_SOURCE) +#define RENAME_NOREPLACE (1 << 0) #define RENAME_EXCHANGE (1 << 1) /* GNU extensions */ @@ -97,4 +98,3 @@ FILE *fopencookie(void *__restrict __cookie, const char *__restrict __mode, cook #endif /* _MLIBC_POSIX_STDIO_H */ - diff --git mlibc-workdir/tests/glibc/memalign.c mlibc-workdir/tests/glibc/memalign.c new file mode 100644 index 00000000..0b3a1581 --- /dev/null +++ mlibc-workdir/tests/glibc/memalign.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include + +int main(void) { + void *p; + + errno = 0; + p = memalign(256, 1); + assert(p != NULL); + assert((uintptr_t)p % 256 == 0); + free(p); + + errno = 0; + p = memalign(3, 1); + assert(p == NULL); + assert(errno == EINVAL); + + return 0; +} diff --git mlibc-clean/tests/meson.build mlibc-workdir/tests/meson.build index 85b967c9..f555a1ec 100644 --- mlibc-clean/tests/meson.build +++ mlibc-workdir/tests/meson.build @@ -190,6 +190,7 @@ all_test_cases = [ 'glibc/rpmatch', 'glibc/strverscmp', 'glibc/memmem', + 'glibc/memalign', 'glibc/stdio_ext', 'glibc/_dl_find_object', 'glibc/shadow',