diff --git a/arch/arm/atomic.h b/arch/arm/atomic.h index 302e6d8..738f528 100644 --- a/arch/arm/atomic.h +++ b/arch/arm/atomic.h @@ -103,6 +103,7 @@ static inline void a_store(volatile int *p, int x) static inline void a_spin() { + __k_cas(0, 0, &(int){0}); } static inline void a_crash() diff --git a/arch/arm/bits/alltypes.h.in b/arch/arm/bits/alltypes.h.in index 0d750cc..183c4c4 100644 --- a/arch/arm/bits/alltypes.h.in +++ b/arch/arm/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/i386/bits/alltypes.h.in b/arch/i386/bits/alltypes.h.in index 502c882..8ba8f6f 100644 --- a/arch/i386/bits/alltypes.h.in +++ b/arch/i386/bits/alltypes.h.in @@ -27,6 +27,8 @@ TYPEDEF long double float_t; TYPEDEF long double double_t; #endif +TYPEDEF struct { _Alignas(8) long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/microblaze/atomic.h b/arch/microblaze/atomic.h index 96265fe..abb79b5 100644 --- a/arch/microblaze/atomic.h +++ b/arch/microblaze/atomic.h @@ -97,6 +97,7 @@ static inline void a_store(volatile int *p, int x) static inline void a_spin() { + a_cas(&(int){0}, 0, 0); } static inline void a_crash() diff --git a/arch/microblaze/bits/alltypes.h.in b/arch/microblaze/bits/alltypes.h.in index 4657d14..a03e1b8 100644 --- a/arch/microblaze/bits/alltypes.h.in +++ b/arch/microblaze/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/mips/atomic.h b/arch/mips/atomic.h index 3ec0358..cc5bf49 100644 --- a/arch/mips/atomic.h +++ b/arch/mips/atomic.h @@ -137,6 +137,7 @@ static inline void a_store(volatile int *p, int x) static inline void a_spin() { + a_cas(&(int){0}, 0, 0); } static inline void a_crash() diff --git a/arch/mips/bits/alltypes.h.in b/arch/mips/bits/alltypes.h.in index 4657d14..a03e1b8 100644 --- a/arch/mips/bits/alltypes.h.in +++ b/arch/mips/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/or1k/atomic.h b/arch/or1k/atomic.h index 5b0411b..f9e6981 100644 --- a/arch/or1k/atomic.h +++ b/arch/or1k/atomic.h @@ -74,6 +74,7 @@ static inline void a_store(volatile int *p, int x) static inline void a_spin() { + a_cas(&(int){0}, 0, 0); } static inline void a_crash() diff --git a/arch/or1k/bits/alltypes.h.in b/arch/or1k/bits/alltypes.h.in index 0d750cc..183c4c4 100644 --- a/arch/or1k/bits/alltypes.h.in +++ b/arch/or1k/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/powerpc/atomic.h b/arch/powerpc/atomic.h index 1044886..1c50361 100644 --- a/arch/powerpc/atomic.h +++ b/arch/powerpc/atomic.h @@ -80,6 +80,7 @@ static inline void a_store(volatile int *p, int x) static inline void a_spin() { + a_cas(&(int){0}, 0, 0); } static inline void a_crash() diff --git a/arch/powerpc/bits/alltypes.h.in b/arch/powerpc/bits/alltypes.h.in index 378124c..ee7f137 100644 --- a/arch/powerpc/bits/alltypes.h.in +++ b/arch/powerpc/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/sh/atomic.h b/arch/sh/atomic.h index 93ab54f..b95bbff 100644 --- a/arch/sh/atomic.h +++ b/arch/sh/atomic.h @@ -53,6 +53,7 @@ static inline void a_dec(volatile int *x) static inline void a_spin() { + a_cas(&(int){0}, 0, 0); } static inline void a_crash() diff --git a/arch/sh/bits/alltypes.h.in b/arch/sh/bits/alltypes.h.in index 378124c..ee7f137 100644 --- a/arch/sh/bits/alltypes.h.in +++ b/arch/sh/bits/alltypes.h.in @@ -13,6 +13,8 @@ TYPEDEF unsigned wint_t; TYPEDEF float float_t; TYPEDEF double double_t; +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/arch/x32/bits/alltypes.h.in b/arch/x32/bits/alltypes.h.in index 8930efa..8e396c9 100644 --- a/arch/x32/bits/alltypes.h.in +++ b/arch/x32/bits/alltypes.h.in @@ -18,6 +18,8 @@ TYPEDEF float float_t; TYPEDEF double double_t; #endif +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long long time_t; TYPEDEF long long suseconds_t; diff --git a/arch/x86_64/bits/alltypes.h.in b/arch/x86_64/bits/alltypes.h.in index 34b7d6a..7b4f3e7 100644 --- a/arch/x86_64/bits/alltypes.h.in +++ b/arch/x86_64/bits/alltypes.h.in @@ -18,6 +18,8 @@ TYPEDEF float float_t; TYPEDEF double double_t; #endif +TYPEDEF struct { long long __ll; long double __ld; } max_align_t; + TYPEDEF long time_t; TYPEDEF long suseconds_t; diff --git a/include/assert.h b/include/assert.h index ab745db..1ee02a4 100644 --- a/include/assert.h +++ b/include/assert.h @@ -8,6 +8,10 @@ #define assert(x) ((void)((x) || (__assert_fail(#x, __FILE__, __LINE__, __func__),0))) #endif +#ifndef __cplusplus +#define static_assert _Static_assert +#endif + #ifdef __cplusplus extern "C" { #endif diff --git a/include/float.h b/include/float.h index 2b2ad39..161e167 100644 --- a/include/float.h +++ b/include/float.h @@ -11,8 +11,10 @@ #define FLT_MANT_DIG 24 #define FLT_MIN_EXP (-125) #define FLT_MAX_EXP 128 +#define FLT_HAS_SUBNORM 1 #define FLT_DIG 6 +#define FLT_DECIMAL_DIG 9 #define FLT_MIN_10_EXP (-37) #define FLT_MAX_10_EXP 38 @@ -24,11 +26,16 @@ #define DBL_MANT_DIG 53 #define DBL_MIN_EXP (-1021) #define DBL_MAX_EXP 1024 +#define DBL_HAS_SUBNORM 1 #define DBL_DIG 15 +#define DBL_DECIMAL_DIG 17 #define DBL_MIN_10_EXP (-307) #define DBL_MAX_10_EXP 308 +#define LDBL_HAS_SUBNORM 1 +#define LDBL_DECIMAL_DIG DECIMAL_DIG + #include #endif diff --git a/include/malloc.h b/include/malloc.h index e69de29..35f8b19 100644 --- a/include/malloc.h +++ b/include/malloc.h @@ -0,0 +1,25 @@ +#ifndef _MALLOC_H +#define _MALLOC_H + +#ifdef __cplusplus +extern "C" { +#endif + +#define __NEED_size_t + +#include + +void *malloc (size_t); +void *calloc (size_t, size_t); +void *realloc (void *, size_t); +void free (void *); +void *valloc (size_t); +void *memalign(size_t, size_t); + +size_t malloc_usable_size(void *); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/include/stdalign.h b/include/stdalign.h index b6e50ae..2cc94be 100644 --- a/include/stdalign.h +++ b/include/stdalign.h @@ -1,6 +1,8 @@ #ifndef _STDALIGN_H #define _STDALIGN_H +#ifndef __cplusplus + /* this whole header only works in C11 or with compiler extensions */ #if __STDC_VERSION__ < 201112L && defined( __GNUC__) #define _Alignas(t) __attribute__((__aligned__(t))) @@ -9,6 +11,9 @@ #define alignas _Alignas #define alignof _Alignof + +#endif + #define __alignas_is_defined 1 #define __alignof_is_defined 1 diff --git a/include/stddef.h b/include/stddef.h index 0a32919..bd75385 100644 --- a/include/stddef.h +++ b/include/stddef.h @@ -10,6 +10,9 @@ #define __NEED_ptrdiff_t #define __NEED_size_t #define __NEED_wchar_t +#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L +#define __NEED_max_align_t +#endif #include diff --git a/include/stdnoreturn.h b/include/stdnoreturn.h index 60d924a..5c6aeeb 100644 --- a/include/stdnoreturn.h +++ b/include/stdnoreturn.h @@ -1,5 +1,7 @@ #ifndef _STDNORETURN_H #define _STDNORETURN_H +#ifndef __cplusplus #include #define noreturn _Noreturn #endif +#endif diff --git a/src/internal/pthread_impl.h b/src/internal/pthread_impl.h index 2d090f8..74c62cc 100644 --- a/src/internal/pthread_impl.h +++ b/src/internal/pthread_impl.h @@ -44,6 +44,7 @@ struct pthread { int exitlock[2]; int startlock[2]; unsigned long sigmask[_NSIG/8/sizeof(long)]; + void *stdio_locks; }; struct __timer { @@ -112,7 +113,7 @@ static inline void __wake(volatile void *addr, int cnt, int priv) { if (priv) priv = 128; if (cnt<0) cnt = INT_MAX; - __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -EINVAL || + __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); } diff --git a/src/internal/stdio_impl.h b/src/internal/stdio_impl.h index 79be9fd..d659522 100644 --- a/src/internal/stdio_impl.h +++ b/src/internal/stdio_impl.h @@ -46,6 +46,7 @@ struct _IO_FILE { void *mustbezero_2; unsigned char *shend; off_t shlim, shcnt; + FILE *prev_locked, *next_locked; }; size_t __stdio_read(FILE *, unsigned char *, size_t); diff --git a/src/malloc/malloc_usable_size.c b/src/malloc/malloc_usable_size.c new file mode 100644 index 0000000..8cccd9d --- /dev/null +++ b/src/malloc/malloc_usable_size.c @@ -0,0 +1,17 @@ +#include + +void *(*const __realloc_dep)(void *, size_t) = realloc; + +struct chunk { + size_t psize, csize; + struct chunk *next, *prev; +}; + +#define OVERHEAD (2*sizeof(size_t)) +#define CHUNK_SIZE(c) ((c)->csize & -2) +#define MEM_TO_CHUNK(p) (struct chunk *)((char *)(p) - OVERHEAD) + +size_t malloc_usable_size(void *p) +{ + return CHUNK_SIZE(MEM_TO_CHUNK(p)) - OVERHEAD; +} diff --git a/src/network/dn_expand.c b/src/network/dn_expand.c index 849df19..d9b3393 100644 --- a/src/network/dn_expand.c +++ b/src/network/dn_expand.c @@ -4,11 +4,13 @@ int __dn_expand(const unsigned char *base, const unsigned char *end, const unsigned char *src, char *dest, int space) { const unsigned char *p = src; - char *dend = dest + (space > 254 ? 254 : space); + char *dend, *dbegin = dest; int len = -1, i, j; - if (p==end || !*p) return -1; + if (p==end || space <= 0) return -1; + dend = dest + (space > 254 ? 254 : space); /* detect reference loop using an iteration counter */ for (i=0; i < end-base; i+=2) { + /* loop invariants: p= end-base) return -1; p = base+j; } else if (*p) { - j = *p+1; - if (j>=end-p || j>dend-dest) return -1; - while (--j) *dest++ = *++p; - *dest++ = *++p ? '.' : 0; + if (dest != dbegin) *dest++ = '.'; + j = *p++; + if (j >= end-p || j >= dend-dest) return -1; + while (j--) *dest++ = *p++; } else { + *dest = 0; if (len < 0) len = p+1-src; return len; } diff --git a/src/stdio/fclose.c b/src/stdio/fclose.c index 38e8a1e..317b3c9 100644 --- a/src/stdio/fclose.c +++ b/src/stdio/fclose.c @@ -1,4 +1,8 @@ #include "stdio_impl.h" +#include "libc.h" + +static void dummy(FILE *f) { } +weak_alias(dummy, __unlist_locked_file); int fclose(FILE *f) { @@ -7,6 +11,8 @@ int fclose(FILE *f) FFINALLOCK(f); + __unlist_locked_file(f); + if (!(perm = f->flags & F_PERM)) { OFLLOCK(); if (f->prev) f->prev->next = f->next; diff --git a/src/stdio/fgets.c b/src/stdio/fgets.c index b01a418..d3f9819 100644 --- a/src/stdio/fgets.c +++ b/src/stdio/fgets.c @@ -10,14 +10,16 @@ char *fgets(char *restrict s, int n, FILE *restrict f) size_t k; int c; + FLOCK(f); + if (n--<=1) { + f->mode |= f->mode-1; + FUNLOCK(f); if (n) return 0; *s = 0; return s; } - FLOCK(f); - while (n) { z = memchr(f->rpos, '\n', f->rend - f->rpos); k = z ? z - f->rpos + 1 : f->rend - f->rpos; @@ -34,7 +36,7 @@ char *fgets(char *restrict s, int n, FILE *restrict f) n--; if ((*p++ = c) == '\n') break; } - *p = 0; + if (s) *p = 0; FUNLOCK(f); diff --git a/src/stdio/fputs.c b/src/stdio/fputs.c index 1112b19..4737f44 100644 --- a/src/stdio/fputs.c +++ b/src/stdio/fputs.c @@ -3,9 +3,7 @@ int fputs(const char *restrict s, FILE *restrict f) { - size_t l = strlen(s); - if (!l) return 0; - return (int)fwrite(s, l, 1, f) - 1; + return (int)fwrite(s, strlen(s), 1, f) - 1; } weak_alias(fputs, fputs_unlocked); diff --git a/src/stdio/fread.c b/src/stdio/fread.c index c461256..33a65f5 100644 --- a/src/stdio/fread.c +++ b/src/stdio/fread.c @@ -8,11 +8,10 @@ size_t fread(void *restrict destv, size_t size, size_t nmemb, FILE *restrict f) unsigned char *dest = destv; size_t len = size*nmemb, l = len, k; - /* Never touch the file if length is zero.. */ - if (!l) return 0; - FLOCK(f); + f->mode |= f->mode-1; + if (f->rend - f->rpos > 0) { /* First exhaust the buffer. */ k = MIN(f->rend - f->rpos, l); diff --git a/src/stdio/ftrylockfile.c b/src/stdio/ftrylockfile.c index 56cccaf..6f9a4b8 100644 --- a/src/stdio/ftrylockfile.c +++ b/src/stdio/ftrylockfile.c @@ -2,9 +2,26 @@ #include "pthread_impl.h" #include +void __do_orphaned_stdio_locks() +{ + FILE *f; + for (f=__pthread_self()->stdio_locks; f; f=f->next_locked) + a_store(&f->lock, 0x40000000); +} + +void __unlist_locked_file(FILE *f) +{ + if (f->lockcount) { + if (f->next_locked) f->next_locked->prev_locked = f->prev_locked; + if (f->prev_locked) f->prev_locked->next_locked = f->next_locked; + else __pthread_self()->stdio_locks = f->next_locked; + } +} + int ftrylockfile(FILE *f) { - int tid = __pthread_self()->tid; + pthread_t self = __pthread_self(); + int tid = self->tid; if (f->lock == tid) { if (f->lockcount == LONG_MAX) return -1; @@ -15,5 +32,8 @@ int ftrylockfile(FILE *f) if (f->lock || a_cas(&f->lock, 0, tid)) return -1; f->lockcount = 1; + f->prev_locked = 0; + f->next_locked = self->stdio_locks; + self->stdio_locks = f; return 0; } diff --git a/src/stdio/funlockfile.c b/src/stdio/funlockfile.c index f8a2a07..30a07ef 100644 --- a/src/stdio/funlockfile.c +++ b/src/stdio/funlockfile.c @@ -1,7 +1,15 @@ #include "stdio_impl.h" #include "pthread_impl.h" +void __unlist_locked_file(FILE *); + void funlockfile(FILE *f) { - if (!--f->lockcount) __unlockfile(f); + if (f->lockcount == 1) { + __unlist_locked_file(f); + f->lockcount = 0; + __unlockfile(f); + } else { + f->lockcount--; + } } diff --git a/src/stdio/fwrite.c b/src/stdio/fwrite.c index d5f6542..81ec271 100644 --- a/src/stdio/fwrite.c +++ b/src/stdio/fwrite.c @@ -28,7 +28,6 @@ size_t __fwritex(const unsigned char *restrict s, size_t l, FILE *restrict f) size_t fwrite(const void *restrict src, size_t size, size_t nmemb, FILE *restrict f) { size_t k, l = size*nmemb; - if (!l) return l; FLOCK(f); k = __fwritex(src, l, f); FUNLOCK(f); diff --git a/src/thread/__timedwait.c b/src/thread/__timedwait.c index 39eb996..d6f1233 100644 --- a/src/thread/__timedwait.c +++ b/src/thread/__timedwait.c @@ -29,7 +29,7 @@ int __timedwait(volatile int *addr, int val, pthread_cleanup_push(cleanup, arg); r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT|priv, val, top); - if (r == EINVAL) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); + if (r == ENOSYS) r = -__syscall_cp(SYS_futex, addr, FUTEX_WAIT, val, top); if (r != EINTR && r != ETIMEDOUT) r = 0; pthread_cleanup_pop(0); diff --git a/src/thread/__wait.c b/src/thread/__wait.c index ec1e820..01ee598 100644 --- a/src/thread/__wait.c +++ b/src/thread/__wait.c @@ -2,15 +2,15 @@ void __wait(volatile int *addr, volatile int *waiters, int val, int priv) { - int spins=10000; + int spins=100; if (priv) priv = 128; - while (spins--) { + while (spins-- && (!waiters || !*waiters)) { if (*addr==val) a_spin(); else return; } if (waiters) a_inc(waiters); while (*addr==val) { - __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -EINVAL + __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); } if (waiters) a_dec(waiters); diff --git a/src/thread/pthread_barrier_wait.c b/src/thread/pthread_barrier_wait.c index 6b329c9..e15abb8 100644 --- a/src/thread/pthread_barrier_wait.c +++ b/src/thread/pthread_barrier_wait.c @@ -79,7 +79,7 @@ int pthread_barrier_wait(pthread_barrier_t *b) /* First thread to enter the barrier becomes the "instance owner" */ if (!inst) { struct instance new_inst = { 0 }; - int spins = 10000; + int spins = 200; b->_b_inst = inst = &new_inst; a_store(&b->_b_lock, 0); if (b->_b_waiters) __wake(&b->_b_lock, 1, 1); @@ -87,7 +87,7 @@ int pthread_barrier_wait(pthread_barrier_t *b) a_spin(); a_inc(&inst->finished); while (inst->finished == 1) - __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|128,1,0) != -EINTR + __syscall(SYS_futex,&inst->finished,FUTEX_WAIT|128,1,0) != -ENOSYS || __syscall(SYS_futex,&inst->finished,FUTEX_WAIT,1,0); return PTHREAD_BARRIER_SERIAL_THREAD; } diff --git a/src/thread/pthread_cond_timedwait.c b/src/thread/pthread_cond_timedwait.c index c5cf66c..2d192b0 100644 --- a/src/thread/pthread_cond_timedwait.c +++ b/src/thread/pthread_cond_timedwait.c @@ -52,7 +52,7 @@ static inline void unlock_requeue(volatile int *l, volatile int *r, int w) { a_store(l, 0); if (w) __wake(l, 1, 1); - else __syscall(SYS_futex, l, FUTEX_REQUEUE|128, 0, 1, r) != -EINVAL + else __syscall(SYS_futex, l, FUTEX_REQUEUE|128, 0, 1, r) != -ENOSYS || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r); } diff --git a/src/thread/pthread_create.c b/src/thread/pthread_create.c index c8c117b..e441bda 100644 --- a/src/thread/pthread_create.c +++ b/src/thread/pthread_create.c @@ -3,6 +3,7 @@ #include "stdio_impl.h" #include "libc.h" #include +#include static void dummy_0() { @@ -11,6 +12,7 @@ weak_alias(dummy_0, __acquire_ptc); weak_alias(dummy_0, __release_ptc); weak_alias(dummy_0, __pthread_tsd_run_dtors); weak_alias(dummy_0, __do_private_robust_list); +weak_alias(dummy_0, __do_orphaned_stdio_locks); _Noreturn void pthread_exit(void *result) { @@ -65,6 +67,7 @@ _Noreturn void pthread_exit(void *result) } __do_private_robust_list(); + __do_orphaned_stdio_locks(); if (self->detached && self->map_base) { /* Detached threads must avoid the kernel clear_child_tid @@ -175,6 +178,7 @@ int pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp if (need < size/8 && need < 2048) { tsd = stack - __pthread_tsd_size; stack = tsd - libc.tls_size; + memset(stack, 0, need); } else { size = ROUND(need); guard = 0; diff --git a/src/thread/pthread_mutex_timedlock.c b/src/thread/pthread_mutex_timedlock.c index 2a959d2..ae883f9 100644 --- a/src/thread/pthread_mutex_timedlock.c +++ b/src/thread/pthread_mutex_timedlock.c @@ -8,6 +8,12 @@ int pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec * int r, t, priv = (m->_m_type & 128) ^ 128; + r = pthread_mutex_trylock(m); + if (r != EBUSY) return r; + + int spins = 100; + while (spins-- && m->_m_lock && !m->_m_waiters) a_spin(); + while ((r=pthread_mutex_trylock(m)) == EBUSY) { if (!(r=m->_m_lock) || ((r&0x40000000) && (m->_m_type&4))) continue; diff --git a/src/thread/pthread_rwlock_timedrdlock.c b/src/thread/pthread_rwlock_timedrdlock.c index a2b4d44..ea50da4 100644 --- a/src/thread/pthread_rwlock_timedrdlock.c +++ b/src/thread/pthread_rwlock_timedrdlock.c @@ -3,6 +3,13 @@ int pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at) { int r, t; + + r = pthread_rwlock_tryrdlock(rw); + if (r != EBUSY) return r; + + int spins = 100; + while (spins-- && rw->_rw_lock && !rw->_rw_waiters) a_spin(); + while ((r=pthread_rwlock_tryrdlock(rw))==EBUSY) { if (!(r=rw->_rw_lock) || (r&0x7fffffff)!=0x7fffffff) continue; t = r | 0x80000000; diff --git a/src/thread/pthread_rwlock_timedwrlock.c b/src/thread/pthread_rwlock_timedwrlock.c index 63a32ec..8d04f56 100644 --- a/src/thread/pthread_rwlock_timedwrlock.c +++ b/src/thread/pthread_rwlock_timedwrlock.c @@ -3,6 +3,13 @@ int pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at) { int r, t; + + r = pthread_rwlock_trywrlock(rw); + if (r != EBUSY) return r; + + int spins = 100; + while (spins-- && rw->_rw_lock && !rw->_rw_waiters) a_spin(); + while ((r=pthread_rwlock_trywrlock(rw))==EBUSY) { if (!(r=rw->_rw_lock)) continue; t = r | 0x80000000; diff --git a/src/thread/sem_timedwait.c b/src/thread/sem_timedwait.c index bfcb6dc..b5a60ad 100644 --- a/src/thread/sem_timedwait.c +++ b/src/thread/sem_timedwait.c @@ -8,6 +8,11 @@ static void cleanup(void *p) int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at) { + if (!sem_trywait(sem)) return 0; + + int spins = 100; + while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin(); + while (sem_trywait(sem)) { int r; a_inc(sem->__val+1);