Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion libm.gmk
Original file line number Diff line number Diff line change
Expand Up @@ -296,7 +296,10 @@ C_MATH := \
math/s_tgammal.o \
math/s_trunc.o \
math/s_truncf.o \
math/s_truncl.o
math/s_truncl.o \
math/s_roundeven.o \
math/s_roundevenf.o \
math/s_roundevenl.o

ifdef SPE
$(info Using SPE math objects)
Expand Down
4 changes: 4 additions & 0 deletions library/include/math.h
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,10 @@ extern float exp2f(float x);
extern double exp2(double x);
extern long double exp2l(long double x);

extern double roundeven (double x);
extern float roundevenf(float x);
extern long double roundevenl(long double x);

#if !defined(__cplusplus) && !defined(shared_comp)
#define log2(x) (log (x) / _M_LN2)
#else
Expand Down
49 changes: 49 additions & 0 deletions library/math/s_roundeven.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* $Id: math_s_roundevenf.c,v 1.0 2025-06-14 12:04:24 clib4devs Exp $
*/

#ifndef _MATH_HEADERS_H
#include "math_headers.h"
#endif /* _MATH_HEADERS_H */

#define BIAS 0x3ff
#define MANT_DIG 53
#define MAX_EXP (2 * BIAS + 1)

double
roundeven (double x) {
uint64_t ix, ux;
EXTRACT_WORD64 (ix, x);
ux = ix & 0x7fffffffffffffffULL;
int exponent = ux >> (MANT_DIG - 1);
if (exponent >= BIAS + MANT_DIG - 1) {
/* Integer, infinity or NaN. */
if (exponent == MAX_EXP)
/* Infinity or NaN; quiet signaling NaNs. */
return x + x;
else
return x;
}
else if (exponent >= BIAS) {
/* At least 1; not necessarily an integer. Locate the bits with
exponents 0 and -1 (when the unbiased exponent is 0, the bit
with exponent 0 is implicit, but as the bias is odd it is OK
to take it from the low bit of the exponent). */
int int_pos = (BIAS + MANT_DIG - 1) - exponent;
int half_pos = int_pos - 1;
uint64_t half_bit = 1ULL << half_pos;
uint64_t int_bit = 1ULL << int_pos;
if ((ix & (int_bit | (half_bit - 1))) != 0)
/* Carry into the exponent works correctly. No need to test whether HALF_BIT is set. */
ix += half_bit;
ix &= ~(int_bit - 1);
}
else if (exponent == BIAS - 1 && ux > 0x3fe0000000000000ULL)
/* Interval (0.5, 1). */
ix = (ix & 0x8000000000000000ULL) | 0x3ff0000000000000ULL;
else
/* Rounds to 0. */
ix &= 0x8000000000000000ULL;
INSERT_WORD64 (x, ix);
return x;
}
49 changes: 49 additions & 0 deletions library/math/s_roundevenf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* $Id: math_s_roundevenf.c,v 1.0 2025-06-14 12:04:24 clib4devs Exp $
*/

#ifndef _MATH_HEADERS_H
#include "math_headers.h"
#endif /* _MATH_HEADERS_H */

#define BIAS 0x7f
#define MANT_DIG 24
#define MAX_EXP (2 * BIAS + 1)

float
roundevenf (float x) {
uint32_t ix, ux;
GET_FLOAT_WORD (ix, x);
ux = ix & 0x7fffffff;
int exponent = ux >> (MANT_DIG - 1);
if (exponent >= BIAS + MANT_DIG - 1) {
/* Integer, infinity or NaN. */
if (exponent == MAX_EXP)
/* Infinity or NaN; quiet signaling NaNs. */
return x + x;
else
return x;
}
else if (exponent >= BIAS) {
/* At least 1; not necessarily an integer. Locate the bits with
exponents 0 and -1 (when the unbiased exponent is 0, the bit
with exponent 0 is implicit, but as the bias is odd it is OK
to take it from the low bit of the exponent). */
int int_pos = (BIAS + MANT_DIG - 1) - exponent;
int half_pos = int_pos - 1;
uint32_t half_bit = 1U << half_pos;
uint32_t int_bit = 1U << int_pos;
if ((ix & (int_bit | (half_bit - 1))) != 0)
/* Carry into the exponent works correctly. No need to test whether HALF_BIT is set. */
ix += half_bit;
ix &= ~(int_bit - 1);
}
else if (exponent == BIAS - 1 && ux > 0x3f000000)
/* Interval (0.5, 1). */
ix = (ix & 0x80000000) | 0x3f800000;
else
/* Rounds to 0. */
ix &= 0x80000000;
SET_FLOAT_WORD (x, ix);
return x;
}
91 changes: 91 additions & 0 deletions library/math/s_roundevenl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
/*
* $Id: math_s_roundevenl.c,v 1.0 2025-06-14 12:04:24 clib4devs Exp $
*/

#ifndef _MATH_HEADERS_H
#include "math_headers.h"
#endif /* _MATH_HEADERS_H */

#define BIAS 0x3fff
#define MANT_DIG 64
#define MAX_EXP (2 * BIAS + 1)

long double
roundevenl(long double x) {
uint16_t se;
uint32_t hx, lx;
GET_LDOUBLE_WORDS (se, hx, lx, x);
int exponent = se & 0x7fff;
if (exponent >= BIAS + MANT_DIG - 1) {
/* Integer, infinity or NaN. */
if (exponent == MAX_EXP)
/* Infinity or NaN; quiet signaling NaNs. */
return x + x;
else
return x;
}
else if (exponent >= BIAS + MANT_DIG - 32) {
/* Not necessarily an integer; integer bit is in low word. Locate the bits with exponents 0 and -1. */
int int_pos = (BIAS + MANT_DIG - 1) - exponent;
int half_pos = int_pos - 1;
uint32_t half_bit = 1U << half_pos;
uint32_t int_bit = 1U << int_pos;
if ((lx & (int_bit | (half_bit - 1))) != 0) {
/* No need to test whether HALF_BIT is set. */
lx += half_bit;
if (lx < half_bit) {
hx++;
if (hx == 0) {
hx = 0x80000000;
se++;
}
}
}
lx &= ~(int_bit - 1);
}
else if (exponent == BIAS + MANT_DIG - 33) {
/* Not necessarily an integer; integer bit is bottom of high word, half bit is top of low word. */
if (((hx & 1) | (lx & 0x7fffffff)) != 0) {
lx += 0x80000000;
if (lx < 0x80000000) {
hx++;
if (hx == 0) {
hx = 0x80000000;
se++;
}
}
}
lx = 0;
}
else if (exponent >= BIAS) {
/* At least 1; not necessarily an integer, integer bit and half
bit are in the high word. Locate the bits with exponents 0 and -1. */
int int_pos = (BIAS + MANT_DIG - 33) - exponent;
int half_pos = int_pos - 1;
uint32_t half_bit = 1U << half_pos;
uint32_t int_bit = 1U << int_pos;
if (((hx & (int_bit | (half_bit - 1))) | lx) != 0) {
hx += half_bit;
if (hx < half_bit) {
hx = 0x80000000;
se++;
}
}
hx &= ~(int_bit - 1);
lx = 0;
}
else if (exponent == BIAS - 1 && (hx > 0x80000000 || lx != 0)) {
/* Interval (0.5, 1). */
se = (se & 0x8000) | 0x3fff;
hx = 0x80000000;
lx = 0;
}
else {
/* Rounds to 0. */
se &= 0x8000;
hx = 0;
lx = 0;
}
SET_LDOUBLE_WORDS (x, se, hx, lx);
return x;
}
2 changes: 1 addition & 1 deletion library/posix/memalign.c
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ memalign(size_t alignment, size_t size) {
goto out;
}

void* original_ptr = malloc(size + header_size + padding);
void* original_ptr = __malloc_r(__clib4, size + header_size + padding);
if (!original_ptr) {
__set_errno_r(__clib4, ENOMEM);
goto out;
Expand Down
4 changes: 1 addition & 3 deletions library/pthread/pthread_cleanup_pop.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,12 +39,10 @@

void
pthread_cleanup_pop(int execute) {
pthread_t thread;
ThreadInfo *inf;
CleanupHandler *handler;

thread = pthread_self();
inf = GetThreadInfo(thread);
inf = GetCurrentThreadInfo();
if (inf != NULL) {
handler = (CleanupHandler *) RemTail((struct List *) &inf->cleanup);

Expand Down
3 changes: 1 addition & 2 deletions library/pthread/pthread_cleanup_push.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,7 @@ pthread_cleanup_push(void (*routine)(void *), void *arg) {
if (handler == NULL)
return;

thread = pthread_self();
inf = GetThreadInfo(thread);
inf = GetCurrentThreadInfo();

handler->routine = routine;
handler->arg = arg;
Expand Down
4 changes: 1 addition & 3 deletions library/pthread/pthread_setcancelstate.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@

int
pthread_setcancelstate(int state, int *oldstate) {
pthread_t thread;
ThreadInfo *inf;

if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
return EINVAL;

thread = pthread_self();
inf = GetThreadInfo(thread);
inf = GetCurrentThreadInfo();

if (oldstate)
*oldstate = inf->cancelstate;
Expand Down
4 changes: 1 addition & 3 deletions library/pthread/pthread_setcanceltype.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,12 @@

int
pthread_setcanceltype(int type, int *oldtype) {
pthread_t thread;
ThreadInfo *inf;

if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
return EINVAL;

thread = pthread_self();
inf = GetThreadInfo(thread);
inf = GetCurrentThreadInfo();

if (oldtype)
*oldtype = inf->canceltype;
Expand Down
4 changes: 1 addition & 3 deletions library/pthread/pthread_testcancel.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,11 +39,9 @@

void
pthread_testcancel(void) {
pthread_t thread;
ThreadInfo *inf;

thread = pthread_self();
inf = GetThreadInfo(thread);
inf = GetCurrentThreadInfo();

if (inf->canceled && (inf->cancelstate == PTHREAD_CANCEL_ENABLE))
pthread_exit(PTHREAD_CANCELED);
Expand Down
4 changes: 4 additions & 0 deletions library/shared_library/clib4.c
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,9 @@ struct Clib4Library *libOpen(struct LibraryManagerInterface *Self, uint32 versio
if (IDOS->NameFromLock(me->pr_CurrentDir, (STRPTR) current_dir_name, sizeof(current_dir_name))) {
__set_current_path((const char *) current_dir_name);
}

ITimer->GetSysTime((struct TimeVal *) &__clib4->clock);

/* At this point exe is fully initialized */
__clib4->__fully_initialized = TRUE;
SHOWMSG("Library initialized");
Expand Down Expand Up @@ -768,6 +771,7 @@ struct Clib4Library *libInit(struct Clib4Library *libBase, BPTR seglist, struct
res->fallbackClib->self = (struct Process *) IExec->FindTask(NULL);
res->fallbackClib->__check_abort_enabled = TRUE;
res->fallbackClib->__fully_initialized = TRUE;
ITimer->GetSysTime((struct TimeVal *) &res->fallbackClib->clock);

/* Init SYSV structures */
IPCMapInit(&res->shmcx.keymap);
Expand Down
20 changes: 12 additions & 8 deletions library/shared_library/clib4_vectors.h
Original file line number Diff line number Diff line change
Expand Up @@ -1174,21 +1174,25 @@ static void *clib4Vectors[] = {

(void *) (0), /* 4392 - unused */

(void *) (sigsuspend), /* 4396 */
(void *) (sigsuspend), /* 4396 */
(void *) (spawnve), /* 4400 */
(void *) (sigpause), /* 4404 */
(void *) (sigwait), /* 4408 */
(void *) (sigwaitinfo), /* 4412 */
(void *) (sigtimedwait), /* 4416 */
(void *) (sigpause), /* 4404 */
(void *) (sigwait), /* 4408 */
(void *) (sigwaitinfo), /* 4412 */
(void *) (sigtimedwait), /* 4416 */

(void *) (getvfsstat), /* 4420 */
(void *) (backtrace), /* 4424 */
(void *) (backtrace_symbols), /* 4428 */
(void *) (backtrace_symbols_fd), /* 4432 */
(void *) (dladdr), /* 4436 */
(void *) (dladdr), /* 4436 */

(void *) (getpriority), /* 4440 */
(void *) (setpriority), /* 4444 */
(void *) (getpriority), /* 4440 */
(void *) (setpriority), /* 4444 */

(void *) (roundeven), /* 4448 */
(void *) (roundevenf), /* 4452 */
(void *) (roundevenl), /* 4456 */

(void *)-1
};
3 changes: 3 additions & 0 deletions library/shared_library/interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -1362,6 +1362,9 @@ struct Clib4IFace {
int (* getpriority) (int which, unsigned int who); /* 4440 */
int (* setpriority) (int which, unsigned int who, int priority); /* 4444 */

double (* roundeven) (double x); /* 4448 */
float (* roundevenf) (float x); /* 4452 */
long double (* roundevenl) (long double x); /* 4456 */
};

#ifdef __PIC__
Expand Down
2 changes: 2 additions & 0 deletions library/shared_library/stubs_roundeven.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "stubs_common.h"
Clib4Call(roundeven, 4448);
2 changes: 2 additions & 0 deletions library/shared_library/stubs_roundevenf.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "stubs_common.h"
Clib4Call(roundevenf, 4452);
2 changes: 2 additions & 0 deletions library/shared_library/stubs_roundevenl.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
#include "stubs_common.h"
Clib4Call(roundevenl, 4456);
3 changes: 3 additions & 0 deletions library/stdlib/free.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@

void
__free_r(struct _clib4 *__clib4, void *ptr) {
if (ptr == NULL)
return;

__memory_lock(__clib4);

AlignedHeader* header = (AlignedHeader*) ((uintptr_t)ptr - sizeof(AlignedHeader));
Expand Down
7 changes: 7 additions & 0 deletions library/stdlib/malloc.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,12 @@ __malloc_r(struct _clib4 *__clib4, size_t size) {
ENTER();
void *result = NULL;

// Prevent overflow
if (size > SIZE_MAX) {
__set_errno_r(__clib4, EOVERFLOW);
goto out;
}

__memory_lock(__clib4);

result = wmem_alloc(__clib4->__wmem_allocator, size);
Expand All @@ -33,6 +39,7 @@ __malloc_r(struct _clib4 *__clib4, size_t size) {

__memory_unlock(__clib4);

out:
LEAVE();
return (result);
}
Expand Down