diff --git a/Makefile b/Makefile index badb0de..c09dac9 100644 --- a/Makefile +++ b/Makefile @@ -16,12 +16,17 @@ export COND_VAR=1 .SECONDARY: $(OBJS) .PHONY: all clean format +all: +ifeq ($(BUILD_MUSL), 1) +all: musl_mutex $(DIR) include/topology.h $(SOS) $(SHS) +else all: $(DIR) include/topology.h $(SOS) $(SHS) +endif no_cond_var: COND_VAR=0 no_cond_var: all -%.so: obj/CLHT/libclht.a obj/ +%.so: musl_mutex obj/CLHT/libclht.a obj/ mkdir -p lib/ $(MAKE) -C src/ ../lib/$@ @@ -31,6 +36,9 @@ obj/: $(DIR): mkdir -p $@ +musl_mutex: + $(MAKE) -C src/musl_mutex + obj/CLHT: cd obj/ && ([ -d CLHT ] || git clone https://github.com/HugoGuiroux/CLHT.git) mkdir -p obj/CLHT/external/lib/ diff --git a/Makefile.config b/Makefile.config index fb4c970..dcb4da4 100644 --- a/Makefile.config +++ b/Makefile.config @@ -2,33 +2,34 @@ # A = algorithm name, lowercase, without space (must match the src/*.c and src/*.h name) # S = waiting strategy. original = hardcoded in the algorithm (see README), otherwise spinlock/spin_then_park/park -ALGORITHMS=mcs_spinlock \ -mcsepfl_original \ -mcs_spin_then_park \ -mcstp_original \ +ALGORITHMS=muslmutex_original \ spinlock_original \ -spinlockepfl_original \ -malthusian_spinlock \ -malthusian_spin_then_park \ -ttas_original \ -ttasepfl_original \ -ticket_original \ -ticketepfl_original \ -clh_spinlock \ -clh_spin_then_park \ -clhepfl_original \ -backoff_original \ empty_original \ +hmcs_original \ +mcs_spinlock \ pthreadinterpose_original \ pthreadadaptive_original \ -concurrency_original \ -htlockepfl_original \ -alockepfl_original \ -hmcs_original \ -hyshmcs_original \ -cbomcs_spinlock \ -cbomcs_spin_then_park \ -cptltkt_original \ -ctkttkt_original \ -partitioned_original \ -mutexee_original +#mcsepfl_original \ +#mcs_spin_then_park \ +#mcstp_original \ +#spinlockepfl_original \ +#malthusian_spinlock \ +#malthusian_spin_then_park \ +#ttas_original \ +#ttasepfl_original \ +#ticket_original \ +#ticketepfl_original \ +#clh_spinlock \ +#clh_spin_then_park \ +#clhepfl_original \ +#backoff_original \ +#concurrency_original \ +#htlockepfl_original \ +#alockepfl_original \ +#hyshmcs_original \ +#cbomcs_spinlock \ +#cbomcs_spin_then_park \ +#cptltkt_original \ +#ctkttkt_original \ +#partitioned_original \ +#mutexee_original diff --git a/ci-build.sh b/ci-build.sh new file mode 100755 index 0000000..91c2b98 --- /dev/null +++ b/ci-build.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +set -eux + +#Discard all uncommited changes +git checkout -f + +#Build LiTL +nproc="$(nproc)" +make BUILD_MUSL=1 no_cond_var -j "$nproc" + +#Delete source files, keep only .so libraries and .sh scripts for use those libraries +if [ "${1:-}" = "delete_sources" ]; then + find . -mindepth 1 ! -path "./.git/*" ! -name ".git" ! -name ".gitignore" ! -name ".clang-format" \ + ! -path "./lib/*" ! -name "lib" \ + ! -name "*.sh" \ + -exec rm -rf {} + +fi diff --git a/include/muslmutex.h b/include/muslmutex.h new file mode 100644 index 0000000..b5f30ad --- /dev/null +++ b/include/muslmutex.h @@ -0,0 +1,122 @@ +/* + * The MIT License (MIT) + * + * Copyright (c) 2016 Hugo Guiroux + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of his software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef __MUSL_MUTEX_H__ +#define __MUSL_MUTEX_H__ + +#define LOCK_ALGORITHM "MUSL" +#define NEED_CONTEXT 0 +#define SUPPORT_WAITING 0 + +// Define needed types before including alltypes_make.h +// #define __NEED_pthread_cond_t +// #define __NEED_pthread_condattr_t + +#include "../src/musl_mutex/alltypes_make.h" +#include "padding.h" // for glibc pthread_cond_t + +// typedef struct musl_mutex { +// // #if COND_VAR +// // pthread_mutex_t posix_lock; +// // char __pad[pad_to_cache_line(sizeof(pthread_mutex_t))]; +// // #endif +// __pthread_mutex_t lock; +// } musl_mutex_t __attribute__((aligned(L_CACHE_LINE_SIZE))); + +typedef __pthread_mutex_t musl_mutex_t; +typedef __pthread_cond_t musl_cond_t; +// typedef void *musl_context_t; // Unused, take the less space + // as possible +typedef void *musl_context_t; +typedef musl_mutex_t lock_mutex_t; +typedef musl_context_t lock_context_t; +typedef musl_cond_t lock_cond_t; + +// + +// typedef __pthread_mutex_t musl_mutex_t; +// typedef __pthread_mutexattr_t musl_mutexattr_t; + +// typedef pthread_mutex_t musl_mutex_t; +// typedef pthread_cond_t musl_cond_t; +// typedef void *musl_context_t; + +// typedef musl_mutex_t lock_mutex_t; +// typedef musl_context_t lock_context_t; + +// typedef void *musl_context_t; // Unused, take the less space as possible +// typedef void *lock_context_t; // Required for interpose.c + +//Decls +musl_mutex_t *musl_mutex_create(const __pthread_mutexattr_t *attr); +int musl_mutex_destroy(musl_mutex_t *lock); + + +// int musl_cond_init(musl_cond_t *cond, const pthread_condattr_t *attr); +// int __pthread_musl_cond_init(musl_cond_t *restrict c, const pthread_condattr_t *restrict a); +// // int musl_cond_timedwait(musl_cond_t *cond, musl_mutex_t *lock, +// // musl_context_t *me, const struct timespec *ts); +// int __pthread_musl_cond_timedwait(musl_cond_t *restrict c, musl_mutex_t *restrict m, musl_context_t *restrict me, const struct timespec *restrict ts); +// // int musl_cond_wait(musl_cond_t *cond, musl_mutex_t *lock, musl_context_t *me); +// int __pthread_musl_cond_wait(musl_cond_t *restrict c, musl_mutex_t *restrict m, musl_context_t *restrict me); + +// // int musl_cond_signal(musl_cond_t *cond); +// int __pthread_musl_cond_signal(musl_cond_t *cond); +// // int musl_cond_broadcast(musl_cond_t *cond); +// int __pthread_musl_cond_broadcast(musl_cond_t *cond); +// // int musl_cond_destroy(musl_cond_t *cond); +// int __pthread_musl_cond_destroy(musl_cond_t *c); + +void musl_thread_start(void); +void musl_thread_exit(void); +void musl_application_init(void); +void musl_application_exit(void); +//unused + + +//Defines +// From musl_mutex/pthread_musl.h +#define lock_mutex_lock __pthread_musl_mutex_lock +#define lock_mutex_trylock __pthread_musl_mutex_trylock +#define lock_mutex_unlock __pthread_musl_mutex_unlock +// #define musl_mutex_init __pthread_mutex_init + +// From here +#define lock_mutex_create musl_mutex_create +#define lock_mutex_destroy musl_mutex_destroy + +//Unused +#define lock_cond_init __pthread_musl_cond_init +#define lock_cond_timedwait __pthread_musl_cond_timedwait +#define lock_cond_wait __pthread_musl_cond_wait +#define lock_cond_signal __pthread_musl_cond_signal +#define lock_cond_broadcast __pthread_musl_cond_broadcast +#define lock_cond_destroy __pthread_musl_cond_destroy +#define lock_thread_start musl_thread_start +#define lock_thread_exit musl_thread_exit +#define lock_application_init musl_application_init +#define lock_application_exit musl_application_exit +#define lock_init_context musl_init_context +//unused + +#endif // __MUSL_MUTEX_H__ diff --git a/src/Makefile b/src/Makefile index 4ab46cb..2f4afd4 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,7 +1,7 @@ include ../Makefile.config LDFLAGS=-L../obj/CLHT/external/lib -L../obj/CLHT -Wl,--whole-archive -Wl,--version-script=interpose.map -lsspfd -lssmem -lclht -Wl,--no-whole-archive -lrt -lm -ldl -lpapi -m64 -pthread -CFLAGS=-I../include/ -I../obj/CLHT/include/ -I../obj/CLHT/external/include/ -fPIC -Wall -Werror -O3 -g +CFLAGS=-I../include/ -I../obj/CLHT/include/ -I../obj/CLHT/external/include/ -fPIC -Wall -O3 -g -Wno-flexible-array-member-not-at-end # Keep objects files .PRECIOUS: %.o @@ -19,4 +19,4 @@ CFLAGS=-I../include/ -I../obj/CLHT/include/ -I../obj/CLHT/external/include/ -fPI .SECONDEXPANSION: ../lib/lib%.so: ../obj/%/interpose.o ../obj/%/utils.o $$(subst algo,%,../obj/algo/algo.o) - $(CC) -shared -o $@ $^ $(LDFLAGS) + $(CC) -shared -o $@ $^ -L ./musl_mutex -lmusl_mutex $(LDFLAGS) diff --git a/src/empty.c b/src/empty.c index bd93620..f19331c 100644 --- a/src/empty.c +++ b/src/empty.c @@ -49,39 +49,48 @@ int empty_mutex_lock(empty_mutex_t *impl, empty_context_t *UNUSED(me)) { } int empty_mutex_trylock(empty_mutex_t *impl, empty_context_t *UNUSED(me)) { + // fprintf(stderr, "empty_mutex_trylock\n"); return REAL(pthread_mutex_trylock)(impl); } void empty_mutex_unlock(empty_mutex_t *impl, empty_context_t *UNUSED(me)) { + // fprintf(stderr, "empty_mutex_unlock\n"); REAL(pthread_mutex_unlock)(impl); } int empty_mutex_destroy(empty_mutex_t *lock) { + // fprintf(stderr, "empty_mutex_destroy\n"); return REAL(pthread_mutex_destroy)(lock); } int empty_cond_init(empty_cond_t *cond, const pthread_condattr_t *attr) { + // fprintf(stderr, "empty_cond_init\n"); return REAL(pthread_cond_init)(cond, attr); } int empty_cond_timedwait(empty_cond_t *cond, empty_mutex_t *lock, empty_context_t *me, const struct timespec *ts) { + // fprintf(stderr, "empty_cond_timedwait\n"); return REAL(pthread_cond_timedwait)(cond, lock, ts); } int empty_cond_wait(empty_cond_t *cond, empty_mutex_t *lock, empty_context_t *UNUSED(me)) { + // fprintf(stderr, "empty_cond_wait\n"); return REAL(pthread_cond_wait)(cond, lock); } int empty_cond_signal(empty_cond_t *cond) { + // fprintf(stderr, "empty_cond_signal\n"); return REAL(pthread_cond_signal)(cond); } int empty_cond_broadcast(empty_cond_t *cond) { + // fprintf(stderr, "empty_cond_broadcast\n"); return REAL(pthread_cond_broadcast)(cond); } int empty_cond_destroy(empty_cond_t *cond) { + // fprintf(stderr, "empty_cond_destroy\n"); return REAL(pthread_cond_destroy)(cond); } diff --git a/src/interpose.c b/src/interpose.c index 1e65e77..77a4b3d 100644 --- a/src/interpose.c +++ b/src/interpose.c @@ -87,6 +87,8 @@ #include #elif defined(MUTEXEE) #include +#elif defined(MUSLMUTEX) +#include #else #error "No lock algorithm known" #endif @@ -697,4 +699,4 @@ int pthread_rwlock_unlock(pthread_rwlock_t *rwlock) { #else assert(0 && "rwlock not supported without indirection"); #endif -} +} \ No newline at end of file diff --git a/src/interpose.h b/src/interpose.h index 08eb99c..ecb5426 100644 --- a/src/interpose.h +++ b/src/interpose.h @@ -97,4 +97,4 @@ extern int (*REAL(pthread_rwlock_trywrlock))(pthread_rwlock_t *lock); extern int (*REAL(pthread_rwlock_unlock))(pthread_rwlock_t *lock); // rdwr locks -#endif // __INTERPOSE_H__ +#endif // __INTERPOSE_H__ \ No newline at end of file diff --git a/src/interpose.map b/src/interpose.map index 9a75060..e6160ef 100644 --- a/src/interpose.map +++ b/src/interpose.map @@ -35,3 +35,8 @@ GLIBC_2.3.2 { pthread_cond_wait; pthread_cond_timedwait; } GLIBC_2.2.5; + +GLIBC_2.39 { + global: + pthread_create; +} GLIBC_2.3.2; diff --git a/src/mcstp.c b/src/mcstp.c index 7d4fbbf..3cf3dd3 100644 --- a/src/mcstp.c +++ b/src/mcstp.c @@ -39,7 +39,7 @@ * is preempted. * Indeed, a thread A can overtake another thread B behind which it has been * waiting for a long time. - * The waiting thread A will first yield its CPU (via pthread_yield) in order to + * The waiting thread A will first yield its CPU (via sched_yield) in order to * create an opportunity for the preempted thread (lock holder or B) to make * progress. * If this is not enough, T will overtake the predecessor thread (B) by marking @@ -144,7 +144,7 @@ int mcs_tp_mutex_trylock(mcs_tp_mutex_t *impl, mcs_tp_node_t *me) { goto success; } else if (me->status == FAILED) { if (GET_TIME() - impl->cs_start_time > MAX_CS_TIME) - pthread_yield(); + sched_yield(); me->last_lock = impl; return EBUSY; @@ -164,7 +164,7 @@ int mcs_tp_mutex_trylock(mcs_tp_mutex_t *impl, mcs_tp_node_t *me) { } if (GET_TIME() - impl->cs_start_time > MAX_CS_TIME) - pthread_yield(); + sched_yield(); me->last_lock = impl; return EBUSY; diff --git a/src/musl_mutex/Makefile b/src/musl_mutex/Makefile new file mode 100644 index 0000000..7eeb480 --- /dev/null +++ b/src/musl_mutex/Makefile @@ -0,0 +1,48 @@ +# Compiler and flags +CC = musl-gcc +CFLAGS = -Wall -Wextra -fPIC -I. -D__NEED_struct_timespec + +# Source files +SRCS = pthread_mutex_lock.c \ + pthread_mutex_timedlock.c \ + pthread_mutex_trylock.c \ + pthread_mutex_unlock.c \ + pthread_mutex_init.c \ + pthread_self_glibc.c \ + pthread_setcancelstate_glibc.c \ + pthread_cond_wait.c \ + pthread_cond_timedwait.c \ + pthread_cond_signal.c \ + pthread_cond_broadcast.c \ + pthread_cond_destroy.c \ + pthread_cond_init.c \ + __timedwait.c \ + __wait.c \ + vmlock.c \ + __syscall_cp.c \ + clock_gettime.c \ + syscall_ret.c \ + # vdso.c \ + +# Object files +OBJS = $(SRCS:.c=.o) + +# Output library +TARGET = libmusl_mutex.a + +# Default target +all: $(TARGET) + +# Link shared library +$(TARGET): $(OBJS) + ar rcs $@ $^ + +# Compile sources +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# Clean up +clean: + rm -f $(OBJS) $(TARGET) + +.PHONY: all clean diff --git a/src/musl_mutex/__syscall_cp.c b/src/musl_mutex/__syscall_cp.c new file mode 100644 index 0000000..1976180 --- /dev/null +++ b/src/musl_mutex/__syscall_cp.c @@ -0,0 +1,18 @@ +#include "pthread_impl.h" +#include "syscall.h" + +long __syscall_cp_c(); +long __syscall_cp_c(syscall_arg_t nr, + syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, + syscall_arg_t x, syscall_arg_t y, syscall_arg_t z) +{ + return __syscall(nr, u, v, w, x, y, z); +} + +weak_alias(sccp, __syscall_cp_c); +long (__syscall_cp)(syscall_arg_t nr, + syscall_arg_t u, syscall_arg_t v, syscall_arg_t w, + syscall_arg_t x, syscall_arg_t y, syscall_arg_t z) +{ + return __syscall_cp_c(nr, u, v, w, x, y, z); +} diff --git a/src/musl_mutex/__syscall_cp.o b/src/musl_mutex/__syscall_cp.o new file mode 100644 index 0000000..8b18f52 Binary files /dev/null and b/src/musl_mutex/__syscall_cp.o differ diff --git a/src/musl_mutex/__timedwait.c b/src/musl_mutex/__timedwait.c new file mode 100644 index 0000000..ca1d9b2 --- /dev/null +++ b/src/musl_mutex/__timedwait.c @@ -0,0 +1,84 @@ +#include "pthread_musl.h" +#include "errno.h" +#include "futex.h" +#include "syscall.h" +#include "pthread_impl.h" +#include + +#include "pthread_setcancelstate_glibc.h" // pthread_setcancelstate +#include + +#define IS32BIT(x) !((x)+0x80000000ULL>>32) +#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) + +static int __futex4_cp(volatile void *addr, int op, int val, const struct timespec *to) +{ + // fprintf(stderr, "Error __futex4_cp.\n"); + int r; +#ifdef SYS_futex_time64 + time_t s = to ? to->tv_sec : 0; + long ns = to ? to->tv_nsec : 0; + r = -ENOSYS; + if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) + r = __syscall_cp(SYS_futex_time64, addr, op, val, + to ? ((long long[]){s, ns}) : 0); + if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + to = to ? (void *)(long[]){CLAMP(s), ns} : 0; +#endif + // fprintf(stderr, "Error __futex4_cp 1.\n"); + r = __syscall_cp(SYS_futex, addr, op, val, to); + // fprintf(stderr, "Error __futex4_cp 2.\n"); + if (r != -ENOSYS) return r; + // fprintf(stderr, "Error __futex4_cp 3.\n"); + return __syscall_cp(SYS_futex, addr, op & ~FUTEX_PRIVATE, val, to); +} + +static volatile int __eintr_valid_flag = 0; + +int __timedwait_cp(volatile int *addr, int val, + clockid_t clk, const struct timespec *at, int priv) +{ + // fprintf(stderr, "Error __timedwait_cp.\n"); + int r; + struct timespec to, *top=0; + + if (priv) priv = FUTEX_PRIVATE; + + if (at) { + if (at->tv_nsec >= 1000000000UL) return EINVAL; + if (clock_gettime(clk, &to)) return EINVAL; + // clock_gettime(clk, &to); + to.tv_sec = at->tv_sec - to.tv_sec; + if ((to.tv_nsec = at->tv_nsec - to.tv_nsec) < 0) { + to.tv_sec--; + to.tv_nsec += 1000000000; + } + if (to.tv_sec < 0) return ETIMEDOUT; + top = &to; + } + // fprintf(stderr, "Error __timedwait_cp 1.\n"); + r = -__futex4_cp(addr, FUTEX_WAIT|priv, val, top); + // fprintf(stderr, "Error __timedwait_cp 2.\n"); + if (r != EINTR && r != ETIMEDOUT && r != ECANCELED) r = 0; + /* Mitigate bug in old kernels wrongly reporting EINTR for non- + * interrupting (SA_RESTART) signal handlers. This is only practical + * when NO interrupting signal handlers have been installed, and + * works by sigaction tracking whether that's the case. */ + if (r == EINTR && !__eintr_valid_flag) r = 0; + // fprintf(stderr, "Error __timedwait_cp return.\n"); + return r; +} + + +int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv) +{ + // fprintf(stderr, "Error __timedwait.\n"); + int cs, r; + pthread_setcancelstate_glibc(PTHREAD_CANCEL_DISABLE, &cs); + // fprintf(stderr, "Error __timedwait 1.\n"); + r = __timedwait_cp(addr, val, clk, at, priv); + // fprintf(stderr, "Error __timedwait 2.\n"); + pthread_setcancelstate_glibc(cs, 0); + // fprintf(stderr, "Error __timedwait return.\n"); + return r; +} diff --git a/src/musl_mutex/__timedwait.o b/src/musl_mutex/__timedwait.o new file mode 100644 index 0000000..43c1e54 Binary files /dev/null and b/src/musl_mutex/__timedwait.o differ diff --git a/src/musl_mutex/__wait.c b/src/musl_mutex/__wait.c new file mode 100644 index 0000000..dc33c1a --- /dev/null +++ b/src/musl_mutex/__wait.c @@ -0,0 +1,17 @@ +#include "pthread_impl.h" + +void __wait(volatile int *addr, volatile int *waiters, int val, int priv) +{ + int spins=100; + if (priv) priv = FUTEX_PRIVATE; + 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) != -ENOSYS + || __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); + } + if (waiters) a_dec(waiters); +} diff --git a/src/musl_mutex/__wait.o b/src/musl_mutex/__wait.o new file mode 100644 index 0000000..5fd588c Binary files /dev/null and b/src/musl_mutex/__wait.o differ diff --git a/src/musl_mutex/alltypes_make.h b/src/musl_mutex/alltypes_make.h new file mode 100644 index 0000000..6a268db --- /dev/null +++ b/src/musl_mutex/alltypes_make.h @@ -0,0 +1,142 @@ +#pragma once + +#define _Addr long +#define _Int64 long +#define _Reg long + +#define __BYTE_ORDER 1234 +#define __LONG_MAX 0x7fffffffffffffffL + + +#define __LITTLE_ENDIAN 1234 +#define __BIG_ENDIAN 4321 +#define __USE_TIME_BITS64 1 + +//#if defined(__NEED_size_t) && !defined(__DEFINED_size_t) +typedef unsigned _Addr size_t; +//#define __DEFINED_size_t +//#endif + +//#if defined(__NEED_uintptr_t) && !defined(__DEFINED_uintptr_t) +typedef unsigned _Addr uintptr_t; +//#define __DEFINED_uintptr_t +//#endif + +//#if defined(__NEED_intptr_t) && !defined(__DEFINED_intptr_t) +typedef _Addr intptr_t; +//#define __DEFINED_intptr_t +//#endif + +//#if defined(__NEED_time_t) && !defined(__DEFINED_time_t) +typedef _Int64 time_t; +//#define __DEFINED_time_t +//#endif + + +//#if defined(__NEED_int8_t) && !defined(__DEFINED_int8_t) +typedef signed char int8_t; +//#define __DEFINED_int8_t +//#endif + +//#if defined(__NEED_int16_t) && !defined(__DEFINED_int16_t) +typedef signed short int16_t; +//#define __DEFINED_int16_t +//#endif + +//#if defined(__NEED_int32_t) && !defined(__DEFINED_int32_t) +typedef signed int int32_t; +//#define __DEFINED_int32_t +//#endif + +//#if defined(__NEED_int64_t) && !defined(__DEFINED_int64_t) +typedef signed _Int64 int64_t; +//#define __DEFINED_int64_t +//#endif + +//#if defined(__NEED_intmax_t) && !defined(__DEFINED_intmax_t) +typedef signed _Int64 intmax_t; +//#define __DEFINED_intmax_t +//#endif + +//#if defined(__NEED_uint8_t) && !defined(__DEFINED_uint8_t) +typedef unsigned char uint8_t; +//#define __DEFINED_uint8_t +//#endif + +//#if defined(__NEED_uint16_t) && !defined(__DEFINED_uint16_t) +typedef unsigned short uint16_t; +//#define __DEFINED_uint16_t +//#endif + +//#if defined(__NEED_uint32_t) && !defined(__DEFINED_uint32_t) +typedef unsigned int uint32_t; +//#define __DEFINED_uint32_t +//#endif + +//#if defined(__NEED_uint64_t) && !defined(__DEFINED_uint64_t) +typedef unsigned _Int64 uint64_t; +//#define __DEFINED_uint64_t +//#endif + +//#if defined(__NEED_uintmax_t) && !defined(__DEFINED_uintmax_t) +typedef unsigned _Int64 uintmax_t; +//#define __DEFINED_uintmax_t +//#endif + +#if defined(__NEED_wctype_t) && !defined(__DEFINED_wctype_t) +typedef unsigned long wctype_t; +#define __DEFINED_wctype_t +#endif + + +#//if defined(__NEED_clockid_t) && !defined(__DEFINED_clockid_t) +typedef int clockid_t; +#define __DEFINED_clockid_t +//#endif + +#if defined(__NEED_struct_timespec) && !defined(__DEFINED_struct_timespec) +struct timespec { time_t tv_sec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER==4321); long tv_nsec; int :8*(sizeof(time_t)-sizeof(long))*(__BYTE_ORDER!=4321); }; +#define __DEFINED_struct_timespec +#endif + +#ifdef __cplusplus +#if defined(__NEED_pthread_t) && !defined(__DEFINED_pthread_t) +typedef unsigned long pthread_t; +#define __DEFINED_pthread_t +#endif + +#endif + +//#if defined(__NEED_pthread_mutexattr_t) && !defined(__DEFINED_pthread_mutexattr_t) +typedef struct { unsigned __attr; } __pthread_mutexattr_t; +#define __DEFINED_pthread_mutexattr_t +//#endif + +#if defined(__NEED_locale_t) && !defined(__DEFINED_locale_t) +typedef struct __locale_struct * locale_t; +#define __DEFINED_locale_t +#endif + +#if defined(__NEED_pthread_attr_t) && !defined(__DEFINED_pthread_attr_t) +typedef struct { union { int __i[sizeof(long)==8?14:9]; volatile int __vi[sizeof(long)==8?14:9]; unsigned long __s[sizeof(long)==8?7:9]; } __u; } pthread_attr_t; +#define __DEFINED_pthread_attr_t +#endif + +//#if defined(__NEED_pthread_mutex_t) && !defined(__DEFINED_pthread_mutex_t) +typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } __pthread_mutex_t; +#define __DEFINED_pthread_mutex_t +//#endif + +typedef struct { union { int __i[12]; volatile int __vi[12]; void *__p[12*sizeof(int)/sizeof(void*)]; } __u; } __pthread_cond_t; + +typedef struct { unsigned __attr; } __pthread_condattr_t; + +#if defined(__NEED_mtx_t) && !defined(__DEFINED_mtx_t) +typedef struct { union { int __i[sizeof(long)==8?10:6]; volatile int __vi[sizeof(long)==8?10:6]; volatile void *volatile __p[sizeof(long)==8?5:6]; } __u; } mtx_t; +#define __DEFINED_mtx_t +#endif + + +#undef _Addr +#undef _Int64 +#undef _Reg diff --git a/src/musl_mutex/atomic.h b/src/musl_mutex/atomic.h new file mode 100644 index 0000000..62642d8 --- /dev/null +++ b/src/musl_mutex/atomic.h @@ -0,0 +1,100 @@ +#ifndef _ATOMIC_H +#define _ATOMIC_H + +#include "stdint.h" +#include "atomic_archx86_64.h" + +#ifndef a_pre_llsc +#define a_pre_llsc() +#endif + +#ifndef a_post_llsc +#define a_post_llsc() +#endif + +#ifndef a_cas +#define a_cas a_cas +static inline int a_cas(volatile int *p, int t, int s) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (old==t && !a_sc(p, s)); + a_post_llsc(); + return old; +} +#endif + +#ifndef a_swap +#define a_swap a_swap +static inline int a_swap(volatile int *p, int v) +{ + int old; + a_pre_llsc(); + do old = a_ll(p); + while (!a_sc(p, v)); + a_post_llsc(); + return old; +} +#endif + +#endif + + +#ifndef a_cas +#error missing definition of a_cas +#endif + +#ifndef a_swap +#define a_swap a_swap +static inline int a_swap(volatile int *p, int v) +{ + int old; + do old = *p; + while (a_cas(p, old, v) != old); + return old; +} +#endif + +#ifndef a_inc +#define a_inc a_inc +static inline void a_inc(volatile int *p) +{ + a_fetch_add(p, 1); +} +#endif + +#ifndef a_dec +#define a_dec a_dec +static inline void a_dec(volatile int *p) +{ + a_fetch_add(p, -1); +} +#endif + +#ifndef a_store +#define a_store a_store +static inline void a_store(volatile int *p, int v) +{ +#ifdef a_barrier + a_barrier(); + *p = v; + a_barrier(); +#else + a_swap(p, v); +#endif +} +#endif + +#ifndef a_barrier +#define a_barrier a_barrier +static void a_barrier() +{ + volatile int tmp = 0; + a_cas(&tmp, 0, 0); +} +#endif + +#ifndef a_spin +#define a_spin a_barrier +#endif \ No newline at end of file diff --git a/src/musl_mutex/atomic_archx86_64.h b/src/musl_mutex/atomic_archx86_64.h new file mode 100644 index 0000000..423684b --- /dev/null +++ b/src/musl_mutex/atomic_archx86_64.h @@ -0,0 +1,72 @@ +#define a_cas a_cas +static inline int a_cas(volatile int *p, int t, int s) +{ + __asm__ __volatile__ ( + "lock ; cmpxchg %3, %1" + : "=a"(t), "=m"(*p) : "a"(t), "r"(s) : "memory" ); + return t; +} + +#define a_cas_p a_cas_p +static inline void *a_cas_p(volatile void *p, void *t, void *s) +{ + __asm__( "lock ; cmpxchg %3, %1" + : "=a"(t), "=m"(*(void *volatile *)p) + : "a"(t), "r"(s) : "memory" ); + return t; +} + +#define a_swap a_swap +static inline int a_swap(volatile int *p, int v) +{ + __asm__ __volatile__( + "xchg %0, %1" + : "=r"(v), "=m"(*p) : "0"(v) : "memory" ); + return v; +} + +#define a_fetch_add a_fetch_add +static inline int a_fetch_add(volatile int *p, int v) +{ + __asm__ __volatile__( + "lock ; xadd %0, %1" + : "=r"(v), "=m"(*p) : "0"(v) : "memory" ); + return v; +} + + +#define a_inc a_inc +static inline void a_inc(volatile int *p) +{ + __asm__ __volatile__( + "lock ; incl %0" + : "=m"(*p) : "m"(*p) : "memory" ); +} + +#define a_dec a_dec +static inline void a_dec(volatile int *p) +{ + __asm__ __volatile__( + "lock ; decl %0" + : "=m"(*p) : "m"(*p) : "memory" ); +} + +#define a_store a_store +static inline void a_store(volatile int *p, int x) +{ + __asm__ __volatile__( + "mov %1, %0 ; lock ; orl $0,(%%rsp)" + : "=m"(*p) : "r"(x) : "memory" ); +} + +#define a_barrier a_barrier +static inline void a_barrier() +{ + __asm__ __volatile__( "" : : : "memory" ); +} + +#define a_spin a_spin +static inline void a_spin() +{ + __asm__ __volatile__( "pause" : : : "memory" ); +} diff --git a/src/musl_mutex/clock_gettime.c b/src/musl_mutex/clock_gettime.c new file mode 100644 index 0000000..4ccbea2 --- /dev/null +++ b/src/musl_mutex/clock_gettime.c @@ -0,0 +1,112 @@ +#include "time.h" +#include "errno.h" +#include "stdint.h" +#include "syscall.h" +#include "atomic.h" + +#ifdef VDSO_CGT_SYM + +static void *volatile vdso_func; + +#ifdef VDSO_CGT32_SYM +static void *volatile vdso_func_32; +static int cgt_time32_wrap(clockid_t clk, struct timespec *ts) +{ + long ts32[2]; + int (*f)(clockid_t, long[2]) = + (int (*)(clockid_t, long[2]))vdso_func_32; + int r = f(clk, ts32); + if (!r) { + /* Fallback to syscalls if time32 overflowed. Maybe + * we lucked out and somehow migrated to a kernel with + * time64 syscalls available. */ + if (ts32[0] < 0) { + a_cas_p(&vdso_func, (void *)cgt_time32_wrap, 0); + return -ENOSYS; + } + ts->tv_sec = ts32[0]; + ts->tv_nsec = ts32[1]; + } + return r; +} +#endif + +static int cgt_init(clockid_t clk, struct timespec *ts) +{ + void *p = __vdsosym(VDSO_CGT_VER, VDSO_CGT_SYM); +#ifdef VDSO_CGT32_SYM + if (!p) { + void *q = __vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM); + if (q) { + a_cas_p(&vdso_func_32, 0, q); + p = cgt_time32_wrap; + } + } +#ifdef VDSO_CGT_WORKAROUND + if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0; +#endif +#endif + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))p; + a_cas_p(&vdso_func, (void *)cgt_init, p); + return f ? f(clk, ts) : -ENOSYS; +} + +static void *volatile vdso_func = (void *)cgt_init; + +#endif + +int __clock_gettime(clockid_t clk, struct timespec *ts) +{ + int r; + +#ifdef VDSO_CGT_SYM + int (*f)(clockid_t, struct timespec *) = + (int (*)(clockid_t, struct timespec *))vdso_func; + if (f) { + r = f(clk, ts); + if (!r) return r; + if (r == -EINVAL) return __syscall_ret(r); + /* Fall through on errors other than EINVAL. Some buggy + * vdso implementations return ENOSYS for clocks they + * can't handle, rather than making the syscall. This + * also handles the case where cgt_init fails to find + * a vdso function to use. */ + } +#endif + +#ifdef SYS_clock_gettime64 + r = -ENOSYS; + if (sizeof(time_t) > 4) + r = __syscall(SYS_clock_gettime64, clk, ts); + if (SYS_clock_gettime == SYS_clock_gettime64 || r!=-ENOSYS) + return __syscall_ret(r); + long ts32[2]; + r = __syscall(SYS_clock_gettime, clk, ts32); +#ifdef SYS_gettimeofday + if (r==-ENOSYS && clk==CLOCK_REALTIME) { + r = __syscall(SYS_gettimeofday, ts32, 0); + ts32[1] *= 1000; + } +#endif + if (!r) { + ts->tv_sec = ts32[0]; + ts->tv_nsec = ts32[1]; + return r; + } + return __syscall_ret(r); +#else + r = __syscall(SYS_clock_gettime, clk, ts); +#ifdef SYS_gettimeofday + if (r == -ENOSYS) { + if (clk == CLOCK_REALTIME) { + __syscall(SYS_gettimeofday, ts, 0); + ts->tv_nsec = (int)ts->tv_nsec * 1000; + return 0; + } + r = -EINVAL; + } +#endif + return __syscall_ret(r); +#endif +} diff --git a/src/musl_mutex/clock_gettime.o b/src/musl_mutex/clock_gettime.o new file mode 100644 index 0000000..fbbc370 Binary files /dev/null and b/src/musl_mutex/clock_gettime.o differ diff --git a/src/musl_mutex/errno.h b/src/musl_mutex/errno.h new file mode 100644 index 0000000..d2e1eee --- /dev/null +++ b/src/musl_mutex/errno.h @@ -0,0 +1,134 @@ +#define EPERM 1 +#define ENOENT 2 +#define ESRCH 3 +#define EINTR 4 +#define EIO 5 +#define ENXIO 6 +#define E2BIG 7 +#define ENOEXEC 8 +#define EBADF 9 +#define ECHILD 10 +#define EAGAIN 11 +#define ENOMEM 12 +#define EACCES 13 +#define EFAULT 14 +#define ENOTBLK 15 +#define EBUSY 16 +#define EEXIST 17 +#define EXDEV 18 +#define ENODEV 19 +#define ENOTDIR 20 +#define EISDIR 21 +#define EINVAL 22 +#define ENFILE 23 +#define EMFILE 24 +#define ENOTTY 25 +#define ETXTBSY 26 +#define EFBIG 27 +#define ENOSPC 28 +#define ESPIPE 29 +#define EROFS 30 +#define EMLINK 31 +#define EPIPE 32 +#define EDOM 33 +#define ERANGE 34 +#define EDEADLK 35 +#define ENAMETOOLONG 36 +#define ENOLCK 37 +#define ENOSYS 38 +#define ENOTEMPTY 39 +#define ELOOP 40 +#define EWOULDBLOCK EAGAIN +#define ENOMSG 42 +#define EIDRM 43 +#define ECHRNG 44 +#define EL2NSYNC 45 +#define EL3HLT 46 +#define EL3RST 47 +#define ELNRNG 48 +#define EUNATCH 49 +#define ENOCSI 50 +#define EL2HLT 51 +#define EBADE 52 +#define EBADR 53 +#define EXFULL 54 +#define ENOANO 55 +#define EBADRQC 56 +#define EBADSLT 57 +#define EDEADLOCK EDEADLK +#define EBFONT 59 +#define ENOSTR 60 +#define ENODATA 61 +#define ETIME 62 +#define ENOSR 63 +#define ENONET 64 +#define ENOPKG 65 +#define EREMOTE 66 +#define ENOLINK 67 +#define EADV 68 +#define ESRMNT 69 +#define ECOMM 70 +#define EPROTO 71 +#define EMULTIHOP 72 +#define EDOTDOT 73 +#define EBADMSG 74 +#define EOVERFLOW 75 +#define ENOTUNIQ 76 +#define EBADFD 77 +#define EREMCHG 78 +#define ELIBACC 79 +#define ELIBBAD 80 +#define ELIBSCN 81 +#define ELIBMAX 82 +#define ELIBEXEC 83 +#define EILSEQ 84 +#define ERESTART 85 +#define ESTRPIPE 86 +#define EUSERS 87 +#define ENOTSOCK 88 +#define EDESTADDRREQ 89 +#define EMSGSIZE 90 +#define EPROTOTYPE 91 +#define ENOPROTOOPT 92 +#define EPROTONOSUPPORT 93 +#define ESOCKTNOSUPPORT 94 +#define EOPNOTSUPP 95 +#define ENOTSUP EOPNOTSUPP +#define EPFNOSUPPORT 96 +#define EAFNOSUPPORT 97 +#define EADDRINUSE 98 +#define EADDRNOTAVAIL 99 +#define ENETDOWN 100 +#define ENETUNREACH 101 +#define ENETRESET 102 +#define ECONNABORTED 103 +#define ECONNRESET 104 +#define ENOBUFS 105 +#define EISCONN 106 +#define ENOTCONN 107 +#define ESHUTDOWN 108 +#define ETOOMANYREFS 109 +#define ETIMEDOUT 110 +#define ECONNREFUSED 111 +#define EHOSTDOWN 112 +#define EHOSTUNREACH 113 +#define EALREADY 114 +#define EINPROGRESS 115 +#define ESTALE 116 +#define EUCLEAN 117 +#define ENOTNAM 118 +#define ENAVAIL 119 +#define EISNAM 120 +#define EREMOTEIO 121 +#define EDQUOT 122 +#define ENOMEDIUM 123 +#define EMEDIUMTYPE 124 +#define ECANCELED 125 +#define ENOKEY 126 +#define EKEYEXPIRED 127 +#define EKEYREVOKED 128 +#define EKEYREJECTED 129 +#define EOWNERDEAD 130 +#define ENOTRECOVERABLE 131 +#define ERFKILL 132 +#define EHWPOISON 133 diff --git a/src/musl_mutex/features.h b/src/musl_mutex/features.h new file mode 100644 index 0000000..85cfb72 --- /dev/null +++ b/src/musl_mutex/features.h @@ -0,0 +1,40 @@ +#ifndef _FEATURES_H +#define _FEATURES_H + +#if defined(_ALL_SOURCE) && !defined(_GNU_SOURCE) +#define _GNU_SOURCE 1 +#endif + +#if defined(_DEFAULT_SOURCE) && !defined(_BSD_SOURCE) +#define _BSD_SOURCE 1 +#endif + +#if !defined(_POSIX_SOURCE) && !defined(_POSIX_C_SOURCE) \ + && !defined(_XOPEN_SOURCE) && !defined(_GNU_SOURCE) \ + && !defined(_BSD_SOURCE) && !defined(__STRICT_ANSI__) +#define _BSD_SOURCE 1 +#define _XOPEN_SOURCE 700 +#endif + +#if __STDC_VERSION__ >= 199901L +#define __restrict restrict +#elif !defined(__GNUC__) +#define __restrict +#endif + +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) +#define __inline inline +#elif !defined(__GNUC__) +#define __inline +#endif + +#if __STDC_VERSION__ >= 201112L +#elif defined(__GNUC__) +#define _Noreturn __attribute__((__noreturn__)) +#else +#define _Noreturn +#endif + +#define __REDIR(x,y) __typeof__(x) x __asm__(#y) + +#endif diff --git a/src/musl_mutex/futex.h b/src/musl_mutex/futex.h new file mode 100644 index 0000000..dafbc24 --- /dev/null +++ b/src/musl_mutex/futex.h @@ -0,0 +1,19 @@ +#ifndef _INTERNAL_FUTEX_H +#define _INTERNAL_FUTEX_H + +#define FUTEX_WAIT 0 +#define FUTEX_WAKE 1 +#define FUTEX_FD 2 +#define FUTEX_REQUEUE 3 +#define FUTEX_CMP_REQUEUE 4 +#define FUTEX_WAKE_OP 5 +#define FUTEX_LOCK_PI 6 +#define FUTEX_UNLOCK_PI 7 +#define FUTEX_TRYLOCK_PI 8 +#define FUTEX_WAIT_BITSET 9 + +#define FUTEX_PRIVATE 128 + +#define FUTEX_CLOCK_REALTIME 256 + +#endif diff --git a/src/musl_mutex/libc.h b/src/musl_mutex/libc.h new file mode 100644 index 0000000..3ead57e --- /dev/null +++ b/src/musl_mutex/libc.h @@ -0,0 +1,60 @@ +#ifndef LIBC_H +#define LIBC_H + +#include +#include +#include + +#define hidden __attribute__((visibility("hidden"))) + +struct __locale_map; + +struct __locale_struct { + const struct __locale_map *cat[6]; +}; + +struct tls_module { + struct tls_module *next; + void *image; + size_t len, size, align, offset; +}; + +struct __libc { + char can_do_threads; + char threaded; + char secure; + volatile signed char need_locks; + int threads_minus_1; + size_t *auxv; + struct tls_module *tls_head; + size_t tls_size, tls_align, tls_cnt; + size_t page_size; + struct __locale_struct global_locale; +}; + +#ifndef PAGE_SIZE +#define PAGE_SIZE libc.page_size +#endif + +extern hidden struct __libc __libc; +#define libc __libc + +void __init_libc(char **, char *); +void __init_tls(size_t *); +void __init_ssp(void *); +void __libc_start_init(void); +void __funcs_on_exit(void); +void __funcs_on_quick_exit(void); +void __libc_exit_fini(void); +void __fork_handler(int); + +extern size_t __hwcap; +extern size_t __sysinfo; +extern char *__progname, *__progname_full; + +extern hidden const char __libc_version[]; + +hidden void __synccall(void (*)(void *), void *); +hidden int __setxid(int, int, int, int); + +#endif diff --git a/src/musl_mutex/libmusl_mutex.a b/src/musl_mutex/libmusl_mutex.a new file mode 100644 index 0000000..abf4080 Binary files /dev/null and b/src/musl_mutex/libmusl_mutex.a differ diff --git a/src/musl_mutex/limits.h b/src/musl_mutex/limits.h new file mode 100644 index 0000000..403b240 --- /dev/null +++ b/src/musl_mutex/limits.h @@ -0,0 +1,165 @@ +#ifndef _LIMITS_H +#define _LIMITS_H + +#include "features.h" + +#include "alltypes_make.h" /* __LONG_MAX */ + +/* Support signed or unsigned plain-char */ + +#if '\xff' > 0 +#define CHAR_MIN 0 +#define CHAR_MAX 255 +#else +#define CHAR_MIN (-128) +#define CHAR_MAX 127 +#endif + +#define CHAR_BIT 8 +#define SCHAR_MIN (-128) +#define SCHAR_MAX 127 +#define UCHAR_MAX 255 +#define SHRT_MIN (-1-0x7fff) +#define SHRT_MAX 0x7fff +#define USHRT_MAX 0xffff +#define INT_MIN (-1-0x7fffffff) +#define INT_MAX 0x7fffffff +#define UINT_MAX 0xffffffffU +#define LONG_MIN (-LONG_MAX-1) +#define LONG_MAX __LONG_MAX +#define ULONG_MAX (2UL*LONG_MAX+1) +#define LLONG_MIN (-LLONG_MAX-1) +#define LLONG_MAX 0x7fffffffffffffffLL +#define ULLONG_MAX (2ULL*LLONG_MAX+1) + +#define MB_LEN_MAX 4 + +#if defined(_POSIX_SOURCE) || defined(_POSIX_C_SOURCE) \ + || defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) || defined(_BSD_SOURCE) + + +#define PIPE_BUF 4096 +#define FILESIZEBITS 64 +#ifndef NAME_MAX +#define NAME_MAX 255 +#endif +#define PATH_MAX 4096 +#define NGROUPS_MAX 32 +#define ARG_MAX 131072 +#define IOV_MAX 1024 +#define SYMLOOP_MAX 40 +#define WORD_BIT 32 +#define SSIZE_MAX LONG_MAX +#define TZNAME_MAX 6 +#define TTY_NAME_MAX 32 +#define HOST_NAME_MAX 255 + +#if LONG_MAX == 0x7fffffffL +#define LONG_BIT 32 +#else +#define LONG_BIT 64 +#endif + +/* Implementation choices... */ + +#define PTHREAD_KEYS_MAX 128 +#define PTHREAD_STACK_MIN 2048 +#define PTHREAD_DESTRUCTOR_ITERATIONS 4 +#define SEM_VALUE_MAX 0x7fffffff +#define SEM_NSEMS_MAX 256 +#define DELAYTIMER_MAX 0x7fffffff +#define MQ_PRIO_MAX 32768 +#define LOGIN_NAME_MAX 256 + +/* Arbitrary numbers... */ + +#define BC_BASE_MAX 99 +#define BC_DIM_MAX 2048 +#define BC_SCALE_MAX 99 +#define BC_STRING_MAX 1000 +#define CHARCLASS_NAME_MAX 14 +#define COLL_WEIGHTS_MAX 2 +#define EXPR_NEST_MAX 32 +#define LINE_MAX 4096 +#define RE_DUP_MAX 255 + +#define NL_ARGMAX 9 +#define NL_MSGMAX 32767 +#define NL_SETMAX 255 +#define NL_TEXTMAX 2048 + +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_XOPEN_SOURCE) + +#ifdef PAGESIZE +#define PAGE_SIZE PAGESIZE +#endif +#define NZERO 20 +#define NL_LANGMAX 32 + +#endif + +#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) \ + || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700) + +#define NL_NMAX 16 + +#endif + +/* POSIX/SUS requirements follow. These numbers come directly + * from SUS and have nothing to do with the host system. */ + +#define _POSIX_AIO_LISTIO_MAX 2 +#define _POSIX_AIO_MAX 1 +#define _POSIX_ARG_MAX 4096 +#define _POSIX_CHILD_MAX 25 +#define _POSIX_CLOCKRES_MIN 20000000 +#define _POSIX_DELAYTIMER_MAX 32 +#define _POSIX_HOST_NAME_MAX 255 +#define _POSIX_LINK_MAX 8 +#define _POSIX_LOGIN_NAME_MAX 9 +#define _POSIX_MAX_CANON 255 +#define _POSIX_MAX_INPUT 255 +#define _POSIX_MQ_OPEN_MAX 8 +#define _POSIX_MQ_PRIO_MAX 32 +#define _POSIX_NAME_MAX 14 +#define _POSIX_NGROUPS_MAX 8 +#define _POSIX_OPEN_MAX 20 +#define _POSIX_PATH_MAX 256 +#define _POSIX_PIPE_BUF 512 +#define _POSIX_RE_DUP_MAX 255 +#define _POSIX_RTSIG_MAX 8 +#define _POSIX_SEM_NSEMS_MAX 256 +#define _POSIX_SEM_VALUE_MAX 32767 +#define _POSIX_SIGQUEUE_MAX 32 +#define _POSIX_SSIZE_MAX 32767 +#define _POSIX_STREAM_MAX 8 +#define _POSIX_SS_REPL_MAX 4 +#define _POSIX_SYMLINK_MAX 255 +#define _POSIX_SYMLOOP_MAX 8 +#define _POSIX_THREAD_DESTRUCTOR_ITERATIONS 4 +#define _POSIX_THREAD_KEYS_MAX 128 +#define _POSIX_THREAD_THREADS_MAX 64 +#define _POSIX_TIMER_MAX 32 +#define _POSIX_TRACE_EVENT_NAME_MAX 30 +#define _POSIX_TRACE_NAME_MAX 8 +#define _POSIX_TRACE_SYS_MAX 8 +#define _POSIX_TRACE_USER_EVENT_MAX 32 +#define _POSIX_TTY_NAME_MAX 9 +#define _POSIX_TZNAME_MAX 6 +#define _POSIX2_BC_BASE_MAX 99 +#define _POSIX2_BC_DIM_MAX 2048 +#define _POSIX2_BC_SCALE_MAX 99 +#define _POSIX2_BC_STRING_MAX 1000 +#define _POSIX2_CHARCLASS_NAME_MAX 14 +#define _POSIX2_COLL_WEIGHTS_MAX 2 +#define _POSIX2_EXPR_NEST_MAX 32 +#define _POSIX2_LINE_MAX 2048 +#define _POSIX2_RE_DUP_MAX 255 + +#define _XOPEN_IOV_MAX 16 +#define _XOPEN_NAME_MAX 255 +#define _XOPEN_PATH_MAX 1024 + +#endif diff --git a/src/musl_mutex/metrics_handlers.o b/src/musl_mutex/metrics_handlers.o new file mode 100644 index 0000000..5ef0340 Binary files /dev/null and b/src/musl_mutex/metrics_handlers.o differ diff --git a/src/musl_mutex/mman.h b/src/musl_mutex/mman.h new file mode 100644 index 0000000..1aa9ecb --- /dev/null +++ b/src/musl_mutex/mman.h @@ -0,0 +1,8 @@ +#ifndef SYS_MMAN_H +#define SYS_MMAN_H + +void __vm_wait(void); +void __vm_lock(void); +void __vm_unlock(void); + +#endif \ No newline at end of file diff --git a/src/musl_mutex/pthread_cond_broadcast.c b/src/musl_mutex/pthread_cond_broadcast.c new file mode 100644 index 0000000..b79573f --- /dev/null +++ b/src/musl_mutex/pthread_cond_broadcast.c @@ -0,0 +1,10 @@ +// #include "pthread_impl.h" + +// int __pthread_musl_cond_broadcast(musl_cond_t *c) +// { +// if (!c->_c_shared) return __private_cond_signal(c, -1); +// if (!c->_c_waiters) return 0; +// a_inc(&c->_c_seq); +// __wake(&c->_c_seq, -1, 0); +// return 0; +// } diff --git a/src/musl_mutex/pthread_cond_broadcast.o b/src/musl_mutex/pthread_cond_broadcast.o new file mode 100644 index 0000000..25fcbc4 Binary files /dev/null and b/src/musl_mutex/pthread_cond_broadcast.o differ diff --git a/src/musl_mutex/pthread_cond_destroy.c b/src/musl_mutex/pthread_cond_destroy.c new file mode 100644 index 0000000..e9e336d --- /dev/null +++ b/src/musl_mutex/pthread_cond_destroy.c @@ -0,0 +1,14 @@ +// #include "pthread_impl.h" + +// int __pthread_musl_cond_destroy(musl_cond_t *c) +// { +// if (c->_c_shared && c->_c_waiters) { +// int cnt; +// a_or(&c->_c_waiters, 0x80000000); +// a_inc(&c->_c_seq); +// __wake(&c->_c_seq, -1, 0); +// while ((cnt = c->_c_waiters) & 0x7fffffff) +// __wait(&c->_c_waiters, 0, cnt, 0); +// } +// return 0; +// } diff --git a/src/musl_mutex/pthread_cond_destroy.o b/src/musl_mutex/pthread_cond_destroy.o new file mode 100644 index 0000000..a3487ae Binary files /dev/null and b/src/musl_mutex/pthread_cond_destroy.o differ diff --git a/src/musl_mutex/pthread_cond_init.c b/src/musl_mutex/pthread_cond_init.c new file mode 100644 index 0000000..d6fb6d4 --- /dev/null +++ b/src/musl_mutex/pthread_cond_init.c @@ -0,0 +1,12 @@ +// #include "pthread_impl.h" + + +// // int __pthread_musl_cond_init(musl_cond_t *restrict c, const pthread_condattr_t *restrict a) +// // { +// // *c = (pthread_cond_t){0}; +// // if (a) { +// // c->_c_clock = a->__attr & 0x7fffffff; +// // if (a->__attr>>31) c->_c_shared = (void *)-1; +// // } +// // return 0; +// // } diff --git a/src/musl_mutex/pthread_cond_init.o b/src/musl_mutex/pthread_cond_init.o new file mode 100644 index 0000000..41541fb Binary files /dev/null and b/src/musl_mutex/pthread_cond_init.o differ diff --git a/src/musl_mutex/pthread_cond_signal.c b/src/musl_mutex/pthread_cond_signal.c new file mode 100644 index 0000000..3a852f9 --- /dev/null +++ b/src/musl_mutex/pthread_cond_signal.c @@ -0,0 +1,11 @@ +// #include "pthread_impl.h" + + +// int __pthread_musl_cond_signal(musl_cond_t *c) +// { +// if (!c->_c_shared) return __private_cond_signal(c, 1); +// if (!c->_c_waiters) return 0; +// a_inc(&c->_c_seq); +// __wake(&c->_c_seq, 1, 0); +// return 0; +// } diff --git a/src/musl_mutex/pthread_cond_signal.o b/src/musl_mutex/pthread_cond_signal.o new file mode 100644 index 0000000..28ccc0c Binary files /dev/null and b/src/musl_mutex/pthread_cond_signal.o differ diff --git a/src/musl_mutex/pthread_cond_timedwait.c b/src/musl_mutex/pthread_cond_timedwait.c new file mode 100644 index 0000000..3c63838 --- /dev/null +++ b/src/musl_mutex/pthread_cond_timedwait.c @@ -0,0 +1,214 @@ +// #include "pthread_impl.h" + + +// /* +// * struct waiter +// * +// * Waiter objects have automatic storage on the waiting thread, and +// * are used in building a linked list representing waiters currently +// * waiting on the condition variable or a group of waiters woken +// * together by a broadcast or signal; in the case of signal, this is a +// * degenerate list of one member. +// * +// * Waiter lists attached to the condition variable itself are +// * protected by the lock on the cv. Detached waiter lists are never +// * modified again, but can only be traversed in reverse order, and are +// * protected by the "barrier" locks in each node, which are unlocked +// * in turn to control wake order. +// * +// * Since process-shared cond var semantics do not necessarily allow +// * one thread to see another's automatic storage (they may be in +// * different processes), the waiter list is not used for the +// * process-shared case, but the structure is still used to store data +// * needed by the cancellation cleanup handler. +// */ + +// struct waiter { +// struct waiter *prev, *next; +// volatile int state, barrier; +// volatile int *notify; +// }; + +// /* Self-synchronized-destruction-safe lock functions */ + +// static inline void lock(volatile int *l) +// { +// if (a_cas(l, 0, 1)) { +// a_cas(l, 1, 2); +// do __wait(l, 0, 2, 1); +// while (a_cas(l, 0, 2)); +// } +// } + +// static inline void unlock(volatile int *l) +// { +// if (a_swap(l, 0)==2) +// __wake(l, 1, 1); +// } + +// 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|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS +// || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r); +// } + +// enum { +// WAITING, +// SIGNALED, +// LEAVING, +// }; + +// int __pthread_musl_cond_timedwait(musl_cond_t *restrict c, musl_mutex_t *restrict m, musl_context_t *restrict me, const struct timespec *restrict ts) +// { +// struct waiter node = { 0 }; +// int e, seq, clock = c->_c_clock, cs, shared=0, oldstate, tmp; +// volatile int *fut; + +// if ((m->_m_type&15) && (m->_m_lock&INT_MAX) != __pthread_self()->tid) +// return EPERM; + +// if (ts && ts->tv_nsec >= 1000000000UL) +// return EINVAL; + +// __pthread_testcancel(); + +// if (c->_c_shared) { +// shared = 1; +// fut = &c->_c_seq; +// seq = c->_c_seq; +// a_inc(&c->_c_waiters); +// } else { +// lock(&c->_c_lock); + +// seq = node.barrier = 2; +// fut = &node.barrier; +// node.state = WAITING; +// node.next = c->_c_head; +// c->_c_head = &node; +// if (!c->_c_tail) c->_c_tail = &node; +// else node.next->prev = &node; + +// unlock(&c->_c_lock); +// } + +// __pthread_musl_mutex_unlock(m); + +// __pthread_musl_setcancelstate(PTHREAD_CANCEL_MASKED, &cs); +// if (cs == PTHREAD_CANCEL_DISABLE) __pthread_musl_setcancelstate(cs, 0); + +// do e = __timedwait_cp(fut, seq, clock, ts, !shared); +// while (*fut==seq && (!e || e==EINTR)); +// if (e == EINTR) e = 0; + +// if (shared) { +// /* Suppress cancellation if a signal was potentially +// * consumed; this is a legitimate form of spurious +// * wake even if not. */ +// if (e == ECANCELED && c->_c_seq != seq) e = 0; +// if (a_fetch_add(&c->_c_waiters, -1) == -0x7fffffff) +// __wake(&c->_c_waiters, 1, 0); +// oldstate = WAITING; +// goto relock; +// } + +// oldstate = a_cas(&node.state, WAITING, LEAVING); + +// if (oldstate == WAITING) { +// /* Access to cv object is valid because this waiter was not +// * yet signaled and a new signal/broadcast cannot return +// * after seeing a LEAVING waiter without getting notified +// * via the futex notify below. */ + +// lock(&c->_c_lock); + +// if (c->_c_head == &node) c->_c_head = node.next; +// else if (node.prev) node.prev->next = node.next; +// if (c->_c_tail == &node) c->_c_tail = node.prev; +// else if (node.next) node.next->prev = node.prev; + +// unlock(&c->_c_lock); + +// if (node.notify) { +// if (a_fetch_add(node.notify, -1)==1) +// __wake(node.notify, 1, 1); +// } +// } else { +// /* Lock barrier first to control wake order. */ +// lock(&node.barrier); +// } + +// relock: +// /* Errors locking the mutex override any existing error or +// * cancellation, since the caller must see them to know the +// * state of the mutex. */ +// if ((tmp = pthread_mutex_lock(m))) e = tmp; + +// if (oldstate == WAITING) goto done; + +// if (!node.next && !(m->_m_type & 8)) +// a_inc(&m->_m_waiters); + +// /* Unlock the barrier that's holding back the next waiter, and +// * either wake it or requeue it to the mutex. */ +// if (node.prev) { +// int val = m->_m_lock; +// if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); +// unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); +// } else if (!(m->_m_type & 8)) { +// a_dec(&m->_m_waiters); +// } + +// /* Since a signal was consumed, cancellation is not permitted. */ +// if (e == ECANCELED) e = 0; + +// done: +// __pthread_setcancelstate(cs, 0); + +// if (e == ECANCELED) { +// __pthread_testcancel(); +// __pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0); +// } + +// return e; +// } + +// int __private_cond_signal(pthread_cond_t *c, int n) +// { +// struct waiter *p, *first=0; +// volatile int ref = 0; +// int cur; + +// lock(&c->_c_lock); +// for (p=c->_c_tail; n && p; p=p->prev) { +// if (a_cas(&p->state, WAITING, SIGNALED) != WAITING) { +// ref++; +// p->notify = &ref; +// } else { +// n--; +// if (!first) first=p; +// } +// } +// /* Split the list, leaving any remainder on the cv. */ +// if (p) { +// if (p->next) p->next->prev = 0; +// p->next = 0; +// } else { +// c->_c_head = 0; +// } +// c->_c_tail = p; +// unlock(&c->_c_lock); + +// /* Wait for any waiters in the LEAVING state to remove +// * themselves from the list before returning or allowing +// * signaled threads to proceed. */ +// while ((cur = ref)) __wait(&ref, 0, cur, 1); + +// /* Allow first signaled waiter, if any, to proceed. */ +// if (first) unlock(&first->barrier); + +// return 0; +// } + +// weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait); diff --git a/src/musl_mutex/pthread_cond_timedwait.o b/src/musl_mutex/pthread_cond_timedwait.o new file mode 100644 index 0000000..c1ba78f Binary files /dev/null and b/src/musl_mutex/pthread_cond_timedwait.o differ diff --git a/src/musl_mutex/pthread_cond_wait.c b/src/musl_mutex/pthread_cond_wait.c new file mode 100644 index 0000000..01523b8 --- /dev/null +++ b/src/musl_mutex/pthread_cond_wait.c @@ -0,0 +1,7 @@ +// #include "pthread_impl.h" +// // #include "../../include/muslmutex.h" + +// int __pthread_musl_cond_wait(pthread_cond_t *restrict c, __pthread_mutex_t *restrict m, musl_context_t *restrict me) +// { +// return __pthread_musl_cond_timedwait(c, m, 0); +// } diff --git a/src/musl_mutex/pthread_cond_wait.o b/src/musl_mutex/pthread_cond_wait.o new file mode 100644 index 0000000..e452b01 Binary files /dev/null and b/src/musl_mutex/pthread_cond_wait.o differ diff --git a/src/musl_mutex/pthread_condattr_destroy.c b/src/musl_mutex/pthread_condattr_destroy.c new file mode 100644 index 0000000..961aead --- /dev/null +++ b/src/musl_mutex/pthread_condattr_destroy.c @@ -0,0 +1,6 @@ +#include "pthread_impl.h" + +int __pthread_musl_condattr_destroy(__pthread_condattr_t *a) +{ + return 0; +} diff --git a/src/musl_mutex/pthread_condattr_init.c b/src/musl_mutex/pthread_condattr_init.c new file mode 100644 index 0000000..1d580bb --- /dev/null +++ b/src/musl_mutex/pthread_condattr_init.c @@ -0,0 +1,7 @@ +#include "pthread_impl.h" + +int __pthread_musl_condattr_init(__pthread_condattr_t *a) +{ + *a = (__pthread_condattr_t){0}; + return 0; +} diff --git a/src/musl_mutex/pthread_condattr_setclock.c b/src/musl_mutex/pthread_condattr_setclock.c new file mode 100644 index 0000000..c691735 --- /dev/null +++ b/src/musl_mutex/pthread_condattr_setclock.c @@ -0,0 +1,9 @@ +#include "pthread_impl.h" + +int __pthread_musl_condattr_setclock(pthread_condattr_t *a, clockid_t clk) +{ + if (clk < 0 || clk-2U < 2) return EINVAL; + a->__attr &= 0x80000000; + a->__attr |= clk; + return 0; +} diff --git a/src/musl_mutex/pthread_condattr_setpshared.c b/src/musl_mutex/pthread_condattr_setpshared.c new file mode 100644 index 0000000..bc98315 --- /dev/null +++ b/src/musl_mutex/pthread_condattr_setpshared.c @@ -0,0 +1,9 @@ +#include "pthread_impl.h" + +int __pthread_musl_condattr_setpshared(__pthread_condattr_t *a, int pshared) +{ + if (pshared > 1U) return EINVAL; + a->__attr &= 0x7fffffff; + a->__attr |= (unsigned)pshared<<31; + return 0; +} diff --git a/src/musl_mutex/pthread_impl.h b/src/musl_mutex/pthread_impl.h new file mode 100644 index 0000000..23eb272 --- /dev/null +++ b/src/musl_mutex/pthread_impl.h @@ -0,0 +1,93 @@ +#ifndef _PTHREAD_IMPL_H +#define _PTHREAD_IMPL_H + +#include "pthread_musl.h" +#include "syscall.h" +#include "mman.h" +#include "atomic.h" +#include "futex.h" +#include "errno.h" +#include "limits.h" +#include "alltypes_make.h" + +#define pthread __pthread + +enum { + DT_EXITED = 0, + DT_EXITING, + DT_JOINABLE, + DT_DETACHED, +}; + +#define __SU (sizeof(size_t)/sizeof(int)) + +#define _a_stacksize __u.__s[0] +#define _a_guardsize __u.__s[1] +#define _a_stackaddr __u.__s[2] +#define _a_detach __u.__i[3*__SU+0] +#define _a_sched __u.__i[3*__SU+1] +#define _a_policy __u.__i[3*__SU+2] +#define _a_prio __u.__i[3*__SU+3] +#define _m_type __u.__i[0] +#define _m_lock __u.__vi[1] +#define _m_waiters __u.__vi[2] +#define _m_prev __u.__p[3] +#define _m_next __u.__p[4] +#define _m_count __u.__i[5] +#define _c_shared __u.__p[0] +#define _c_seq __u.__vi[2] +#define _c_waiters __u.__vi[3] +#define _c_clock __u.__i[4] +#define _c_lock __u.__vi[8] +#define _c_head __u.__p[1] +#define _c_tail __u.__p[5] +#define _rw_lock __u.__vi[0] +#define _rw_waiters __u.__vi[1] +#define _rw_shared __u.__i[2] +#define _b_lock __u.__vi[0] +#define _b_waiters __u.__vi[1] +#define _b_limit __u.__i[2] +#define _b_count __u.__vi[3] +#define _b_waiters2 __u.__vi[4] +#define _b_inst __u.__p[3] + +#ifndef TP_OFFSET +#define TP_OFFSET 0 +#endif + +#ifndef DTP_OFFSET +#define DTP_OFFSET 0 +#endif + +#ifndef tls_mod_off_t +#define tls_mod_off_t size_t +#endif + +#define SIGTIMER 32 +#define SIGCANCEL 33 +#define SIGSYNCCALL 34 + + +// __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv) +int __timedwait(volatile int *addr, int val, clockid_t clk, const struct timespec *at, int priv); +// void __wait(volatile void *, volatile int *, int, int); +void __wait(volatile int *addr, volatile int *waiters, int val, int priv); + +static inline void __wake(volatile void *addr, int cnt, int priv) +{ + if (priv) priv = FUTEX_PRIVATE; + if (cnt<0) cnt = INT_MAX; + __syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS || + __syscall(SYS_futex, addr, FUTEX_WAKE, cnt); +} + +static inline void __futexwait(volatile void *addr, int val, int priv) +{ + if (priv) priv = FUTEX_PRIVATE; + __syscall(SYS_futex, addr, FUTEX_WAIT|priv, val, 0) != -ENOSYS || + __syscall(SYS_futex, addr, FUTEX_WAIT, val, 0); +} + + +#endif + \ No newline at end of file diff --git a/src/musl_mutex/pthread_musl.h b/src/musl_mutex/pthread_musl.h new file mode 100644 index 0000000..17849a9 --- /dev/null +++ b/src/musl_mutex/pthread_musl.h @@ -0,0 +1,86 @@ +// #ifndef _PTHREAD_H +// #define _PTHREAD_H +#pragma once +//#ifdef __cplusplus +//extern "C" { +//#endif + +#include "features.h" +#include "alltypes_make.h" + +#define __NEED_clockid_t +#define __NEED_struct_timespec +#define __NEED_pthread_t +#define __NEED_pthread_attr_t +#define __NEED_pthread_mutexattr_t +#define __NEED_pthread_mutex_t +#define __NEED_size_t + + +//#include +#include "time.h" + +#define PTHREAD_CREATE_JOINABLE 0 +#define PTHREAD_CREATE_DETACHED 1 + +#define PTHREAD_MUTEX_NORMAL 0 +#define PTHREAD_MUTEX_DEFAULT 0 +#define PTHREAD_MUTEX_RECURSIVE 1 +#define PTHREAD_MUTEX_ERRORCHECK 2 + +#define PTHREAD_MUTEX_STALLED 0 +#define PTHREAD_MUTEX_ROBUST 1 + +#define PTHREAD_PRIO_NONE 0 +#define PTHREAD_PRIO_INHERIT 1 +#define PTHREAD_PRIO_PROTECT 2 + +#define PTHREAD_INHERIT_SCHED 0 +#define PTHREAD_EXPLICIT_SCHED 1 + +#define PTHREAD_SCOPE_SYSTEM 0 +#define PTHREAD_SCOPE_PROCESS 1 + +#define PTHREAD_PROCESS_PRIVATE 0 +#define PTHREAD_PROCESS_SHARED 1 + +#define PTHREAD_MUTEX_INITIALIZER {{{0}}} +#define PTHREAD_RWLOCK_INITIALIZER {{{0}}} +#define PTHREAD_COND_INITIALIZER {{{0}}} +#define PTHREAD_ONCE_INIT 0 + +#define PTHREAD_CANCEL_ENABLE 0 +#define PTHREAD_CANCEL_DISABLE 1 +#define PTHREAD_CANCEL_MASKED 2 + +#define PTHREAD_CANCEL_DEFERRED 0 +#define PTHREAD_CANCEL_ASYNCHRONOUS 1 + +#define PTHREAD_CANCELED ((void *)-1) + +#define PTHREAD_BARRIER_SERIAL_THREAD (-1) + +#define PTHREAD_NULL ((pthread_t)0) + + +#ifdef __GNUC__ +__attribute__((const)) +#endif + +typedef void *musl_context_t; + +int __pthread_musl_mutex_lock(__pthread_mutex_t *impl, musl_context_t *me); +int __pthread_musl_mutex_unlock(__pthread_mutex_t *impl, musl_context_t *me); +int __pthread_musl_mutex_trylock(__pthread_mutex_t *, musl_context_t *me); +int __pthread_musl_mutex_timedlock(__pthread_mutex_t *restrict m, const struct timespec *restrict at, musl_context_t *me); +int __pthread_musl_mutex_init(__pthread_mutex_t *restrict m, const __pthread_mutexattr_t *restrict a); + +#ifdef _GNU_SOURCE +struct cpu_set_t; +#endif + +//#ifdef __cplusplus +//} +//#endif + +// #endif diff --git a/src/musl_mutex/pthread_mutex_init.c b/src/musl_mutex/pthread_mutex_init.c new file mode 100644 index 0000000..ab41595 --- /dev/null +++ b/src/musl_mutex/pthread_mutex_init.c @@ -0,0 +1,14 @@ +#include "pthread_impl.h" +#include +#include "assert.h" + +int __pthread_musl_mutex_init(__pthread_mutex_t *restrict m, const __pthread_mutexattr_t *restrict a) +{ + // fprintf(stderr, "Error __pthread_musl_mutex_init.\n"); + // assert(0); + // return 0; + + *m = (__pthread_mutex_t){0}; + if (a) m->_m_type = a->__attr; + return 0; +} \ No newline at end of file diff --git a/src/musl_mutex/pthread_mutex_init.o b/src/musl_mutex/pthread_mutex_init.o new file mode 100644 index 0000000..478fc81 Binary files /dev/null and b/src/musl_mutex/pthread_mutex_init.o differ diff --git a/src/musl_mutex/pthread_mutex_lock.c b/src/musl_mutex/pthread_mutex_lock.c new file mode 100644 index 0000000..2712eb3 --- /dev/null +++ b/src/musl_mutex/pthread_mutex_lock.c @@ -0,0 +1,14 @@ +#include "pthread_impl.h" +#include +#include + +int __pthread_musl_mutex_lock(__pthread_mutex_t *m, musl_context_t *me) +{ + // fprintf(stderr, "Error __pthread_musl_mutex_lock.\n"); + + if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL + && !a_cas(&m->_m_lock, 0, EBUSY)) + return 0; + + return __pthread_musl_mutex_timedlock(m, 0, me); +} diff --git a/src/musl_mutex/pthread_mutex_lock.o b/src/musl_mutex/pthread_mutex_lock.o new file mode 100644 index 0000000..a5652fb Binary files /dev/null and b/src/musl_mutex/pthread_mutex_lock.o differ diff --git a/src/musl_mutex/pthread_mutex_timedlock.c b/src/musl_mutex/pthread_mutex_timedlock.c new file mode 100644 index 0000000..a4a902c --- /dev/null +++ b/src/musl_mutex/pthread_mutex_timedlock.c @@ -0,0 +1,100 @@ +#include "pthread_impl.h" +#include "pthread_self_glibc.h" +#include + +#define IS32BIT(x) !((x)+0x80000000ULL>>32) +#define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63)) + +static int __futex4(volatile void *addr, int op, int val, const struct timespec *to) +{ +#ifdef SYS_futex_time64 + time_t s = to ? to->tv_sec : 0; + long ns = to ? to->tv_nsec : 0; + int r = -ENOSYS; + if (SYS_futex == SYS_futex_time64 || !IS32BIT(s)) + r = __syscall(SYS_futex_time64, addr, op, val, + to ? ((long long[]){s, ns}) : 0); + if (SYS_futex == SYS_futex_time64 || r!=-ENOSYS) return r; + to = to ? (void *)(long[]){CLAMP(s), ns} : 0; +#endif + return __syscall(SYS_futex, addr, op, val, to); +} + +static int pthread_musl_mutex_timedlock_pi(__pthread_mutex_t *restrict m, const struct timespec *restrict at, musl_context_t *me) +{ + // fprintf(stderr, "Error pthread_musl_mutex_timedlock_pi.\n"); + + int type = m->_m_type; + int priv = (type & 128) ^ 128; + unsigned long self = pthread_self_glibc(); + int e; + + //if (!priv) self->robust_list.pending = &m->_m_next; + + do e = -__futex4(&m->_m_lock, FUTEX_LOCK_PI|priv, 0, at); + while (e==EINTR); + //if (e) self->robust_list.pending = 0; + + switch (e) { + case 0: + /* Catch spurious success for non-robust mutexes. */ + if (!(type&4) && ((m->_m_lock & 0x40000000) || m->_m_waiters)) { + a_store(&m->_m_waiters, -1); + __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv); + //self->robust_list.pending = 0; + break; + } + /* Signal to trylock that we already have the lock. */ + m->_m_count = -1; + return __pthread_musl_mutex_trylock(m, me); + case ETIMEDOUT: + return e; + case EDEADLK: + if ((type&3) == PTHREAD_MUTEX_ERRORCHECK) return e; + } + do e = __timedwait(&(int){0}, 0, CLOCK_REALTIME, at, 1); + while (e != ETIMEDOUT); + return e; +} + +int __pthread_musl_mutex_timedlock(__pthread_mutex_t *restrict m, const struct timespec *restrict at, musl_context_t *me) +{ + // fprintf(stderr, "Error __pthread_musl_mutex_timedlock.\n"); + + if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL + && !a_cas(&m->_m_lock, 0, EBUSY)) + return 0; + + int type = m->_m_type; + int r, t, priv = (type & 128) ^ 128; + + r = __pthread_musl_mutex_trylock(m, me); + if (r != EBUSY) return r; + + if (type&8) return pthread_musl_mutex_timedlock_pi(m, at, me); + + int spins = 100; + while (spins-- && m->_m_lock && !m->_m_waiters) a_spin(); + + while ((r=__pthread_musl_mutex_trylock(m, me)) == EBUSY) { + r = m->_m_lock; + int own = r & 0x3fffffff; + if (!own && (!r || (type&4))) + continue; + // fprintf(stderr, "own: %d\n", own); + // fprintf(stderr, "pthread_self_glibc(): %ul\n", pthread_self_glibc()); + if ((type&3) == PTHREAD_MUTEX_ERRORCHECK + && own == pthread_self_glibc()) + // fprintf(stderr, "return EDEADLK 10;\n"); + return EDEADLK; + + a_inc(&m->_m_waiters); + t = r | 0x80000000; + a_cas(&m->_m_lock, r, t); + r = __timedwait(&m->_m_lock, t, CLOCK_REALTIME, at, priv); + a_dec(&m->_m_waiters); + if (r && r != EINTR) break; + } + // fprintf(stderr, "return r 98:\n"); + return r; +} diff --git a/src/musl_mutex/pthread_mutex_timedlock.o b/src/musl_mutex/pthread_mutex_timedlock.o new file mode 100644 index 0000000..5cdc76e Binary files /dev/null and b/src/musl_mutex/pthread_mutex_timedlock.o differ diff --git a/src/musl_mutex/pthread_mutex_trylock.c b/src/musl_mutex/pthread_mutex_trylock.c new file mode 100644 index 0000000..6af501d --- /dev/null +++ b/src/musl_mutex/pthread_mutex_trylock.c @@ -0,0 +1,102 @@ +#include "pthread_impl.h" +#include "pthread_self_glibc.h" +#include +#include + +int __pthread_musl_mutex_trylock_owner(__pthread_mutex_t *m) +{ + // fprintf(stderr, "Error pthread_musl_mutex_trylock_owner.\n"); + int old, own; + int type = m->_m_type; + // pthread_t self = pthread_self(); + unsigned long tid = pthread_self_glibc(); + + old = m->_m_lock; + own = old & 0x3fffffff; + if (own == tid) { + if ((type&8) && m->_m_count<0) { + old &= 0x40000000; + m->_m_count = 0; + goto success; + } + if ((type&3) == PTHREAD_MUTEX_RECURSIVE) { + if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN; + m->_m_count++; + return 0; + } + } + if (own == 0x3fffffff) { + // fprintf(stderr, "return ENOTRECOVERABLE 29;\n"); + return ENOTRECOVERABLE; + } + if (own || (old && !(type & 4))) { + // fprintf(stderr, "return EBUSY 33;\n"); + return EBUSY; + } + + //Work with robust_list + /* + if (type & 128) { + if (!self->robust_list.off) { + self->robust_list.off = (char*)&m->_m_lock-(char *)&m->_m_next; + __syscall(SYS_set_robust_list, &self->robust_list, 3*sizeof(long)); + } + if (m->_m_waiters) tid |= 0x80000000; + self->robust_list.pending = &m->_m_next; + } + */ + tid |= old & 0x40000000; + + if (a_cas(&m->_m_lock, old, tid) != old) { + //self->robust_list.pending = 0; + if ((type&12)==12 && m->_m_waiters) { + // fprintf(stderr, "return ENOTRECOVERABLE 53;\n"); + return ENOTRECOVERABLE; + } + // fprintf(stderr, "return EBUSY 56;\n"); + return EBUSY; + } + +success: + if ((type&8) && m->_m_waiters) { + int priv = (type & 128) ^ 128; + __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv); + //self->robust_list.pending = 0; + // fprintf(stderr, "return (type&4) ? ENOTRECOVERABLE : EBUSY;\n"); + return (type&4) ? ENOTRECOVERABLE : EBUSY; + } + + /* + volatile void *next = self->robust_list.head; + m->_m_next = next; + m->_m_prev = &self->robust_list.head; + if (next != &self->robust_list.head) *(volatile void *volatile *) + ((char *)next - sizeof(void *)) = &m->_m_next; + self->robust_list.head = &m->_m_next; + self->robust_list.pending = 0; + */ + + if (old) { + m->_m_count = 0; + // fprintf(stderr, "return EOWNERDEAD 81;\n"); + return EOWNERDEAD; + } + + // fprintf(stderr, "return 0;\n"); + return 0; +} + +int __pthread_musl_mutex_trylock(__pthread_mutex_t *m, musl_context_t *me) +{ + // fprintf(stderr, "Error __pthread_musl_mutex_trylock.\n"); + // fprintf(stderr, "Error cond_var not supported."); + // assert(1); + // return 0; + if ((m->_m_type&15) == PTHREAD_MUTEX_NORMAL) { + // fprintf(stderr, "return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY;\n"); + return a_cas(&m->_m_lock, 0, EBUSY) & EBUSY; + } + + // fprintf(stderr, "return __pthread_mutex_trylock_owner(m);\n"); + return __pthread_musl_mutex_trylock_owner(m); +} diff --git a/src/musl_mutex/pthread_mutex_trylock.o b/src/musl_mutex/pthread_mutex_trylock.o new file mode 100644 index 0000000..c16f6b2 Binary files /dev/null and b/src/musl_mutex/pthread_mutex_trylock.o differ diff --git a/src/musl_mutex/pthread_mutex_unlock.c b/src/musl_mutex/pthread_mutex_unlock.c new file mode 100644 index 0000000..9a14189 --- /dev/null +++ b/src/musl_mutex/pthread_mutex_unlock.c @@ -0,0 +1,62 @@ +#include "pthread_impl.h" +#include + +int __pthread_musl_mutex_unlock(__pthread_mutex_t *m, musl_context_t *me) +{ + // fprintf(stderr, "Error __pthread_musl_mutex_unlock.\n"); + unsigned long self; + int waiters = m->_m_waiters; + int cont; + int type = m->_m_type & 15; + int priv = (m->_m_type & 128) ^ 128; + int new = 0; + int old; + + if (type != PTHREAD_MUTEX_NORMAL) { + // fprintf(stderr, "type != PTHREAD_MUTEX_NORMAL\n"); + // self = __pthread_self(); + old = m->_m_lock; + int own = old & 0x3fffffff; + // if (own != self->tid) + // return EPERM; + if ((type&3) == PTHREAD_MUTEX_RECURSIVE && m->_m_count) { + // fprintf(stderr, "type&3 == PTHREAD_MUTEX_RECURSIVE && m->_m_count\n"); + return m->_m_count--, 0; + } + if ((type&4) && (old&0x40000000)) { + new = 0x7fffffff; + } + if (!priv) { + // self->robust_list.pending = &m->_m_next; + // fprintf(stderr, "!priv\n"); + __vm_lock(); + } + // volatile void *prev = m->_m_prev; + // volatile void *next = m->_m_next; + // *(volatile void *volatile *)prev = next; + // if (next != &self->robust_list.head) *(volatile void *volatile *) + // ((char *)next - sizeof(void *)) = prev; + } + if (type&8) { + if (old<0 || a_cas(&m->_m_lock, old, new)!=old) { + if (new) a_store(&m->_m_waiters, -1); + __syscall(SYS_futex, &m->_m_lock, FUTEX_UNLOCK_PI|priv); + } + cont = 0; + waiters = 0; + } else { + cont = a_swap(&m->_m_lock, new); + } + if (type != PTHREAD_MUTEX_NORMAL && !priv) { + // self->robust_list.pending = 0; + // fprintf(stderr, "type != PTHREAD_MUTEX_NORMAL && !priv\n"); + __vm_unlock(); + } + if (waiters || cont<0) + __wake(&m->_m_lock, 1, priv); + + // fprintf(stderr, "return 0 58;\n"); + return 0; +} + +// weak_alias(__pthread_musl_mutex_unlock, pthread_mutex_unlock); diff --git a/src/musl_mutex/pthread_mutex_unlock.o b/src/musl_mutex/pthread_mutex_unlock.o new file mode 100644 index 0000000..a7ef547 Binary files /dev/null and b/src/musl_mutex/pthread_mutex_unlock.o differ diff --git a/src/musl_mutex/pthread_self_glibc.c b/src/musl_mutex/pthread_self_glibc.c new file mode 100644 index 0000000..a11cce1 --- /dev/null +++ b/src/musl_mutex/pthread_self_glibc.c @@ -0,0 +1,7 @@ +#include + +#include "pthread_self_glibc.h" + +unsigned long int pthread_self_glibc () { + return pthread_self(); +} diff --git a/src/musl_mutex/pthread_self_glibc.h b/src/musl_mutex/pthread_self_glibc.h new file mode 100644 index 0000000..00a677b --- /dev/null +++ b/src/musl_mutex/pthread_self_glibc.h @@ -0,0 +1,2 @@ + +unsigned long int pthread_self_glibc (); \ No newline at end of file diff --git a/src/musl_mutex/pthread_self_glibc.o b/src/musl_mutex/pthread_self_glibc.o new file mode 100644 index 0000000..777b835 Binary files /dev/null and b/src/musl_mutex/pthread_self_glibc.o differ diff --git a/src/musl_mutex/pthread_setcancelstate_glibc.c b/src/musl_mutex/pthread_setcancelstate_glibc.c new file mode 100644 index 0000000..fd7314d --- /dev/null +++ b/src/musl_mutex/pthread_setcancelstate_glibc.c @@ -0,0 +1,7 @@ +#include "pthread_setcancelstate_glibc.h" + +#include + +int pthread_setcancelstate_glibc(int state, int *oldstate) { + return pthread_setcancelstate(state, oldstate); +} diff --git a/src/musl_mutex/pthread_setcancelstate_glibc.h b/src/musl_mutex/pthread_setcancelstate_glibc.h new file mode 100644 index 0000000..c80d54b --- /dev/null +++ b/src/musl_mutex/pthread_setcancelstate_glibc.h @@ -0,0 +1,3 @@ + + +int pthread_setcancelstate_glibc(int state, int *oldstate); diff --git a/src/musl_mutex/pthread_setcancelstate_glibc.o b/src/musl_mutex/pthread_setcancelstate_glibc.o new file mode 100644 index 0000000..cbd72ae Binary files /dev/null and b/src/musl_mutex/pthread_setcancelstate_glibc.o differ diff --git a/src/musl_mutex/stdint.h b/src/musl_mutex/stdint.h new file mode 100644 index 0000000..dc9ecbc --- /dev/null +++ b/src/musl_mutex/stdint.h @@ -0,0 +1,117 @@ +#ifndef _STDINT_H +#define _STDINT_H + +#define __NEED_int8_t +#define __NEED_int16_t +#define __NEED_int32_t +#define __NEED_int64_t + +#define __NEED_uint8_t +#define __NEED_uint16_t +#define __NEED_uint32_t +#define __NEED_uint64_t + +#define __NEED_intptr_t +#define __NEED_uintptr_t + +#define __NEED_intmax_t +#define __NEED_uintmax_t + +#include "alltypes_make.h" + +typedef int8_t int_fast8_t; +typedef int64_t int_fast64_t; + +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; + +typedef uint8_t uint_fast8_t; +typedef uint64_t uint_fast64_t; + +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +#define INT8_MIN (-1-0x7f) +#define INT16_MIN (-1-0x7fff) +#define INT32_MIN (-1-0x7fffffff) +#define INT64_MIN (-1-0x7fffffffffffffff) + +#define INT8_MAX (0x7f) +#define INT16_MAX (0x7fff) +#define INT32_MAX (0x7fffffff) +#define INT64_MAX (0x7fffffffffffffff) + +#define UINT8_MAX (0xff) +#define UINT16_MAX (0xffff) +#define UINT32_MAX (0xffffffffu) +#define UINT64_MAX (0xffffffffffffffffu) + +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST64_MIN INT64_MIN + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST64_MIN INT64_MIN + +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST64_MAX INT64_MAX + +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MAX INT64_MAX + +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +#define WINT_MIN 0U +#define WINT_MAX UINT32_MAX + +#if L'\0'-1 > 0 +#define WCHAR_MAX (0xffffffffu+L'\0') +#define WCHAR_MIN (0+L'\0') +#else +#define WCHAR_MAX (0x7fffffff+L'\0') +#define WCHAR_MIN (-1-0x7fffffff+L'\0') +#endif + +#define SIG_ATOMIC_MIN INT32_MIN +#define SIG_ATOMIC_MAX INT32_MAX + +#include "stdintx86_64.h" + +#define INT8_C(c) c +#define INT16_C(c) c +#define INT32_C(c) c + +#define UINT8_C(c) c +#define UINT16_C(c) c +#define UINT32_C(c) c ## U + +#if UINTPTR_MAX == UINT64_MAX +#define INT64_C(c) c ## L +#define UINT64_C(c) c ## UL +#define INTMAX_C(c) c ## L +#define UINTMAX_C(c) c ## UL +#else +#define INT64_C(c) c ## LL +#define UINT64_C(c) c ## ULL +#define INTMAX_C(c) c ## LL +#define UINTMAX_C(c) c ## ULL +#endif + +#endif diff --git a/src/musl_mutex/stdintx86_64.h b/src/musl_mutex/stdintx86_64.h new file mode 100644 index 0000000..1bb147f --- /dev/null +++ b/src/musl_mutex/stdintx86_64.h @@ -0,0 +1,20 @@ +typedef int32_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef uint32_t uint_fast16_t; +typedef uint32_t uint_fast32_t; + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST32_MIN INT32_MIN + +#define INT_FAST16_MAX INT32_MAX +#define INT_FAST32_MAX INT32_MAX + +#define UINT_FAST16_MAX UINT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INTPTR_MIN INT64_MIN +#define INTPTR_MAX INT64_MAX +#define UINTPTR_MAX UINT64_MAX +#define PTRDIFF_MIN INT64_MIN +#define PTRDIFF_MAX INT64_MAX +#define SIZE_MAX UINT64_MAX diff --git a/src/musl_mutex/syscall.h b/src/musl_mutex/syscall.h new file mode 100644 index 0000000..3f47186 --- /dev/null +++ b/src/musl_mutex/syscall.h @@ -0,0 +1,410 @@ +#ifndef _INTERNAL_SYSCALL_H +#define _INTERNAL_SYSCALL_H + +#include +#include +#include +#include "syscall_archx86_64.h" + +#ifndef SYSCALL_RLIM_INFINITY +#define SYSCALL_RLIM_INFINITY (~0ULL) +#endif + +#ifndef SYSCALL_MMAP2_UNIT +#define SYSCALL_MMAP2_UNIT 4096ULL +#endif + +#ifndef __SYSCALL_LL_PRW +#define __SYSCALL_LL_PRW(x) __SYSCALL_LL_O(x) +#endif + +#ifndef __scc +#define __scc(X) ((long) (X)) +typedef long syscall_arg_t; +#endif + +long __syscall_ret(unsigned long), + __syscall_cp(syscall_arg_t, syscall_arg_t, syscall_arg_t, syscall_arg_t, + syscall_arg_t, syscall_arg_t, syscall_arg_t); + +#define __syscall1(n,a) __syscall1(n,__scc(a)) +#define __syscall2(n,a,b) __syscall2(n,__scc(a),__scc(b)) +#define __syscall3(n,a,b,c) __syscall3(n,__scc(a),__scc(b),__scc(c)) +#define __syscall4(n,a,b,c,d) __syscall4(n,__scc(a),__scc(b),__scc(c),__scc(d)) +#define __syscall5(n,a,b,c,d,e) __syscall5(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e)) +#define __syscall6(n,a,b,c,d,e,f) __syscall6(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) +#define __syscall7(n,a,b,c,d,e,f,g) __syscall7(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f),__scc(g)) + +#define __SYSCALL_NARGS_X(a,b,c,d,e,f,g,h,n,...) n +#define __SYSCALL_NARGS(...) __SYSCALL_NARGS_X(__VA_ARGS__,7,6,5,4,3,2,1,0,) +#define __SYSCALL_CONCAT_X(a,b) a##b +#define __SYSCALL_CONCAT(a,b) __SYSCALL_CONCAT_X(a,b) +#define __SYSCALL_DISP(b,...) __SYSCALL_CONCAT(b,__SYSCALL_NARGS(__VA_ARGS__))(__VA_ARGS__) + +#define __syscall(...) __SYSCALL_DISP(__syscall,__VA_ARGS__) +#define syscall(...) __syscall_ret(__syscall(__VA_ARGS__)) + +#define socketcall(nm,a,b,c,d,e,f) __syscall_ret(__socketcall(nm,a,b,c,d,e,f)) +#define socketcall_cp(nm,a,b,c,d,e,f) __syscall_ret(__socketcall_cp(nm,a,b,c,d,e,f)) + +#define __syscall_cp0(n) (__syscall_cp)(n,0,0,0,0,0,0) +#define __syscall_cp1(n,a) (__syscall_cp)(n,__scc(a),0,0,0,0,0) +#define __syscall_cp2(n,a,b) (__syscall_cp)(n,__scc(a),__scc(b),0,0,0,0) +#define __syscall_cp3(n,a,b,c) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),0,0,0) +#define __syscall_cp4(n,a,b,c,d) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),0,0) +#define __syscall_cp5(n,a,b,c,d,e) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),0) +#define __syscall_cp6(n,a,b,c,d,e,f) (__syscall_cp)(n,__scc(a),__scc(b),__scc(c),__scc(d),__scc(e),__scc(f)) + +#define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__) +#define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__)) + +static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, syscall_arg_t b, syscall_arg_t c, syscall_arg_t d, syscall_arg_t e, syscall_arg_t f) +{ + long r; + if (cp) r = __syscall_cp(sys, a, b, c, d, e, f); + else r = __syscall(sys, a, b, c, d, e, f); + if (r != -ENOSYS) return r; +#ifdef SYS_socketcall + if (cp) r = __syscall_cp(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); + else r = __syscall(SYS_socketcall, sock, ((long[6]){a, b, c, d, e, f})); +#endif + return r; +} +#define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \ + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f)) +#define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \ + __scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f)) + +/* fixup legacy 16-bit junk */ + +#ifdef SYS_getuid32 +#undef SYS_lchown +#undef SYS_getuid +#undef SYS_getgid +#undef SYS_geteuid +#undef SYS_getegid +#undef SYS_setreuid +#undef SYS_setregid +#undef SYS_getgroups +#undef SYS_setgroups +#undef SYS_fchown +#undef SYS_setresuid +#undef SYS_getresuid +#undef SYS_setresgid +#undef SYS_getresgid +#undef SYS_chown +#undef SYS_setuid +#undef SYS_setgid +#undef SYS_setfsuid +#undef SYS_setfsgid +#define SYS_lchown SYS_lchown32 +#define SYS_getuid SYS_getuid32 +#define SYS_getgid SYS_getgid32 +#define SYS_geteuid SYS_geteuid32 +#define SYS_getegid SYS_getegid32 +#define SYS_setreuid SYS_setreuid32 +#define SYS_setregid SYS_setregid32 +#define SYS_getgroups SYS_getgroups32 +#define SYS_setgroups SYS_setgroups32 +#define SYS_fchown SYS_fchown32 +#define SYS_setresuid SYS_setresuid32 +#define SYS_getresuid SYS_getresuid32 +#define SYS_setresgid SYS_setresgid32 +#define SYS_getresgid SYS_getresgid32 +#define SYS_chown SYS_chown32 +#define SYS_setuid SYS_setuid32 +#define SYS_setgid SYS_setgid32 +#define SYS_setfsuid SYS_setfsuid32 +#define SYS_setfsgid SYS_setfsgid32 +#endif + + +/* fixup legacy 32-bit-vs-lfs64 junk */ + +#ifdef SYS_fcntl64 +#undef SYS_fcntl +#define SYS_fcntl SYS_fcntl64 +#endif + +#ifdef SYS_getdents64 +#undef SYS_getdents +#define SYS_getdents SYS_getdents64 +#endif + +#ifdef SYS_ftruncate64 +#undef SYS_ftruncate +#undef SYS_truncate +#define SYS_ftruncate SYS_ftruncate64 +#define SYS_truncate SYS_truncate64 +#endif + +#ifdef SYS_stat64 +#undef SYS_stat +#define SYS_stat SYS_stat64 +#endif + +#ifdef SYS_fstat64 +#undef SYS_fstat +#define SYS_fstat SYS_fstat64 +#endif + +#ifdef SYS_lstat64 +#undef SYS_lstat +#define SYS_lstat SYS_lstat64 +#endif + +#ifdef SYS_statfs64 +#undef SYS_statfs +#define SYS_statfs SYS_statfs64 +#endif + +#ifdef SYS_fstatfs64 +#undef SYS_fstatfs +#define SYS_fstatfs SYS_fstatfs64 +#endif + +#if defined(SYS_newfstatat) +#undef SYS_fstatat +#define SYS_fstatat SYS_newfstatat +#elif defined(SYS_fstatat64) +#undef SYS_fstatat +#define SYS_fstatat SYS_fstatat64 +#endif + +#ifdef SYS_ugetrlimit +#undef SYS_getrlimit +#define SYS_getrlimit SYS_ugetrlimit +#endif + +#ifdef SYS__newselect +#undef SYS_select +#define SYS_select SYS__newselect +#endif + +#ifdef SYS_pread64 +#undef SYS_pread +#undef SYS_pwrite +#define SYS_pread SYS_pread64 +#define SYS_pwrite SYS_pwrite64 +#endif + +#ifdef SYS_fadvise64_64 +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64_64 +#elif defined(SYS_fadvise64) +#undef SYS_fadvise +#define SYS_fadvise SYS_fadvise64 +#endif + +#ifdef SYS_sendfile64 +#undef SYS_sendfile +#define SYS_sendfile SYS_sendfile64 +#endif + +#ifdef SYS_timer_settime32 +#define SYS_timer_settime SYS_timer_settime32 +#endif + +#ifdef SYS_timer_gettime32 +#define SYS_timer_gettime SYS_timer_gettime32 +#endif + +#ifdef SYS_timerfd_settime32 +#define SYS_timerfd_settime SYS_timerfd_settime32 +#endif + +#ifdef SYS_timerfd_gettime32 +#define SYS_timerfd_gettime SYS_timerfd_gettime32 +#endif + +#ifdef SYS_clock_settime32 +#define SYS_clock_settime SYS_clock_settime32 +#endif + +#ifdef SYS_clock_gettime32 +#define SYS_clock_gettime SYS_clock_gettime32 +#endif + +#ifdef SYS_clock_getres_time32 +#define SYS_clock_getres SYS_clock_getres_time32 +#endif + +#ifdef SYS_clock_nanosleep_time32 +#define SYS_clock_nanosleep SYS_clock_nanosleep_time32 +#endif + +#ifdef SYS_gettimeofday_time32 +#define SYS_gettimeofday SYS_gettimeofday_time32 +#endif + +#ifdef SYS_settimeofday_time32 +#define SYS_settimeofday SYS_settimeofday_time32 +#endif + +/* Ensure that the plain syscall names are defined even for "time64-only" + * archs. These facilitate callers passing null time arguments, and make + * tests for establishing which to use/fallback-to more consistent when + * they do need to be called with time arguments. */ + +#ifndef SYS_clock_gettime +#define SYS_clock_gettime SYS_clock_gettime64 +#endif + +#ifndef SYS_clock_settime +#define SYS_clock_settime SYS_clock_settime64 +#endif + +#ifndef SYS_clock_adjtime +#define SYS_clock_adjtime SYS_clock_adjtime64 +#endif + +#ifndef SYS_clock_getres +#define SYS_clock_getres SYS_clock_getres_time64 +#endif + +#ifndef SYS_clock_nanosleep +#define SYS_clock_nanosleep SYS_clock_nanosleep_time64 +#endif + +#ifndef SYS_timer_gettime +#define SYS_timer_gettime SYS_timer_gettime64 +#endif + +#ifndef SYS_timer_settime +#define SYS_timer_settime SYS_timer_settime64 +#endif + +#ifndef SYS_timerfd_gettime +#define SYS_timerfd_gettime SYS_timerfd_gettime64 +#endif + +#ifndef SYS_timerfd_settime +#define SYS_timerfd_settime SYS_timerfd_settime64 +#endif + +#ifndef SYS_utimensat +#define SYS_utimensat SYS_utimensat_time64 +#endif + +#ifndef SYS_pselect6 +#define SYS_pselect6 SYS_pselect6_time64 +#endif + +#ifndef SYS_ppoll +#define SYS_ppoll SYS_ppoll_time64 +#endif + +#ifndef SYS_recvmmsg +#define SYS_recvmmsg SYS_recvmmsg_time64 +#endif + +#ifndef SYS_mq_timedsend +#define SYS_mq_timedsend SYS_mq_timedsend_time64 +#endif + +#ifndef SYS_mq_timedreceive +#define SYS_mq_timedreceive SYS_mq_timedreceive_time64 +#endif + +/* SYS_semtimedop omitted because SYS_ipc may provide it */ + +#ifndef SYS_rt_sigtimedwait +#define SYS_rt_sigtimedwait SYS_rt_sigtimedwait_time64 +#endif + +#ifndef SYS_futex +#define SYS_futex SYS_futex_time64 +#endif + +#ifndef SYS_sched_rr_get_interval +#define SYS_sched_rr_get_interval SYS_sched_rr_get_interval_time64 +#endif + + + + +/* socketcall calls */ + +#define __SC_socket 1 +#define __SC_bind 2 +#define __SC_connect 3 +#define __SC_listen 4 +#define __SC_accept 5 +#define __SC_getsockname 6 +#define __SC_getpeername 7 +#define __SC_socketpair 8 +#define __SC_send 9 +#define __SC_recv 10 +#define __SC_sendto 11 +#define __SC_recvfrom 12 +#define __SC_shutdown 13 +#define __SC_setsockopt 14 +#define __SC_getsockopt 15 +#define __SC_sendmsg 16 +#define __SC_recvmsg 17 +#define __SC_accept4 18 +#define __SC_recvmmsg 19 +#define __SC_sendmmsg 20 + +/* This is valid only because all socket syscalls are made via + * socketcall, which always fills unused argument slots with zeros. */ +#ifndef SYS_accept +#define SYS_accept SYS_accept4 +#endif + +#ifndef SO_RCVTIMEO_OLD +#define SO_RCVTIMEO_OLD 20 +#endif +#ifndef SO_SNDTIMEO_OLD +#define SO_SNDTIMEO_OLD 21 +#endif + +#define SO_TIMESTAMP_OLD 29 +#define SO_TIMESTAMPNS_OLD 35 +#define SO_TIMESTAMPING_OLD 37 +#define SCM_TIMESTAMP_OLD SO_TIMESTAMP_OLD +#define SCM_TIMESTAMPNS_OLD SO_TIMESTAMPNS_OLD +#define SCM_TIMESTAMPING_OLD SO_TIMESTAMPING_OLD + +#ifndef SIOCGSTAMP_OLD +#define SIOCGSTAMP_OLD 0x8906 +#endif +#ifndef SIOCGSTAMPNS_OLD +#define SIOCGSTAMPNS_OLD 0x8907 +#endif + +#ifdef SYS_open +#define __sys_open2(x,pn,fl) __syscall2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp2(SYS_open, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp3(SYS_open, pn, (fl)|O_LARGEFILE, mo) +#else +#define __sys_open2(x,pn,fl) __syscall3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open3(x,pn,fl,mo) __syscall4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#define __sys_open_cp2(x,pn,fl) __syscall_cp3(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE) +#define __sys_open_cp3(x,pn,fl,mo) __syscall_cp4(SYS_openat, AT_FDCWD, pn, (fl)|O_LARGEFILE, mo) +#endif + +#define __sys_open(...) __SYSCALL_DISP(__sys_open,,__VA_ARGS__) +#define sys_open(...) __syscall_ret(__sys_open(__VA_ARGS__)) + +#define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__) +#define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__)) + +#ifdef SYS_wait4 +#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d) +#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d) +#else +hidden long __emulate_wait4(int, int *, int, void *, int); +#define __sys_wait4(a,b,c,d) __emulate_wait4(a,b,c,d,0) +#define __sys_wait4_cp(a,b,c,d) __emulate_wait4(a,b,c,d,1) +#endif + +#define sys_wait4(a,b,c,d) __syscall_ret(__sys_wait4(a,b,c,d)) +#define sys_wait4_cp(a,b,c,d) __syscall_ret(__sys_wait4_cp(a,b,c,d)) + +void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned); + +void *__vdsosym(const char *, const char *); + +#endif diff --git a/src/musl_mutex/syscall_archx86_64.h b/src/musl_mutex/syscall_archx86_64.h new file mode 100644 index 0000000..92d5c17 --- /dev/null +++ b/src/musl_mutex/syscall_archx86_64.h @@ -0,0 +1,70 @@ +#define __SYSCALL_LL_E(x) (x) +#define __SYSCALL_LL_O(x) (x) + +static __inline long __syscall0(long n) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall1(long n, long a1) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall2(long n, long a1, long a2) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2) + : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall3(long n, long a1, long a2, long a3) +{ + unsigned long ret; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall4(long n, long a1, long a2, long a3, long a4) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10): "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall5(long n, long a1, long a2, long a3, long a4, long a5) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8) : "rcx", "r11", "memory"); + return ret; +} + +static __inline long __syscall6(long n, long a1, long a2, long a3, long a4, long a5, long a6) +{ + unsigned long ret; + register long r10 __asm__("r10") = a4; + register long r8 __asm__("r8") = a5; + register long r9 __asm__("r9") = a6; + __asm__ __volatile__ ("syscall" : "=a"(ret) : "a"(n), "D"(a1), "S"(a2), + "d"(a3), "r"(r10), "r"(r8), "r"(r9) : "rcx", "r11", "memory"); + return ret; +} + +#define VDSO_USEFUL +#define VDSO_CGT_SYM "__vdso_clock_gettime" +#define VDSO_CGT_VER "LINUX_2.6" +#define VDSO_GETCPU_SYM "__vdso_getcpu" +#define VDSO_GETCPU_VER "LINUX_2.6" + +#define IPC_64 0 diff --git a/src/musl_mutex/syscall_make.h b/src/musl_mutex/syscall_make.h new file mode 100644 index 0000000..25ccb44 --- /dev/null +++ b/src/musl_mutex/syscall_make.h @@ -0,0 +1,727 @@ +#define __NR_read 0 +#define __NR_write 1 +#define __NR_open 2 +#define __NR_close 3 +#define __NR_stat 4 +#define __NR_fstat 5 +#define __NR_lstat 6 +#define __NR_poll 7 +#define __NR_lseek 8 +#define __NR_mmap 9 +#define __NR_mprotect 10 +#define __NR_munmap 11 +#define __NR_brk 12 +#define __NR_rt_sigaction 13 +#define __NR_rt_sigprocmask 14 +#define __NR_rt_sigreturn 15 +#define __NR_ioctl 16 +#define __NR_pread64 17 +#define __NR_pwrite64 18 +#define __NR_readv 19 +#define __NR_writev 20 +#define __NR_access 21 +#define __NR_pipe 22 +#define __NR_select 23 +#define __NR_sched_yield 24 +#define __NR_mremap 25 +#define __NR_msync 26 +#define __NR_mincore 27 +#define __NR_madvise 28 +#define __NR_shmget 29 +#define __NR_shmat 30 +#define __NR_shmctl 31 +#define __NR_dup 32 +#define __NR_dup2 33 +#define __NR_pause 34 +#define __NR_nanosleep 35 +#define __NR_getitimer 36 +#define __NR_alarm 37 +#define __NR_setitimer 38 +#define __NR_getpid 39 +#define __NR_sendfile 40 +#define __NR_socket 41 +#define __NR_connect 42 +#define __NR_accept 43 +#define __NR_sendto 44 +#define __NR_recvfrom 45 +#define __NR_sendmsg 46 +#define __NR_recvmsg 47 +#define __NR_shutdown 48 +#define __NR_bind 49 +#define __NR_listen 50 +#define __NR_getsockname 51 +#define __NR_getpeername 52 +#define __NR_socketpair 53 +#define __NR_setsockopt 54 +#define __NR_getsockopt 55 +#define __NR_clone 56 +#define __NR_fork 57 +#define __NR_vfork 58 +#define __NR_execve 59 +#define __NR_exit 60 +#define __NR_wait4 61 +#define __NR_kill 62 +#define __NR_uname 63 +#define __NR_semget 64 +#define __NR_semop 65 +#define __NR_semctl 66 +#define __NR_shmdt 67 +#define __NR_msgget 68 +#define __NR_msgsnd 69 +#define __NR_msgrcv 70 +#define __NR_msgctl 71 +#define __NR_fcntl 72 +#define __NR_flock 73 +#define __NR_fsync 74 +#define __NR_fdatasync 75 +#define __NR_truncate 76 +#define __NR_ftruncate 77 +#define __NR_getdents 78 +#define __NR_getcwd 79 +#define __NR_chdir 80 +#define __NR_fchdir 81 +#define __NR_rename 82 +#define __NR_mkdir 83 +#define __NR_rmdir 84 +#define __NR_creat 85 +#define __NR_link 86 +#define __NR_unlink 87 +#define __NR_symlink 88 +#define __NR_readlink 89 +#define __NR_chmod 90 +#define __NR_fchmod 91 +#define __NR_chown 92 +#define __NR_fchown 93 +#define __NR_lchown 94 +#define __NR_umask 95 +#define __NR_gettimeofday 96 +#define __NR_getrlimit 97 +#define __NR_getrusage 98 +#define __NR_sysinfo 99 +#define __NR_times 100 +#define __NR_ptrace 101 +#define __NR_getuid 102 +#define __NR_syslog 103 +#define __NR_getgid 104 +#define __NR_setuid 105 +#define __NR_setgid 106 +#define __NR_geteuid 107 +#define __NR_getegid 108 +#define __NR_setpgid 109 +#define __NR_getppid 110 +#define __NR_getpgrp 111 +#define __NR_setsid 112 +#define __NR_setreuid 113 +#define __NR_setregid 114 +#define __NR_getgroups 115 +#define __NR_setgroups 116 +#define __NR_setresuid 117 +#define __NR_getresuid 118 +#define __NR_setresgid 119 +#define __NR_getresgid 120 +#define __NR_getpgid 121 +#define __NR_setfsuid 122 +#define __NR_setfsgid 123 +#define __NR_getsid 124 +#define __NR_capget 125 +#define __NR_capset 126 +#define __NR_rt_sigpending 127 +#define __NR_rt_sigtimedwait 128 +#define __NR_rt_sigqueueinfo 129 +#define __NR_rt_sigsuspend 130 +#define __NR_sigaltstack 131 +#define __NR_utime 132 +#define __NR_mknod 133 +#define __NR_uselib 134 +#define __NR_personality 135 +#define __NR_ustat 136 +#define __NR_statfs 137 +#define __NR_fstatfs 138 +#define __NR_sysfs 139 +#define __NR_getpriority 140 +#define __NR_setpriority 141 +#define __NR_sched_setparam 142 +#define __NR_sched_getparam 143 +#define __NR_sched_setscheduler 144 +#define __NR_sched_getscheduler 145 +#define __NR_sched_get_priority_max 146 +#define __NR_sched_get_priority_min 147 +#define __NR_sched_rr_get_interval 148 +#define __NR_mlock 149 +#define __NR_munlock 150 +#define __NR_mlockall 151 +#define __NR_munlockall 152 +#define __NR_vhangup 153 +#define __NR_modify_ldt 154 +#define __NR_pivot_root 155 +#define __NR__sysctl 156 +#define __NR_prctl 157 +#define __NR_arch_prctl 158 +#define __NR_adjtimex 159 +#define __NR_setrlimit 160 +#define __NR_chroot 161 +#define __NR_sync 162 +#define __NR_acct 163 +#define __NR_settimeofday 164 +#define __NR_mount 165 +#define __NR_umount2 166 +#define __NR_swapon 167 +#define __NR_swapoff 168 +#define __NR_reboot 169 +#define __NR_sethostname 170 +#define __NR_setdomainname 171 +#define __NR_iopl 172 +#define __NR_ioperm 173 +#define __NR_create_module 174 +#define __NR_init_module 175 +#define __NR_delete_module 176 +#define __NR_get_kernel_syms 177 +#define __NR_query_module 178 +#define __NR_quotactl 179 +#define __NR_nfsservctl 180 +#define __NR_getpmsg 181 +#define __NR_putpmsg 182 +#define __NR_afs_syscall 183 +#define __NR_tuxcall 184 +#define __NR_security 185 +#define __NR_gettid 186 +#define __NR_readahead 187 +#define __NR_setxattr 188 +#define __NR_lsetxattr 189 +#define __NR_fsetxattr 190 +#define __NR_getxattr 191 +#define __NR_lgetxattr 192 +#define __NR_fgetxattr 193 +#define __NR_listxattr 194 +#define __NR_llistxattr 195 +#define __NR_flistxattr 196 +#define __NR_removexattr 197 +#define __NR_lremovexattr 198 +#define __NR_fremovexattr 199 +#define __NR_tkill 200 +#define __NR_time 201 +#define __NR_futex 202 +#define __NR_sched_setaffinity 203 +#define __NR_sched_getaffinity 204 +#define __NR_set_thread_area 205 +#define __NR_io_setup 206 +#define __NR_io_destroy 207 +#define __NR_io_getevents 208 +#define __NR_io_submit 209 +#define __NR_io_cancel 210 +#define __NR_get_thread_area 211 +#define __NR_lookup_dcookie 212 +#define __NR_epoll_create 213 +#define __NR_epoll_ctl_old 214 +#define __NR_epoll_wait_old 215 +#define __NR_remap_file_pages 216 +#define __NR_getdents64 217 +#define __NR_set_tid_address 218 +#define __NR_restart_syscall 219 +#define __NR_semtimedop 220 +#define __NR_fadvise64 221 +#define __NR_timer_create 222 +#define __NR_timer_settime 223 +#define __NR_timer_gettime 224 +#define __NR_timer_getoverrun 225 +#define __NR_timer_delete 226 +#define __NR_clock_settime 227 +#define __NR_clock_gettime 228 +#define __NR_clock_getres 229 +#define __NR_clock_nanosleep 230 +#define __NR_exit_group 231 +#define __NR_epoll_wait 232 +#define __NR_epoll_ctl 233 +#define __NR_tgkill 234 +#define __NR_utimes 235 +#define __NR_vserver 236 +#define __NR_mbind 237 +#define __NR_set_mempolicy 238 +#define __NR_get_mempolicy 239 +#define __NR_mq_open 240 +#define __NR_mq_unlink 241 +#define __NR_mq_timedsend 242 +#define __NR_mq_timedreceive 243 +#define __NR_mq_notify 244 +#define __NR_mq_getsetattr 245 +#define __NR_kexec_load 246 +#define __NR_waitid 247 +#define __NR_add_key 248 +#define __NR_request_key 249 +#define __NR_keyctl 250 +#define __NR_ioprio_set 251 +#define __NR_ioprio_get 252 +#define __NR_inotify_init 253 +#define __NR_inotify_add_watch 254 +#define __NR_inotify_rm_watch 255 +#define __NR_migrate_pages 256 +#define __NR_openat 257 +#define __NR_mkdirat 258 +#define __NR_mknodat 259 +#define __NR_fchownat 260 +#define __NR_futimesat 261 +#define __NR_newfstatat 262 +#define __NR_unlinkat 263 +#define __NR_renameat 264 +#define __NR_linkat 265 +#define __NR_symlinkat 266 +#define __NR_readlinkat 267 +#define __NR_fchmodat 268 +#define __NR_faccessat 269 +#define __NR_pselect6 270 +#define __NR_ppoll 271 +#define __NR_unshare 272 +#define __NR_set_robust_list 273 +#define __NR_get_robust_list 274 +#define __NR_splice 275 +#define __NR_tee 276 +#define __NR_sync_file_range 277 +#define __NR_vmsplice 278 +#define __NR_move_pages 279 +#define __NR_utimensat 280 +#define __NR_epoll_pwait 281 +#define __NR_signalfd 282 +#define __NR_timerfd_create 283 +#define __NR_eventfd 284 +#define __NR_fallocate 285 +#define __NR_timerfd_settime 286 +#define __NR_timerfd_gettime 287 +#define __NR_accept4 288 +#define __NR_signalfd4 289 +#define __NR_eventfd2 290 +#define __NR_epoll_create1 291 +#define __NR_dup3 292 +#define __NR_pipe2 293 +#define __NR_inotify_init1 294 +#define __NR_preadv 295 +#define __NR_pwritev 296 +#define __NR_rt_tgsigqueueinfo 297 +#define __NR_perf_event_open 298 +#define __NR_recvmmsg 299 +#define __NR_fanotify_init 300 +#define __NR_fanotify_mark 301 +#define __NR_prlimit64 302 +#define __NR_name_to_handle_at 303 +#define __NR_open_by_handle_at 304 +#define __NR_clock_adjtime 305 +#define __NR_syncfs 306 +#define __NR_sendmmsg 307 +#define __NR_setns 308 +#define __NR_getcpu 309 +#define __NR_process_vm_readv 310 +#define __NR_process_vm_writev 311 +#define __NR_kcmp 312 +#define __NR_finit_module 313 +#define __NR_sched_setattr 314 +#define __NR_sched_getattr 315 +#define __NR_renameat2 316 +#define __NR_seccomp 317 +#define __NR_getrandom 318 +#define __NR_memfd_create 319 +#define __NR_kexec_file_load 320 +#define __NR_bpf 321 +#define __NR_execveat 322 +#define __NR_userfaultfd 323 +#define __NR_membarrier 324 +#define __NR_mlock2 325 +#define __NR_copy_file_range 326 +#define __NR_preadv2 327 +#define __NR_pwritev2 328 +#define __NR_pkey_mprotect 329 +#define __NR_pkey_alloc 330 +#define __NR_pkey_free 331 +#define __NR_statx 332 +#define __NR_io_pgetevents 333 +#define __NR_rseq 334 +#define __NR_pidfd_send_signal 424 +#define __NR_io_uring_setup 425 +#define __NR_io_uring_enter 426 +#define __NR_io_uring_register 427 +#define __NR_open_tree 428 +#define __NR_move_mount 429 +#define __NR_fsopen 430 +#define __NR_fsconfig 431 +#define __NR_fsmount 432 +#define __NR_fspick 433 +#define __NR_pidfd_open 434 +#define __NR_clone3 435 +#define __NR_close_range 436 +#define __NR_openat2 437 +#define __NR_pidfd_getfd 438 +#define __NR_faccessat2 439 +#define __NR_process_madvise 440 +#define __NR_epoll_pwait2 441 +#define __NR_mount_setattr 442 +#define __NR_landlock_create_ruleset 444 +#define __NR_landlock_add_rule 445 +#define __NR_landlock_restrict_self 446 +#define __NR_memfd_secret 447 +#define __NR_process_mrelease 448 +#define __NR_futex_waitv 449 +#define __NR_set_mempolicy_home_node 450 +#define __NR_cachestat 451 +#define __NR_fchmodat2 452 + +#define SYS_read 0 +#define SYS_write 1 +#define SYS_open 2 +#define SYS_close 3 +#define SYS_stat 4 +#define SYS_fstat 5 +#define SYS_lstat 6 +#define SYS_poll 7 +#define SYS_lseek 8 +#define SYS_mmap 9 +#define SYS_mprotect 10 +#define SYS_munmap 11 +#define SYS_brk 12 +#define SYS_rt_sigaction 13 +#define SYS_rt_sigprocmask 14 +#define SYS_rt_sigreturn 15 +#define SYS_ioctl 16 +#define SYS_pread64 17 +#define SYS_pwrite64 18 +#define SYS_readv 19 +#define SYS_writev 20 +#define SYS_access 21 +#define SYS_pipe 22 +#define SYS_select 23 +#define SYS_sched_yield 24 +#define SYS_mremap 25 +#define SYS_msync 26 +#define SYS_mincore 27 +#define SYS_madvise 28 +#define SYS_shmget 29 +#define SYS_shmat 30 +#define SYS_shmctl 31 +#define SYS_dup 32 +#define SYS_dup2 33 +#define SYS_pause 34 +#define SYS_nanosleep 35 +#define SYS_getitimer 36 +#define SYS_alarm 37 +#define SYS_setitimer 38 +#define SYS_getpid 39 +#define SYS_sendfile 40 +#define SYS_socket 41 +#define SYS_connect 42 +#define SYS_accept 43 +#define SYS_sendto 44 +#define SYS_recvfrom 45 +#define SYS_sendmsg 46 +#define SYS_recvmsg 47 +#define SYS_shutdown 48 +#define SYS_bind 49 +#define SYS_listen 50 +#define SYS_getsockname 51 +#define SYS_getpeername 52 +#define SYS_socketpair 53 +#define SYS_setsockopt 54 +#define SYS_getsockopt 55 +#define SYS_clone 56 +#define SYS_fork 57 +#define SYS_vfork 58 +#define SYS_execve 59 +#define SYS_exit 60 +#define SYS_wait4 61 +#define SYS_kill 62 +#define SYS_uname 63 +#define SYS_semget 64 +#define SYS_semop 65 +#define SYS_semctl 66 +#define SYS_shmdt 67 +#define SYS_msgget 68 +#define SYS_msgsnd 69 +#define SYS_msgrcv 70 +#define SYS_msgctl 71 +#define SYS_fcntl 72 +#define SYS_flock 73 +#define SYS_fsync 74 +#define SYS_fdatasync 75 +#define SYS_truncate 76 +#define SYS_ftruncate 77 +#define SYS_getdents 78 +#define SYS_getcwd 79 +#define SYS_chdir 80 +#define SYS_fchdir 81 +#define SYS_rename 82 +#define SYS_mkdir 83 +#define SYS_rmdir 84 +#define SYS_creat 85 +#define SYS_link 86 +#define SYS_unlink 87 +#define SYS_symlink 88 +#define SYS_readlink 89 +#define SYS_chmod 90 +#define SYS_fchmod 91 +#define SYS_chown 92 +#define SYS_fchown 93 +#define SYS_lchown 94 +#define SYS_umask 95 +#define SYS_gettimeofday 96 +#define SYS_getrlimit 97 +#define SYS_getrusage 98 +#define SYS_sysinfo 99 +#define SYS_times 100 +#define SYS_ptrace 101 +#define SYS_getuid 102 +#define SYS_syslog 103 +#define SYS_getgid 104 +#define SYS_setuid 105 +#define SYS_setgid 106 +#define SYS_geteuid 107 +#define SYS_getegid 108 +#define SYS_setpgid 109 +#define SYS_getppid 110 +#define SYS_getpgrp 111 +#define SYS_setsid 112 +#define SYS_setreuid 113 +#define SYS_setregid 114 +#define SYS_getgroups 115 +#define SYS_setgroups 116 +#define SYS_setresuid 117 +#define SYS_getresuid 118 +#define SYS_setresgid 119 +#define SYS_getresgid 120 +#define SYS_getpgid 121 +#define SYS_setfsuid 122 +#define SYS_setfsgid 123 +#define SYS_getsid 124 +#define SYS_capget 125 +#define SYS_capset 126 +#define SYS_rt_sigpending 127 +#define SYS_rt_sigtimedwait 128 +#define SYS_rt_sigqueueinfo 129 +#define SYS_rt_sigsuspend 130 +#define SYS_sigaltstack 131 +#define SYS_utime 132 +#define SYS_mknod 133 +#define SYS_uselib 134 +#define SYS_personality 135 +#define SYS_ustat 136 +#define SYS_statfs 137 +#define SYS_fstatfs 138 +#define SYS_sysfs 139 +#define SYS_getpriority 140 +#define SYS_setpriority 141 +#define SYS_sched_setparam 142 +#define SYS_sched_getparam 143 +#define SYS_sched_setscheduler 144 +#define SYS_sched_getscheduler 145 +#define SYS_sched_get_priority_max 146 +#define SYS_sched_get_priority_min 147 +#define SYS_sched_rr_get_interval 148 +#define SYS_mlock 149 +#define SYS_munlock 150 +#define SYS_mlockall 151 +#define SYS_munlockall 152 +#define SYS_vhangup 153 +#define SYS_modify_ldt 154 +#define SYS_pivot_root 155 +#define SYS__sysctl 156 +#define SYS_prctl 157 +#define SYS_arch_prctl 158 +#define SYS_adjtimex 159 +#define SYS_setrlimit 160 +#define SYS_chroot 161 +#define SYS_sync 162 +#define SYS_acct 163 +#define SYS_settimeofday 164 +#define SYS_mount 165 +#define SYS_umount2 166 +#define SYS_swapon 167 +#define SYS_swapoff 168 +#define SYS_reboot 169 +#define SYS_sethostname 170 +#define SYS_setdomainname 171 +#define SYS_iopl 172 +#define SYS_ioperm 173 +#define SYS_create_module 174 +#define SYS_init_module 175 +#define SYS_delete_module 176 +#define SYS_get_kernel_syms 177 +#define SYS_query_module 178 +#define SYS_quotactl 179 +#define SYS_nfsservctl 180 +#define SYS_getpmsg 181 +#define SYS_putpmsg 182 +#define SYS_afs_syscall 183 +#define SYS_tuxcall 184 +#define SYS_security 185 +#define SYS_gettid 186 +#define SYS_readahead 187 +#define SYS_setxattr 188 +#define SYS_lsetxattr 189 +#define SYS_fsetxattr 190 +#define SYS_getxattr 191 +#define SYS_lgetxattr 192 +#define SYS_fgetxattr 193 +#define SYS_listxattr 194 +#define SYS_llistxattr 195 +#define SYS_flistxattr 196 +#define SYS_removexattr 197 +#define SYS_lremovexattr 198 +#define SYS_fremovexattr 199 +#define SYS_tkill 200 +#define SYS_time 201 +#define SYS_futex 202 +#define SYS_sched_setaffinity 203 +#define SYS_sched_getaffinity 204 +#define SYS_set_thread_area 205 +#define SYS_io_setup 206 +#define SYS_io_destroy 207 +#define SYS_io_getevents 208 +#define SYS_io_submit 209 +#define SYS_io_cancel 210 +#define SYS_get_thread_area 211 +#define SYS_lookup_dcookie 212 +#define SYS_epoll_create 213 +#define SYS_epoll_ctl_old 214 +#define SYS_epoll_wait_old 215 +#define SYS_remap_file_pages 216 +#define SYS_getdents64 217 +#define SYS_set_tid_address 218 +#define SYS_restart_syscall 219 +#define SYS_semtimedop 220 +#define SYS_fadvise64 221 +#define SYS_timer_create 222 +#define SYS_timer_settime 223 +#define SYS_timer_gettime 224 +#define SYS_timer_getoverrun 225 +#define SYS_timer_delete 226 +#define SYS_clock_settime 227 +#define SYS_clock_gettime 228 +#define SYS_clock_getres 229 +#define SYS_clock_nanosleep 230 +#define SYS_exit_group 231 +#define SYS_epoll_wait 232 +#define SYS_epoll_ctl 233 +#define SYS_tgkill 234 +#define SYS_utimes 235 +#define SYS_vserver 236 +#define SYS_mbind 237 +#define SYS_set_mempolicy 238 +#define SYS_get_mempolicy 239 +#define SYS_mq_open 240 +#define SYS_mq_unlink 241 +#define SYS_mq_timedsend 242 +#define SYS_mq_timedreceive 243 +#define SYS_mq_notify 244 +#define SYS_mq_getsetattr 245 +#define SYS_kexec_load 246 +#define SYS_waitid 247 +#define SYS_add_key 248 +#define SYS_request_key 249 +#define SYS_keyctl 250 +#define SYS_ioprio_set 251 +#define SYS_ioprio_get 252 +#define SYS_inotify_init 253 +#define SYS_inotify_add_watch 254 +#define SYS_inotify_rm_watch 255 +#define SYS_migrate_pages 256 +#define SYS_openat 257 +#define SYS_mkdirat 258 +#define SYS_mknodat 259 +#define SYS_fchownat 260 +#define SYS_futimesat 261 +#define SYS_newfstatat 262 +#define SYS_unlinkat 263 +#define SYS_renameat 264 +#define SYS_linkat 265 +#define SYS_symlinkat 266 +#define SYS_readlinkat 267 +#define SYS_fchmodat 268 +#define SYS_faccessat 269 +#define SYS_pselect6 270 +#define SYS_ppoll 271 +#define SYS_unshare 272 +#define SYS_set_robust_list 273 +#define SYS_get_robust_list 274 +#define SYS_splice 275 +#define SYS_tee 276 +#define SYS_sync_file_range 277 +#define SYS_vmsplice 278 +#define SYS_move_pages 279 +#define SYS_utimensat 280 +#define SYS_epoll_pwait 281 +#define SYS_signalfd 282 +#define SYS_timerfd_create 283 +#define SYS_eventfd 284 +#define SYS_fallocate 285 +#define SYS_timerfd_settime 286 +#define SYS_timerfd_gettime 287 +#define SYS_accept4 288 +#define SYS_signalfd4 289 +#define SYS_eventfd2 290 +#define SYS_epoll_create1 291 +#define SYS_dup3 292 +#define SYS_pipe2 293 +#define SYS_inotify_init1 294 +#define SYS_preadv 295 +#define SYS_pwritev 296 +#define SYS_rt_tgsigqueueinfo 297 +#define SYS_perf_event_open 298 +#define SYS_recvmmsg 299 +#define SYS_fanotify_init 300 +#define SYS_fanotify_mark 301 +#define SYS_prlimit64 302 +#define SYS_name_to_handle_at 303 +#define SYS_open_by_handle_at 304 +#define SYS_clock_adjtime 305 +#define SYS_syncfs 306 +#define SYS_sendmmsg 307 +#define SYS_setns 308 +#define SYS_getcpu 309 +#define SYS_process_vm_readv 310 +#define SYS_process_vm_writev 311 +#define SYS_kcmp 312 +#define SYS_finit_module 313 +#define SYS_sched_setattr 314 +#define SYS_sched_getattr 315 +#define SYS_renameat2 316 +#define SYS_seccomp 317 +#define SYS_getrandom 318 +#define SYS_memfd_create 319 +#define SYS_kexec_file_load 320 +#define SYS_bpf 321 +#define SYS_execveat 322 +#define SYS_userfaultfd 323 +#define SYS_membarrier 324 +#define SYS_mlock2 325 +#define SYS_copy_file_range 326 +#define SYS_preadv2 327 +#define SYS_pwritev2 328 +#define SYS_pkey_mprotect 329 +#define SYS_pkey_alloc 330 +#define SYS_pkey_free 331 +#define SYS_statx 332 +#define SYS_io_pgetevents 333 +#define SYS_rseq 334 +#define SYS_pidfd_send_signal 424 +#define SYS_io_uring_setup 425 +#define SYS_io_uring_enter 426 +#define SYS_io_uring_register 427 +#define SYS_open_tree 428 +#define SYS_move_mount 429 +#define SYS_fsopen 430 +#define SYS_fsconfig 431 +#define SYS_fsmount 432 +#define SYS_fspick 433 +#define SYS_pidfd_open 434 +#define SYS_clone3 435 +#define SYS_close_range 436 +#define SYS_openat2 437 +#define SYS_pidfd_getfd 438 +#define SYS_faccessat2 439 +#define SYS_process_madvise 440 +#define SYS_epoll_pwait2 441 +#define SYS_mount_setattr 442 +#define SYS_landlock_create_ruleset 444 +#define SYS_landlock_add_rule 445 +#define SYS_landlock_restrict_self 446 +#define SYS_memfd_secret 447 +#define SYS_process_mrelease 448 +#define SYS_futex_waitv 449 +#define SYS_set_mempolicy_home_node 450 +#define SYS_cachestat 451 +#define SYS_fchmodat2 452 diff --git a/src/musl_mutex/syscall_ret.c b/src/musl_mutex/syscall_ret.c new file mode 100644 index 0000000..ba7ebcc --- /dev/null +++ b/src/musl_mutex/syscall_ret.c @@ -0,0 +1,13 @@ +#include "syscall.h" +#include +// #include + +long __syscall_ret(unsigned long r) +{ + // fprintf(stderr, "Error __syscall_ret.\n"); + if (r > -4096UL) { + // errno = -r; + return -1; + } + return r; +} diff --git a/src/musl_mutex/syscall_ret.o b/src/musl_mutex/syscall_ret.o new file mode 100644 index 0000000..51dfb56 Binary files /dev/null and b/src/musl_mutex/syscall_ret.o differ diff --git a/src/musl_mutex/test_build.sh b/src/musl_mutex/test_build.sh new file mode 100644 index 0000000..20ea9fd --- /dev/null +++ b/src/musl_mutex/test_build.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Clean first +make clean + +# Create the output directories if they don't exist +mkdir -p ../../obj/musl_mutex +mkdir -p ../../lib + +# Build the object files +make + +# Check if all object files were created +echo "Checking for object files..." +ls -la *.o + +# Display any errors during compilation +if [ $? -ne 0 ]; then + echo "Error: Failed to build object files" + exit 1 +fi + +echo "Build successful!" \ No newline at end of file diff --git a/src/musl_mutex/time.h b/src/musl_mutex/time.h new file mode 100644 index 0000000..41edc3a --- /dev/null +++ b/src/musl_mutex/time.h @@ -0,0 +1,10 @@ +#ifndef TIME_H +#define TIME_H + +#include "alltypes_make.h" + +int __clock_gettime(clockid_t, struct timespec *); + +#define CLOCK_REALTIME 0 + +#endif diff --git a/src/musl_mutex/vdso.c b/src/musl_mutex/vdso.c new file mode 100644 index 0000000..afecfe5 --- /dev/null +++ b/src/musl_mutex/vdso.c @@ -0,0 +1,93 @@ +#include +#include +#include "limits.h" +#include "stdint.h" +#include +#include "libc.h" +#include "syscall.h" + +#ifdef VDSO_USEFUL + +#if ULONG_MAX == 0xffffffff +typedef Elf32_Ehdr Ehdr; +typedef Elf32_Phdr Phdr; +typedef Elf32_Sym Sym; +typedef Elf32_Verdef Verdef; +typedef Elf32_Verdaux Verdaux; +#else +typedef Elf64_Ehdr Ehdr; +typedef Elf64_Phdr Phdr; +typedef Elf64_Sym Sym; +typedef Elf64_Verdef Verdef; +typedef Elf64_Verdaux Verdaux; +#endif + +static int checkver(Verdef *def, int vsym, const char *vername, char *strings) +{ + vsym &= 0x7fff; + for (;;) { + if (!(def->vd_flags & VER_FLG_BASE) + && (def->vd_ndx & 0x7fff) == vsym) + break; + if (def->vd_next == 0) + return 0; + def = (Verdef *)((char *)def + def->vd_next); + } + Verdaux *aux = (Verdaux *)((char *)def + def->vd_aux); + return !strcmp(vername, strings + aux->vda_name); +} + +#define OK_TYPES (1<e_phoff); + size_t *dynv=0, base=-1; + for (i=0; ie_phnum; i++, ph=(void *)((char *)ph+eh->e_phentsize)) { + if (ph->p_type == PT_LOAD) + base = (size_t)eh + ph->p_offset - ph->p_vaddr; + else if (ph->p_type == PT_DYNAMIC) + dynv = (void *)((char *)eh + ph->p_offset); + } + if (!dynv || base==(size_t)-1) return 0; + + char *strings = 0; + Sym *syms = 0; + Elf_Symndx *hashtab = 0; + uint16_t *versym = 0; + Verdef *verdef = 0; + + for (i=0; dynv[i]; i+=2) { + void *p = (void *)(base + dynv[i+1]); + switch(dynv[i]) { + case DT_STRTAB: strings = p; break; + case DT_SYMTAB: syms = p; break; + case DT_HASH: hashtab = p; break; + case DT_VERSYM: versym = p; break; + case DT_VERDEF: verdef = p; break; + } + } + + if (!strings || !syms || !hashtab) return 0; + if (!verdef) versym = 0; + + for (i=0; i>4) & OK_BINDS)) continue; + if (!syms[i].st_shndx) continue; + if (strcmp(name, strings+syms[i].st_name)) continue; + if (versym && !checkver(verdef, versym[i], vername, strings)) + continue; + return (void *)(base + syms[i].st_value); + } + + return 0; +} + +#endif diff --git a/src/musl_mutex/vdso.o b/src/musl_mutex/vdso.o new file mode 100644 index 0000000..003f429 Binary files /dev/null and b/src/musl_mutex/vdso.o differ diff --git a/src/musl_mutex/vmlock.c b/src/musl_mutex/vmlock.c new file mode 100644 index 0000000..c989caf --- /dev/null +++ b/src/musl_mutex/vmlock.c @@ -0,0 +1,23 @@ +#include "pthread_impl.h" +#include "mman.h" + +static volatile int vmlock[2]; +volatile int *const __vmlock_lockptr = vmlock; + +void __vm_wait() +{ + int tmp; + while ((tmp=vmlock[0])) + __wait(vmlock, vmlock+1, tmp, 1); +} + +void __vm_lock() +{ + a_inc(vmlock); +} + +void __vm_unlock() +{ + if (a_fetch_add(vmlock, -1)==1 && vmlock[1]) + __wake(vmlock, -1, 1); +} diff --git a/src/musl_mutex/vmlock.o b/src/musl_mutex/vmlock.o new file mode 100644 index 0000000..7709a31 Binary files /dev/null and b/src/musl_mutex/vmlock.o differ diff --git a/src/muslmutex.c b/src/muslmutex.c new file mode 100644 index 0000000..94ba1d4 --- /dev/null +++ b/src/muslmutex.c @@ -0,0 +1,353 @@ +#include +#include +#include +#include +#include +#include "interpose.h" +#include "utils.h" +#include "musl_mutex/pthread_musl.h" +#include "musl_mutex/pthread_impl.h" +#include "musl_mutex/pthread_self_glibc.h" +#include "musl_mutex/pthread_setcancelstate_glibc.h" + +musl_mutex_t *musl_mutex_create(const __pthread_mutexattr_t *attr) { + musl_mutex_t *impl = (musl_mutex_t*) calloc(1, sizeof(musl_mutex_t)); + + // #if COND_VAR + // REAL(__pthread_mutex_init)(&impl->lock, attr); + // #endif + + return impl; +} + +int musl_mutex_destroy(musl_mutex_t *lock) { + // #if COND_VAR + // REAL(__pthread_mutex_destroy)(lock); + // #endif + free(lock); + return 0; +} + +// int musl_cond_init(musl_cond_t *cond, const pthread_condattr_t *attr) { +// fprintf(stderr, "musl_cond_init\n"); +// #if COND_VAR +// return REAL(pthread_cond_init)(cond, attr); +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +// int musl_cond_timedwait(musl_cond_t *cond, musl_mutex_t *lock, musl_context_t *UNUSED(me), +// const struct timespec *ts) { +// fprintf(stderr, "musl_cond_timedwait\n"); +// #if COND_VAR +// int res; +// if (ts) +// res = REAL(pthread_cond_timedwait)(cond, &lock->lock, ts); +// else +// res = REAL(pthread_cond_wait)(cond, &lock->lock); + +// return res; +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +// int musl_cond_wait(musl_cond_t *cond, musl_mutex_t *lock, musl_context_t *UNUSED(me)) { +// fprintf(stderr, "musl_cond_wait\n"); +// #if COND_VAR +// int res = REAL(pthread_cond_wait)(cond, &lock->lock); +// return res; +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +// int musl_cond_signal(musl_cond_t *cond) { +// fprintf(stderr, "musl_cond_signal\n"); +// #if COND_VAR +// return REAL(pthread_cond_signal)(cond); +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +// int musl_cond_broadcast(musl_cond_t *cond) { +// fprintf(stderr, "musl_cond_broadcast\n"); +// #if COND_VAR +// return REAL(pthread_cond_broadcast)(cond); +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +// int musl_cond_destroy(musl_cond_t *cond) { +// fprintf(stderr, "musl_cond_destroy\n"); +// #if COND_VAR +// return REAL(pthread_cond_destroy)(cond); +// #else +// fprintf(stderr, "Error cond_var not supported."); +// assert(0); +// #endif +// } + +void musl_thread_start(void) { +} + +void musl_thread_exit(void) { +} + +void musl_application_init(void) { +} + +void musl_application_exit(void) { +} + +void musl_init_context(lock_mutex_t *impl, + lock_context_t *context, + int number) { +} + +int __pthread_musl_cond_wait(pthread_cond_t *restrict c, __pthread_mutex_t *restrict m, musl_context_t *restrict me) +{ + return __pthread_musl_cond_timedwait(c, m, me, 0); +} + +struct waiter { + struct waiter *prev, *next; + volatile int state, barrier; + volatile int *notify; +}; + +/* Self-synchronized-destruction-safe lock functions */ + +static inline void lock(volatile int *l) +{ + if (a_cas(l, 0, 1)) { + a_cas(l, 1, 2); + do __wait(l, 0, 2, 1); + while (a_cas(l, 0, 2)); + } +} + +static inline void unlock(volatile int *l) +{ + if (a_swap(l, 0)==2) + __wake(l, 1, 1); +} + +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|FUTEX_PRIVATE, 0, 1, r) != -ENOSYS + || __syscall(SYS_futex, l, FUTEX_REQUEUE, 0, 1, r); +} + +enum { + WAITING, + SIGNALED, + LEAVING, +}; + +int __pthread_musl_cond_timedwait(musl_cond_t *restrict c, musl_mutex_t *restrict m, musl_context_t *restrict me, const struct timespec *restrict ts) +{ + struct waiter node = { 0 }; + int e, seq, clock = c->_c_clock, cs, shared=0, oldstate, tmp; + volatile int *fut; + + if ((m->_m_type&15) && (m->_m_lock&INT_MAX) != pthread_self_glibc()) + return EPERM; + + if (ts && ts->tv_nsec >= 1000000000UL) + return EINVAL; + + // fprintf(stderr, "__pthread_testcancel 170\n"); + pthread_testcancel(); // TODO: Add this back + + if (c->_c_shared) { + shared = 1; + fut = &c->_c_seq; + seq = c->_c_seq; + a_inc(&c->_c_waiters); + } else { + lock(&c->_c_lock); + + seq = node.barrier = 2; + fut = &node.barrier; + node.state = WAITING; + node.next = c->_c_head; + c->_c_head = &node; + if (!c->_c_tail) c->_c_tail = &node; + else node.next->prev = &node; + + unlock(&c->_c_lock); + } + + __pthread_musl_mutex_unlock(m, me); + + pthread_setcancelstate_glibc(PTHREAD_CANCEL_MASKED, &cs); + if (cs == PTHREAD_CANCEL_DISABLE) pthread_setcancelstate_glibc(cs, 0); + + do e = __timedwait_cp(fut, seq, clock, ts, !shared); + while (*fut==seq && (!e || e==EINTR)); + if (e == EINTR) e = 0; + + if (shared) { + /* Suppress cancellation if a signal was potentially + * consumed; this is a legitimate form of spurious + * wake even if not. */ + if (e == ECANCELED && c->_c_seq != seq) e = 0; + if (a_fetch_add(&c->_c_waiters, -1) == -0x7fffffff) + __wake(&c->_c_waiters, 1, 0); + oldstate = WAITING; + goto relock; + } + + oldstate = a_cas(&node.state, WAITING, LEAVING); + + if (oldstate == WAITING) { + /* Access to cv object is valid because this waiter was not + * yet signaled and a new signal/broadcast cannot return + * after seeing a LEAVING waiter without getting notified + * via the futex notify below. */ + + lock(&c->_c_lock); + + if (c->_c_head == &node) c->_c_head = node.next; + else if (node.prev) node.prev->next = node.next; + if (c->_c_tail == &node) c->_c_tail = node.prev; + else if (node.next) node.next->prev = node.prev; + + unlock(&c->_c_lock); + + if (node.notify) { + if (a_fetch_add(node.notify, -1)==1) + __wake(node.notify, 1, 1); + } + } else { + /* Lock barrier first to control wake order. */ + lock(&node.barrier); + } + +relock: + /* Errors locking the mutex override any existing error or + * cancellation, since the caller must see them to know the + * state of the mutex. */ + if ((tmp = __pthread_musl_mutex_lock(m, me))) e = tmp; + + if (oldstate == WAITING) goto done; + + if (!node.next && !(m->_m_type & 8)) + a_inc(&m->_m_waiters); + + /* Unlock the barrier that's holding back the next waiter, and + * either wake it or requeue it to the mutex. */ + if (node.prev) { + int val = m->_m_lock; + if (val>0) a_cas(&m->_m_lock, val, val|0x80000000); + unlock_requeue(&node.prev->barrier, &m->_m_lock, m->_m_type & (8|128)); + } else if (!(m->_m_type & 8)) { + a_dec(&m->_m_waiters); + } + + /* Since a signal was consumed, cancellation is not permitted. */ + if (e == ECANCELED) e = 0; + +done: + pthread_setcancelstate_glibc(cs, 0); + + if (e == ECANCELED) { + fprintf(stderr, "__pthread_testcancel 266\n"); + // __pthread_testcancel(); // TODO: Add this back + pthread_testcancel(); + pthread_setcancelstate_glibc(PTHREAD_CANCEL_DISABLE, 0); + } + + return e; +} + +int __private_cond_signal(musl_cond_t *c, int n) +{ + struct waiter *p, *first=0; + volatile int ref = 0; + int cur; + + lock(&c->_c_lock); + for (p=c->_c_tail; n && p; p=p->prev) { + if (a_cas(&p->state, WAITING, SIGNALED) != WAITING) { + ref++; + p->notify = &ref; + } else { + n--; + if (!first) first=p; + } + } + /* Split the list, leaving any remainder on the cv. */ + if (p) { + if (p->next) p->next->prev = 0; + p->next = 0; + } else { + c->_c_head = 0; + } + c->_c_tail = p; + unlock(&c->_c_lock); + + /* Wait for any waiters in the LEAVING state to remove + * themselves from the list before returning or allowing + * signaled threads to proceed. */ + while ((cur = ref)) __wait(&ref, 0, cur, 1); + + /* Allow first signaled waiter, if any, to proceed. */ + if (first) unlock(&first->barrier); + + return 0; +} + +weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait); + +int __pthread_musl_cond_signal(musl_cond_t *c) +{ + if (!c->_c_shared) return __private_cond_signal(c, 1); + if (!c->_c_waiters) return 0; + a_inc(&c->_c_seq); + __wake(&c->_c_seq, 1, 0); + return 0; +} + +int __pthread_musl_cond_broadcast(musl_cond_t *c) +{ + if (!c->_c_shared) return __private_cond_signal(c, -1); + if (!c->_c_waiters) return 0; + a_inc(&c->_c_seq); + __wake(&c->_c_seq, -1, 0); + return 0; +} + +int __pthread_musl_cond_destroy(musl_cond_t *c) +{ + if (c->_c_shared && c->_c_waiters) { + int cnt; + a_or(&c->_c_waiters, 0x80000000); + a_inc(&c->_c_seq); + __wake(&c->_c_seq, -1, 0); + while ((cnt = c->_c_waiters) & 0x7fffffff) + __wait(&c->_c_waiters, 0, cnt, 0); + } + return 0; +} + +int __pthread_musl_cond_init(musl_cond_t *restrict c, const __pthread_condattr_t *restrict a) +{ + *c = (musl_cond_t){0}; + if (a) { + c->_c_clock = a->__attr & 0x7fffffff; + if (a->__attr>>31) c->_c_shared = (void *)-1; + } + return 0; +} diff --git a/src/ticketepfl.c b/src/ticketepfl.c index d322541..2360df3 100644 --- a/src/ticketepfl.c +++ b/src/ticketepfl.c @@ -96,7 +96,7 @@ int ticketepfl_mutex_lock(ticketepfl_mutex_t *impl, if (distance > 20) { sched_yield(); - /* pthread_yield(); */ + /* sched_yield(); */ } } diff --git a/src/utils.h b/src/utils.h index 5514bdf..0a7ce9f 100644 --- a/src/utils.h +++ b/src/utils.h @@ -109,9 +109,11 @@ static inline uint64_t rdtsc(void) { return low | ((uint64_t)high) << 32; } +#if !defined(__GLIBC__) || (__GLIBC__ == 2 && __GLIBC_MINOR__ < 30) static inline int gettid() { return syscall(SYS_gettid); } +#endif // EPFL libslock #define my_random xorshf96 diff --git a/test/Makefile b/test/Makefile new file mode 100644 index 0000000..eb9d0af --- /dev/null +++ b/test/Makefile @@ -0,0 +1,15 @@ +LDFLAGS= -lpthread + +all: test + +test: test_program.o read_args.o + gcc read_args.o test_program.o -o test_program $(LDFLAGS) + +test_program.o: test_program.c + gcc -c -ggdb test_program.c + +read_args.o: read_args.c mutex_test_args.h + gcc -c read_args.c + +clean: + rm -rf *.o diff --git a/test/mutex_test_args.h b/test/mutex_test_args.h new file mode 100644 index 0000000..fa2a5f0 --- /dev/null +++ b/test/mutex_test_args.h @@ -0,0 +1,6 @@ +struct mutex_test_args { + int thread_num; + int iter_num; +} typedef mutex_test_args; + +mutex_test_args read_args(int argc, char *argv[]); diff --git a/test/read_args.c b/test/read_args.c new file mode 100644 index 0000000..ef0173b --- /dev/null +++ b/test/read_args.c @@ -0,0 +1,47 @@ +#include +#include +#include "mutex_test_args.h" +#include + +void check_args(mutex_test_args *args) { + if (args->iter_num < 1) { + printf("Wrong iteration number: %d, setting it to the default: 1\n", args->iter_num); + args->iter_num = 1; + } + if (args->thread_num < 1) { + printf("Wrong thread number: %d, setting it to the default: 1\n", args->thread_num); + args->thread_num = 1; + } +} + +mutex_test_args read_args(int argc, char *argv[]) { + struct option long_opts[] = { + {"threads", required_argument, NULL, 't'}, + {"iterations", required_argument, NULL, 'i'}, + {NULL, 0, NULL, 0}}; + + char *opts = "t:i"; + int opt; + mutex_test_args args = {-1, -1}; + + int long_index; + opt = getopt_long(argc, argv, opts, long_opts, &long_index); + + while (opt != -1) { + switch (opt) { + case 't': { + sscanf(optarg, "%d", &args.thread_num); + break; + } + case 'i': { + sscanf(optarg, "%d", &args.iter_num); + break; + } + } + opt = getopt_long(argc, argv, opts, long_opts, &long_index); + } + + check_args(&args); + + return args; +} diff --git a/test/test_program.c b/test/test_program.c new file mode 100644 index 0000000..6755482 --- /dev/null +++ b/test/test_program.c @@ -0,0 +1,36 @@ +#include +#include +#include +#include "mutex_test_args.h" + +__uint64_t shared_num = 0; +pthread_mutex_t mutex; + +void *incr_shared_res(void *iter_num) { + int max_iterations = *(int *)iter_num; + for (__uint64_t i = 0; i < max_iterations; i++) { + pthread_mutex_lock(&mutex); + shared_num += 1; + //printf("shared_num current value: %d\n", shared_num); + pthread_mutex_unlock(&mutex); + } + // pthread_mutex_unlock(&mutex); +} + +int main(int argc, char *argv[]) { + pthread_mutex_init(&mutex, NULL); + + mutex_test_args args = read_args(argc, argv); + + pthread_t *threads = calloc(args.thread_num, sizeof(pthread_t)); + for (unsigned i = 0; i < args.thread_num; i++) { + pthread_create(&threads[i], NULL, incr_shared_res, &args.iter_num); + } + + for (unsigned i = 0; i < args.thread_num; i++) { + pthread_join(threads[i], NULL); + } + printf("shared_num value after threads work is: %d\n", shared_num); + free(threads); + return 0; +}