From 8c4d2b54a09be10e52a3e65570046ba4213adfe0 Mon Sep 17 00:00:00 2001 From: Alexey Suslov Date: Wed, 11 Feb 2026 22:00:55 +0500 Subject: [PATCH] Add compatibility for non-glibc (e.g. musl) builds --- Makefile | 3 +- common/drand48-compat.c | 150 ++++++++++++++++++++++++++++++++++++++ common/drand48-compat.h | 45 ++++++++++++ common/server-functions.c | 6 ++ jobs/jobs.h | 5 ++ 5 files changed, 208 insertions(+), 1 deletion(-) create mode 100644 common/drand48-compat.c create mode 100644 common/drand48-compat.h diff --git a/Makefile b/Makefile index 0800e659..ea0d950b 100644 --- a/Makefile +++ b/Makefile @@ -12,7 +12,7 @@ ifeq ($m, 64) ARCH = -m64 endif -CFLAGS = $(ARCH) -O3 -std=gnu11 -Wall -Wno-array-bounds -mpclmul -march=core2 -mfpmath=sse -mssse3 -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 +CFLAGS = $(ARCH) -O3 -std=gnu11 -Wall -Wextra -Wno-unused-parameter -Wno-error=array-bounds -Wno-error=incompatible-pointer-types -mpclmul -march=core2 -mfpmath=sse -mssse3 -fno-strict-aliasing -fno-strict-overflow -fwrapv -DAES=1 -DCOMMIT=\"${COMMIT}\" -D_GNU_SOURCE=1 -D_FILE_OFFSET_BITS=64 LDFLAGS = $(ARCH) -ggdb -rdynamic -lm -lrt -lcrypto -lz -lpthread -lcrypto LIB = ${OBJ}/lib @@ -40,6 +40,7 @@ DEPENDENCE_STRANGE := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJECTS_STRAN DEPENDENCE_NORM := $(subst ${OBJ}/,${DEP}/,$(patsubst %.o,%.d,${OBJECTS})) LIB_OBJS_NORMAL := \ + ${OBJ}/common/drand48-compat.o \ ${OBJ}/common/crc32c.o \ ${OBJ}/common/pid.o \ ${OBJ}/common/sha1.o \ diff --git a/common/drand48-compat.c b/common/drand48-compat.c new file mode 100644 index 00000000..de291d45 --- /dev/null +++ b/common/drand48-compat.c @@ -0,0 +1,150 @@ +#include "drand48-compat.h" +#include /* memset */ +#include /* ldexp */ + +#ifndef __GLIBC__ + +/* glibc-compatible constants */ +#define DR48_A 0x5deece66dULL +#define DR48_C 0x00000000bULL +#define DR48_MASK ((1ULL << 48) - 1ULL) + +static inline uint64_t pack48(const unsigned short x[3]) { + return ((uint64_t)x[0]) + | ((uint64_t)x[1] << 16) + | ((uint64_t)x[2] << 32); +} + +static inline void unpack48(uint64_t v, unsigned short x[3]) { + x[0] = (unsigned short)(v & 0xFFFFu); + x[1] = (unsigned short)((v >> 16) & 0xFFFFu); + x[2] = (unsigned short)((v >> 32) & 0xFFFFu); +} + +static inline void ensure_init(struct drand48_data *b) { + if (b-> __init) + return; + + /* Allow "zero-filled struct" init, as man page suggests. */ + b->__x[0] = 0x330e; + b->__x[1] = 0; + b->__x[2] = 0; + b->__a = DR48_A; + b->__c = (unsigned short)DR48_C; + b->__init = 1; +} + +static inline void iterate(unsigned short xsubi[3], struct drand48_data *b) { + uint64_t x = pack48(xsubi); + /* (a*x + c) mod 2^48 */ + x = (b->__a * x + (uint64_t)b->__c) & DR48_MASK; + unpack48(x, xsubi); +} + +int srand48_r(long int seedval, struct drand48_data *buffer) { + /* Standards say seedval is effectively 32-bit. */ + if (sizeof(long int) > 4) + seedval &= 0xffffffffL; + + buffer->__x[2] = (unsigned short)((uint32_t)seedval >> 16); + buffer->__x[1] = (unsigned short)((uint32_t)seedval & 0xFFFFu); + buffer->__x[0] = 0x330e; + + buffer->__a = DR48_A; + buffer->__c = (unsigned short)DR48_C; + buffer->__init = 1; + return 0; +} + +int seed48_r(unsigned short int seed16v[3], struct drand48_data *buffer) { + ensure_init(buffer); + + buffer->__old_x[0] = buffer->__x[0]; + buffer->__old_x[1] = buffer->__x[1]; + buffer->__old_x[2] = buffer->__x[2]; + + buffer->__x[0] = seed16v[0]; + buffer->__x[1] = seed16v[1]; + buffer->__x[2] = seed16v[2]; + + buffer->__a = DR48_A; + buffer->__c = (unsigned short)DR48_C; + buffer->__init = 1; + return 0; +} + +/* param[0..2] = X, param[3..5] = A, param[6] = C */ +int lcong48_r(unsigned short int param[7], struct drand48_data *buffer) { + buffer->__x[0] = param[0]; + buffer->__x[1] = param[1]; + buffer->__x[2] = param[2]; + + buffer->__a = ((unsigned long long)param[3]) + | ((unsigned long long)param[4] << 16) + | ((unsigned long long)param[5] << 32); + + buffer->__c = param[6]; + buffer->__init = 1; + return 0; +} + +int drand48_r(struct drand48_data *buffer, double *result) { + ensure_init(buffer); + iterate(buffer->__x, buffer); + + uint64_t x = pack48(buffer->__x); + /* x in [0, 2^48); convert to [0.0, 1.0) */ + *result = ldexp((double)x, -48); + return 0; +} + +int erand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, double *result) { + ensure_init(buffer); + iterate(xsubi, buffer); + + uint64_t x = pack48(xsubi); + *result = ldexp((double)x, -48); + return 0; +} + +int lrand48_r(struct drand48_data *buffer, long int *result) { + ensure_init(buffer); + iterate(buffer->__x, buffer); + + uint64_t x = pack48(buffer->__x); + /* non-negative in [0, 2^31) */ + *result = (long int)(x >> 17); + return 0; +} + +int nrand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) { + ensure_init(buffer); + iterate(xsubi, buffer); + + uint64_t x = pack48(xsubi); + *result = (long int)(x >> 17); + return 0; +} + +int mrand48_r(struct drand48_data *buffer, long int *result) { + ensure_init(buffer); + iterate(buffer->__x, buffer); + + uint64_t x = pack48(buffer->__x); + /* signed in [-2^31, 2^31) */ + int32_t v = (int32_t)(x >> 16); + *result = (long int)v; + return 0; +} + +int jrand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, long int *result) { + ensure_init(buffer); + iterate(xsubi, buffer); + + uint64_t x = pack48(xsubi); + int32_t v = (int32_t)(x >> 16); + *result = (long int)v; + return 0; +} + +#endif diff --git a/common/drand48-compat.h b/common/drand48-compat.h new file mode 100644 index 00000000..1a2c42ef --- /dev/null +++ b/common/drand48-compat.h @@ -0,0 +1,45 @@ +#pragma once + +/* + Drop-in drand48_r compat for non-glibc libcs (e.g., musl). + Provides: + struct drand48_data + srand48_r, seed48_r, lcong48_r + drand48_r, erand48_r + lrand48_r, nrand48_r + mrand48_r, jrand48_r + + Compile this ONLY when your libc doesn't provide these symbols, + otherwise you'll get duplicate symbol errors. +*/ + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +struct drand48_data { + unsigned short int __x[3]; /* Current state. */ + unsigned short int __old_x[3]; /* Old state. */ + unsigned short int __c; /* Additive const. */ + unsigned short int __init; /* Init flag. */ + unsigned long long int __a; /* Factor. */ +}; + +int srand48_r(long int seedval, struct drand48_data *buffer); +int seed48_r(unsigned short int seed16v[3], struct drand48_data *buffer); +int lcong48_r(unsigned short int param[7], struct drand48_data *buffer); + +int drand48_r(struct drand48_data *buffer, double *result); +int erand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, double *result); + +int lrand48_r(struct drand48_data *buffer, long int *result); +int nrand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, long int *result); + +int mrand48_r(struct drand48_data *buffer, long int *result); +int jrand48_r(unsigned short int xsubi[3], struct drand48_data *buffer, long int *result); + +#ifdef __cplusplus +} +#endif diff --git a/common/server-functions.c b/common/server-functions.c index 3d852ffd..0edf800f 100644 --- a/common/server-functions.c +++ b/common/server-functions.c @@ -35,7 +35,9 @@ #include #include #include +#ifdef __GLIBC__ #include +#endif #include #include #include @@ -168,6 +170,7 @@ const char *get_version_string (void) { } void print_backtrace (void) { +#ifdef __GLIBC__ void *buffer[64]; int nptrs = backtrace (buffer, 64); kwrite (2, "\n------- Stack Backtrace -------\n", 33); @@ -178,6 +181,9 @@ void print_backtrace (void) { kwrite (2, s, strlen (s)); kwrite (2, "\n", 1); } +#else + kwrite(2, "--- Backtrace Only On Glibc ---\n", 32); +#endif } pthread_t debug_main_pthread_id; diff --git a/jobs/jobs.h b/jobs/jobs.h index f249a0a4..70fbf83e 100644 --- a/jobs/jobs.h +++ b/jobs/jobs.h @@ -25,6 +25,11 @@ #include #include #include + +#ifndef __GLIBC__ +#include "common/drand48-compat.h" +#endif + #include "net/net-events.h" #include "net/net-msg.h" #include "net/net-timers.h"