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-clean/options/posix/musl-generic-regex/glob.c mlibc-workdir/options/posix/musl-generic-regex/glob.c index 411f6a84..cbf0fd26 100644 --- mlibc-clean/options/posix/musl-generic-regex/glob.c +++ mlibc-workdir/options/posix/musl-generic-regex/glob.c @@ -18,6 +18,58 @@ struct match char name[]; }; +struct glob_context +{ + int (*errfunc)(const char *path, int err); + __typeof__(((glob_t *)0)->gl_opendir) opendir; + __typeof__(((glob_t *)0)->gl_readdir) readdir; + __typeof__(((glob_t *)0)->gl_closedir) closedir; + __typeof__(((glob_t *)0)->gl_stat) stat; + __typeof__(((glob_t *)0)->gl_lstat) lstat; +}; + +static void *default_opendir(const char *path) +{ + return opendir(path); +} + +#if defined(_GNU_SOURCE) +static struct dirent *default_readdir(void *dir) +{ + return readdir(dir); +} + +static int default_stat(const char *path, struct stat *st) +{ + return stat(path, st); +} + +static int default_lstat(const char *path, struct stat *st) +{ + return lstat(path, st); +} +#else +static void *default_readdir(void *dir) +{ + return readdir(dir); +} + +static int default_stat(const char *path, void *st) +{ + return stat(path, st); +} + +static int default_lstat(const char *path, void *st) +{ + return lstat(path, st); +} +#endif + +static void default_closedir(void *dir) +{ + closedir(dir); +} + static int append(struct match **tail, const char *name, size_t len, int mark) { struct match *new = malloc(sizeof(struct match) + len + 2); @@ -33,7 +85,7 @@ static int append(struct match **tail, const char *name, size_t len, int mark) return 0; } -static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (*errfunc)(const char *path, int err), struct match **tail) +static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, struct glob_context *context, struct match **tail) { /* If GLOB_MARK is unused, we don't care about type. */ if (!type && !(flags & GLOB_MARK)) type = DT_REG; @@ -101,12 +153,12 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* * or if that fails, use lstat for determining existence to * avoid false negatives in the case of broken symlinks. */ struct stat st; - if ((flags & GLOB_MARK) && (!type||type==DT_LNK) && !stat(buf, &st)) { + if ((flags & GLOB_MARK) && (!type||type==DT_LNK) && !context->stat(buf, &st)) { if (S_ISDIR(st.st_mode)) type = DT_DIR; else type = DT_REG; } - if (!type && lstat(buf, &st)) { - if (errno!=ENOENT && (errfunc(buf, errno) || (flags & GLOB_ERR))) + if (!type && context->lstat(buf, &st)) { + if (errno!=ENOENT && (context->errfunc(buf, errno) || (flags & GLOB_ERR))) return GLOB_ABORTED; return 0; } @@ -125,15 +177,15 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* saved_sep = '\\'; } } - DIR *dir = opendir(pos ? buf : "."); + void *dir = context->opendir(pos ? buf : "."); if (!dir) { - if (errfunc(buf, errno) || (flags & GLOB_ERR)) + if (context->errfunc(buf, errno) || (flags & GLOB_ERR)) return GLOB_ABORTED; return 0; } int old_errno = errno; struct dirent *de; - while (errno=0, de=readdir(dir)) { + while (errno=0, de=context->readdir(dir)) { /* Quickly skip non-directories when there's pattern left. */ if (p2 && de->d_type && de->d_type!=DT_DIR && de->d_type!=DT_LNK) continue; @@ -158,16 +210,16 @@ static int do_glob(char *buf, size_t pos, int type, char *pat, int flags, int (* memcpy(buf+pos, de->d_name, l+1); if (p2) *p2 = saved_sep; - int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, errfunc, tail); + int r = do_glob(buf, pos+l, de->d_type, p2 ? p2 : "", flags, context, tail); if (r) { - closedir(dir); + context->closedir(dir); return r; } } int readerr = errno; if (p2) *p2 = saved_sep; - closedir(dir); - if (readerr && (errfunc(buf, errno) || (flags & GLOB_ERR))) + context->closedir(dir); + if (readerr && (context->errfunc(buf, errno) || (flags & GLOB_ERR))) return GLOB_ABORTED; errno = old_errno; return 0; @@ -228,13 +280,19 @@ static int expand_tilde(char **pat, char *buf, size_t *pos) int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, int err), glob_t *restrict g) { struct match head = { .next = NULL }, *tail = &head; + struct glob_context context = { + .errfunc = errfunc ? errfunc : ignore_err, + .opendir = (flags & GLOB_ALTDIRFUNC) ? g->gl_opendir : default_opendir, + .readdir = (flags & GLOB_ALTDIRFUNC) ? g->gl_readdir : default_readdir, + .closedir = (flags & GLOB_ALTDIRFUNC) ? g->gl_closedir : default_closedir, + .stat = (flags & GLOB_ALTDIRFUNC) ? g->gl_stat : default_stat, + .lstat = (flags & GLOB_ALTDIRFUNC) ? g->gl_lstat : default_lstat, + }; size_t cnt, i; size_t offs = (flags & GLOB_DOOFFS) ? g->gl_offs : 0; int error = 0; char buf[PATH_MAX]; - if (!errfunc) errfunc = ignore_err; - if (!(flags & GLOB_APPEND)) { g->gl_offs = offs; g->gl_pathc = 0; @@ -250,7 +308,7 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && *p == '~') error = expand_tilde(&s, buf, &pos); if (!error) - error = do_glob(buf, pos, 0, s, flags, errfunc, &tail); + error = do_glob(buf, pos, 0, s, flags, &context, &tail); free(p); } 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',