Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
8196968
Don't open timer.device any tyme a pthread timed function is called
afxgroup Apr 3, 2026
fa87547
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 3, 2026
1dbd4ac
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 3, 2026
98f16aa
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 3, 2026
f0c3810
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 14, 2026
0a184cf
Fixed uuid created as local memory variable
afxgroup Apr 24, 2026
4d56f46
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 24, 2026
1d1d69e
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 26, 2026
e411f1a
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 27, 2026
3cf177f
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 27, 2026
81144fc
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 28, 2026
4dbe2bf
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup Apr 28, 2026
5b837a3
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup May 13, 2026
10b9d40
Merge branch 'development' of github.com:AmigaLabs/clib4 into develop…
afxgroup May 14, 2026
688983e
Refactor debug output formatting
afxgroup May 27, 2026
cfcc514
Fixing error with NULL comparisons and unnamed temporary values
walkero-gr Jun 6, 2026
5bd78fb
Latest changes to I/O wasn't committed before 2.1 release
afxgroup Jun 7, 2026
c0dd181
Updated with latest development changes
afxgroup Jun 7, 2026
d6fb3a0
Update version and revision numbers in c.lib_rev.h
afxgroup Jun 7, 2026
c11811f
Fixing when nightly version string is applied
walkero-gr Jun 7, 2026
a19fc90
Merge pull request #422 from AmigaLabs/fixing-nightly-version-string
walkero-gr Jun 7, 2026
2b1abfd
Fix array bound errors when compiled with gcc13
walkero-gr Jun 8, 2026
292f38c
Merge pull request #423 from AmigaLabs/fix-array-bounds
walkero-gr Jun 10, 2026
bc9105b
Make wmem allocator process-global singleton (#424)
afxgroup Jun 10, 2026
128547a
Merge pull request #418 from AmigaLabs/fixing-comparisons-and-unnamed…
walkero-gr Jun 10, 2026
593b1ad
fix(pipe): POSIX-correct blocking/non-blocking read behavior (#425)
afxgroup Jun 11, 2026
03e7883
pthread: pthread_getattr_np reports the real thread stack (#430)
derfsss Jun 13, 2026
8485e95
Using my fork of the upgraded discord notification action
walkero-gr Jun 13, 2026
b42696a
Merge pull request #432 from AmigaLabs/update-discord-notifications
walkero-gr Jun 13, 2026
b90269d
Update github checkout action
walkero-gr Jun 13, 2026
f0139ba
Merge pull request #433 from AmigaLabs/update-actions-checkout
walkero-gr Jun 13, 2026
6e5bb9d
Updated action-gh-release to latest version
walkero-gr Jun 13, 2026
c3a9268
Changed the version to major
walkero-gr Jun 13, 2026
8b2dba3
Merge pull request #434 from AmigaLabs/update-action-gh-release
walkero-gr Jun 13, 2026
b3ddf67
Update github action update-tag
walkero-gr Jun 13, 2026
383d62c
Merge pull request #435 from AmigaLabs/update-github-action-update-tag
walkero-gr Jun 13, 2026
6c7cc52
Fix/pthread create race condition (#436)
afxgroup Jun 19, 2026
729ab37
fix: O_ACCMODE flag handling in fdopen/fopen/fread/fwrite/fcntl (#437)
afxgroup Jun 19, 2026
4c1322c
fix(altivec): vec_strcpy reads past source page boundary on G4 (#438)
derfsss Jun 20, 2026
db79871
optimize: Cache Clib4Resource pointer to eliminate repeated OpenResou…
afxgroup Jun 28, 2026
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
2 changes: 1 addition & 1 deletion .github/workflows/_compile.yml
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Pull code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Add repository to git safe directories
run: |
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/makeRelease.yml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Notify on Discord on successful release
uses: hunghg255/action-notifications@master
uses: walkero-gr/action-notifications@master
with:
discord_webhook: https://discord.com/api/webhooks/${{ secrets.DISCORD_ANNOUNCEMENTS_ID }}/${{ secrets.DISCORD_ANNOUNCEMENTS_TOKEN }}
title: "clib4 ${{ github.event.release.tag_name }} released"
Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/mergeMainBranches.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Pull code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Compile clib4
uses: ./.github/actions/compile
Expand All @@ -38,7 +38,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Pull code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Compile clib4
uses: ./.github/actions/compile
Expand All @@ -54,7 +54,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: PR notification
uses: hunghg255/action-notifications@master
uses: walkero-gr/action-notifications@master
with:
discord_webhook: https://discord.com/api/webhooks/${{ secrets.DISCORD_ANNOUNCEMENTS_ID }}/${{ secrets.DISCORD_ANNOUNCEMENTS_TOKEN }}
title: "Deploy to ${{ github.event.pull_request.base.ref }}"
Expand Down
14 changes: 7 additions & 7 deletions .github/workflows/nightly.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,21 @@ jobs:
version: "nightly"
steps:
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v6
with: { fetch-depth: 0 }
- name: Set Tag
id: tag
run: |
echo "version=nightly" >> "$GITHUB_OUTPUT"
- name: Update Tag
uses: richardsimko/update-tag@v1
uses: richardsimko/update-tag@v2
with:
tag_name: "nightly"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Create Release
id: create_release
uses: softprops/action-gh-release@v2.2.2
uses: softprops/action-gh-release@v3
with:
tag_name: "nightly"
name: "clib4 nightly-builds"
Expand All @@ -54,7 +54,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v6
with: { fetch-depth: 0 }

- name: Compile clib4
Expand All @@ -70,7 +70,7 @@ jobs:
mv clib4.lha clib4-nightly.lha

- name: Upload Files
uses: softprops/action-gh-release@v2.2.2
uses: softprops/action-gh-release@v3
with:
tag_name: "nightly"
draft: false
Expand All @@ -89,7 +89,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Checkout Code
uses: actions/checkout@v4
uses: actions/checkout@v6
with: { fetch-depth: 0 }

- name: Compile clib4
Expand All @@ -105,7 +105,7 @@ jobs:
mv clib4.lha clib4-nightly_SPE.lha

- name: Upload Files
uses: softprops/action-gh-release@v2.2.2
uses: softprops/action-gh-release@v3
with:
tag_name: "nightly"
draft: false
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/prChecks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Pull code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Compile clib4
uses: ./.github/actions/compile
Expand All @@ -37,7 +37,7 @@ jobs:
- '${{ github.workspace }}:/opt/code'
steps:
- name: Pull code
uses: actions/checkout@v4
uses: actions/checkout@v6

- name: Compile clib4
uses: ./.github/actions/compile
Expand Down
4 changes: 2 additions & 2 deletions GNUmakefile.os4
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ WARNINGS := \
-Wundef -Wmissing-declarations -Wunused -Wwrite-strings -Wno-unused-value -Wno-comment -Wno-missing-braces \
-Wno-deprecated-declarations -Wno-unused-variable -Wno-parentheses -Wno-missing-prototypes \
-Wstrict-aliasing -Wno-shadow -Wno-discarded-qualifiers -Wno-unused-function -Wno-unused-parameter -Wno-strict-aliasing \
-Wno-type-limits -Wno-cast-function-type -Wno-frame-address -Wno-error=unused-but-set-variable -Werror
-Wno-type-limits -Wno-cast-function-type -Wno-frame-address -Wno-error=unused-but-set-variable -Werror
# -Wbad-function-cast -Wconversion -Wformat

ifndef SPE
Expand Down Expand Up @@ -275,7 +275,7 @@ ifdef GITTAG
$(VERBOSE)sed -i 's/Version: [0-9]*\.[0-9]*/Version: $(MAJOR).$(MINOR)/g' misc/control
endif

ifdef NIGHTLY
ifneq ($(filter YES yes,$(NIGHTLY)),)
$(VERBOSE)sed -i 's/clib4.library \([0-9]*\.[0-9]*\)-\([a-z0-9]*\)/clib4.library \1-nightly-$(GIT_HASH)/g' library/c.lib_rev.h
endif

Expand Down
6 changes: 3 additions & 3 deletions library/c.lib_rev.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#define VERSION 2
#define REVISION 1

#define DATE "07.06.2026"
#define DATE "19.06.2026"
#define VERS "clib4.library 2.1"
#define VSTRING "clib4.library 2.1 (07.06.2026)\r\n"
#define VERSTAG "\0$VER: clib4.library 2.1-nightly-c971606 (07.06.2026)"
#define VSTRING "clib4.library 2.1 (19.06.2026)\r\n"
#define VERSTAG "\0$VER: clib4.library 2.1-nightly-c971606 (19.06.2026)"
12 changes: 10 additions & 2 deletions library/cpu/altivec/vec_strcpy.sx
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ vec_strcpy:
mr DMS,SMD // IU1 |dst - src| = src - dst
Pos_value:
subf. QBC,DST,ADD // IU1 Bytes to even QW start of vect (min 32)
addi ADD,DD,PAGE_SIZE // IU1 dst addr in next 4K page
addi ADD,SRC,PAGE_SIZE // IU1 SRC addr in next 4K page (loads fault on
// the SOURCE, so guard the source's page,
// not the dest's -- else an unmapped page
// just past src faults while dst is mid-page)
cmpi cr7,0,DMS,MIN_VEC // IU1 Check for min byte count separation

mtctr QBC // IU2 Init counter
Expand All @@ -171,7 +174,12 @@ v_strcpy:
#ifdef VRSAVE
mfspr RSV,VRSV // IU2 Get current VRSAVE contents
#endif
subf. PBC,DD,ADD // IU1 Now bytes to next 4K page
rlwinm Rt,DS,0,0,27 // IU1 Align src down to QW first: lvx loads are
// 16-aligned (use DS&~15), so an unaligned
// (rg-DS)/16 rounds to 0 and New_page_0 then
// loads a whole page past the src page end
subf. PBC,Rt,ADD // IU1 QW-exact bytes from aligned src to its 4K
// page boundary (loads fault on SRC, not dest)

#ifdef VRSAVE
oris Rt,RSV,0xff00 // IU1 Or in registers used by this routine
Expand Down
13 changes: 10 additions & 3 deletions library/dos.h
Original file line number Diff line number Diff line change
Expand Up @@ -309,8 +309,7 @@ struct _clib4 {

APTR stdio_lock;

/* Wof Allocator main pointer */
wmem_allocator_t *__wmem_allocator;
void *unused1;
APTR __environment_pool;

/* Names of files and directories to delete when shutting down. */
Expand All @@ -319,7 +318,7 @@ struct _clib4 {

/* Local timer I/O. */
struct MsgPort *__timer_port;
BOOL unused1;
BOOL unused3;
void *unused2;
struct TimeRequest *__timer_request;
struct Library *__TimerBase;
Expand Down Expand Up @@ -604,6 +603,14 @@ struct _clib4 {
*/
struct iob *__sf[3]; /* per-process stdin/stdout/stderr iob pointers */
struct _glue *__sglue; /* per-process root glue node for FILE slots */

/*
* Cached pointer to the global Clib4Resource.
* Initialized once in stdlib_memory_init to avoid repeated OpenResource() calls
* in malloc/free hot path. The resource itself is shared across all processes,
* but each process caches its own pointer for fast access.
*/
struct Clib4Resource *__clib4_resource;
};

#ifndef __getClib4
Expand Down
10 changes: 10 additions & 0 deletions library/fcntl/fcntl.c
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,16 @@ fcntl(int file_descriptor, int cmd, ... /* int arg */) {

result = OK;

/* Access mode: mutually exclusive O_RDONLY/O_WRONLY/O_RDWR */
if (FLAG_IS_SET(fd->fd_Flags, FDF_READ) && FLAG_IS_SET(fd->fd_Flags, FDF_WRITE))
SET_FLAG(result, O_RDWR);
else if (FLAG_IS_SET(fd->fd_Flags, FDF_WRITE))
SET_FLAG(result, O_WRONLY);
/* else: O_RDONLY == 0, already the default */

if (FLAG_IS_SET(fd->fd_Flags, FDF_APPEND))
SET_FLAG(result, O_APPEND);

if (FLAG_IS_SET(fd->fd_Flags, FDF_NON_BLOCKING))
SET_FLAG(result, O_NONBLOCK);

Expand Down
2 changes: 2 additions & 0 deletions library/profile/_mcount.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

#include "gmon.h"

volatile uintptr_t exec_addr = 4;

void __mcount(uint32 frompc, uint32 selfpc);

void
Expand Down
3 changes: 2 additions & 1 deletion library/profile/gmon.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
#include "../shared_library/math.h"

#undef DebugPrintF
#define dprintf(format, args...) ((struct ExecIFace *)((*(struct ExecBase **)4)->MainInterface))->DebugPrintF("[%s] " format, __PRETTY_FUNCTION__, ##args)
extern volatile uintptr_t exec_addr;
#define dprintf(format, args...) ((struct ExecIFace *)((*(struct ExecBase **)(exec_addr))->MainInterface))->DebugPrintF("[%s] " format, __PRETTY_FUNCTION__, ##args)

void moncontrol(int);
void monstartup(uint32, uint32);
Expand Down
36 changes: 31 additions & 5 deletions library/pthread/pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,16 @@ _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const stru
task = FindTask(NULL);
inf = GetCurrentThreadInfo();

/* Include the thread's dedicated cancel signal in the wait mask.
* pthread_cancel() signals that mask to wake the target, but without
* it here a thread parked in a condition wait (or in sem_wait, which
* is built on top of this function) never wakes and the cancellation
* is never acted upon. The SIGBREAKF_CTRL_C checks below only cover
* the fallback case where the dedicated signal could not be
* allocated at thread creation time. */
if (inf != NULL && inf->cancel_signal_mask != 0)
sigs |= inf->cancel_signal_mask;

if (abstime) {
// Compute relative time BEFORE sending the timer request.
// This way, if the deadline has already passed we can return
Expand Down Expand Up @@ -363,16 +373,18 @@ _pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex, const stru
// did we timeout?
if (sigs & (1 << inf->timerPort.mp_SigBit))
return ETIMEDOUT;
else if (sigs & SIGBREAKF_CTRL_C) {
else if (sigs & (SIGBREAKF_CTRL_C | (inf != NULL ? inf->cancel_signal_mask : 0))) {
pthread_testcancel();
// Re-Enable CTRL-C in case a signal handler is installed
Signal(task, SIGBREAKF_CTRL_C);
if (sigs & SIGBREAKF_CTRL_C)
Signal(task, SIGBREAKF_CTRL_C);
}
} else {
if (sigs & SIGBREAKF_CTRL_C) {
if (sigs & (SIGBREAKF_CTRL_C | (inf != NULL ? inf->cancel_signal_mask : 0))) {
pthread_testcancel();
// Re-Enable CTRL-C in case a signal handler is installed
Signal(task, SIGBREAKF_CTRL_C);
if (sigs & SIGBREAKF_CTRL_C)
Signal(task, SIGBREAKF_CTRL_C);
}
}

Expand Down Expand Up @@ -476,6 +488,20 @@ void __pthread_exit_func(void) {
struct DOSIFace *IDOS = _IDOS;
SHOWMSG("[__pthread_exit_func :] Pthread __pthread_exit_func called.\n");

/* A thread that never exits by itself (a daemon-style worker parked
* in pthread_cond_wait / sem_wait) would wedge the join/wait loop
* below forever, making the process unkillable. On POSIX systems
* exit() simply terminates the remaining threads. Approximate that:
* request cancellation of every live thread first, so parked threads
* wake, run their cancellation cleanup handlers and leave through
* the normal pthread exit path -- which keeps dos.library's
* parent/child process accounting intact (no force-removal). */
for (i = PTHREAD_FIRST_THREAD_ID; i < PTHREAD_THREADS_MAX; i++) {
inf = &threads[i];
if (inf->status != THREAD_STATE_IDLE && inf->task != NULL)
pthread_cancel(i);
}

// if we don't do this we can easily end up with unloaded code being executed
for (i = PTHREAD_FIRST_THREAD_ID; i < PTHREAD_THREADS_MAX; i++) {
inf = &threads[i];
Expand Down Expand Up @@ -576,4 +602,4 @@ PTHREAD_DESTRUCTOR(__pthread_exit) {
}

LEAVE();
}
}
22 changes: 18 additions & 4 deletions library/pthread/pthread_create.c
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,6 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
_pthread_clear_threadinfo(inf);
inf->status = THREAD_STATE_RUNNING; // Prevents another GetThreadId(NULL) from returning this slot
inf->thread_id = threadnew; /* Save our pthread_t ID */
MutexRelease(thread_sem);

D(("pthread_create: slot %d reserved (task %p)\n", threadnew, inf->task));
inf->start = start;
Expand All @@ -371,7 +370,9 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
msgPort = AllocSysObject(ASOT_PORT, NULL);
if (msgPort == 0) {
SHOWMSG("Cannot allocate message port\n");
goto out;
_pthread_clear_threadinfo(inf); // Release the reserved slot back to IDLE
MutexRelease(thread_sem);
return EAGAIN;
}

newThreadMessage = AllocSysObjectTags(ASOT_MESSAGE,
Expand All @@ -380,8 +381,14 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
TAG_DONE);
if (newThreadMessage == NULL) {
SHOWMSG("Cannot allocate message\n");
goto out;
}

FreeSysObject(ASOT_PORT, msgPort);
msgPort = NULL;

_pthread_clear_threadinfo(inf); // Release the reserved slot back to IDLE
MutexRelease(thread_sem);
return EAGAIN;
}


/* Check minimum stack size */
Expand Down Expand Up @@ -434,6 +441,10 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
FreeSignal(inf->cancel_signal);
inf->cancel_signal = -1;
}
if (inf->join_signal != -1) {
FreeSignal(inf->join_signal);
inf->join_signal = -1;
}
if (newThreadMessage != NULL) {
FreeSysObject(ASOT_MESSAGE, newThreadMessage);
newThreadMessage = NULL;
Expand All @@ -443,6 +454,7 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
msgPort = NULL;
}
_pthread_clear_threadinfo(inf); // Release the reserved slot back to IDLE
MutexRelease(thread_sem);
return EAGAIN;
}

Expand All @@ -456,5 +468,7 @@ pthread_create(pthread_t *thread, const pthread_attr_t *attr, void *(*start)(voi
newThreadMessage = NULL;
msgPort = NULL;

MutexRelease(thread_sem);

return OK;
}
13 changes: 13 additions & 0 deletions library/pthread/pthread_getattr_np.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,5 +51,18 @@ pthread_getattr_np(pthread_t thread, pthread_attr_t *attr) {

*attr = inf->attr;

/* Report the thread's ACTUAL stack, matching the Linux/glibc
* semantics of pthread_getattr_np: callers chain this into
* pthread_attr_getstack() to derive the live stack bounds (stack
* overflow detection, GC stack scanning, ...). The creation-time
* attr normally has stackaddr == NULL (and stacksize == 0 when the
* default was used), which sends such callers computing bounds far
* off the real stack. The exec Task always knows the truth. */
if (inf->task != NULL) {
struct Task *t = (struct Task *) inf->task;
attr->stackaddr = t->tc_SPLower;
attr->stacksize = (size_t) ((char *) t->tc_SPUpper - (char *) t->tc_SPLower);
}

return 0;
}
Loading