Skip to content

libphoenix: make pthread attrs (more) POSIX-compliant#484

Open
adamgreloch wants to merge 12 commits into
masterfrom
adamgreloch/RTOS-1353
Open

libphoenix: make pthread attrs (more) POSIX-compliant#484
adamgreloch wants to merge 12 commits into
masterfrom
adamgreloch/RTOS-1353

Conversation

@adamgreloch

@adamgreloch adamgreloch commented Jun 15, 2026

Copy link
Copy Markdown
Member

TASK: RTOS-1353

Description

Motivation and Context

Types of changes

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to change)
  • Chore (refactoring, style fixes, git/CI config, submodule management, no code logic changes)

How Has This Been Tested?

  • Already covered by automatic testing.
  • New test added: damianloew/posix_tests
  • Tested by hand on: riscv64

Checklist:

  • My change requires a change to the documentation.
  • I have updated the documentation accordingly.
  • I have added tests to cover my changes.
  • All new and existing linter checks and tests passed.
  • My changes generate no new compilation warnings for any of the targets.

Special treatment

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request adds NULL pointer checks to pthread_attr_init and pthread_attr_destroy to prevent potential dereferences, and fixes a logical bug in pthread_attr_setdetachstate by changing the logical OR (||) to a logical AND (&&) when validating the detachstate parameter. No review comments were provided, so there is no additional feedback.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

@github-actions

github-actions Bot commented Jun 15, 2026

Copy link
Copy Markdown

Unit Test Results

10 860 tests  ±0   10 190 ✅ ±0   52m 23s ⏱️ -35s
   670 suites ±0      670 💤 ±0 
     1 files   ±0        0 ❌ ±0 

Results for commit e2a03e2. ± Comparison against base commit fb9670d.

♻️ This comment has been updated with latest results.

@adamgreloch adamgreloch marked this pull request as ready for review June 17, 2026 11:25
@adamgreloch

Copy link
Copy Markdown
Member Author

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the pthread_attr_t structure, introduces new fields such as guardsize and inheritsched, and implements several missing pthread_attr_* getter and setter functions. However, two critical issues were identified in pthread_create: first, the thread's detached state is incorrectly initialized using the default attributes instead of the user-provided attributes; second, adding the stack size and guard size can result in an integer overflow, potentially leading to an undersized stack allocation and memory corruption.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pthread/pthread.c
Comment thread pthread/pthread.c Outdated
@adamgreloch adamgreloch force-pushed the adamgreloch/RTOS-1353 branch 2 times, most recently from 35b09b7 to 4dea89e Compare June 17, 2026 12:11
@adamgreloch adamgreloch requested a review from ziemleszcz June 17, 2026 12:11
@adamgreloch adamgreloch changed the title libphoenix: make pthread attrs POSIX-compliant libphoenix: make pthread attrs (more) POSIX-compliant Jun 17, 2026
@adamgreloch adamgreloch force-pushed the adamgreloch/RTOS-1353 branch 2 times, most recently from b20dbf9 to 68a70c5 Compare June 17, 2026 12:24
Comment thread include/sys/types.h
Comment thread include/pthread.h Outdated
Comment thread pthread/pthread.c Outdated
Comment thread pthread/pthread.c Outdated
Comment thread pthread/pthread.c Outdated
Comment thread pthread/pthread.c
Comment thread pthread/pthread.c Outdated
Comment thread pthread/pthread.c
Comment thread pthread/pthread.c Outdated
@adamgreloch adamgreloch changed the title libphoenix: make pthread attrs (more) POSIX-compliant !libphoenix: make pthread attrs (more) POSIX-compliant Jun 17, 2026
@adamgreloch adamgreloch changed the title !libphoenix: make pthread attrs (more) POSIX-compliant libphoenix: make pthread attrs (more) POSIX-compliant Jun 17, 2026
@adamgreloch adamgreloch force-pushed the adamgreloch/RTOS-1353 branch from 68a70c5 to e2a03e2 Compare June 17, 2026 13:54
@adamgreloch adamgreloch requested a review from ziemleszcz June 17, 2026 13:54
@ziemleszcz

Copy link
Copy Markdown
Contributor

/gemini review

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the pthread attributes implementation, updating the pthread_attr_t structure to support guardsize and inheritsched, renaming fields for clarity, and introducing macro-generated getters. Feedback points out POSIX compliance issues: sched_get_priority_max and sched_get_priority_min should set errno and return -1 on failure rather than returning the error code directly, and pthread_create should ignore guardsize when a custom stackaddr is provided.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pthread/pthread.c
Comment on lines 842 to 848
int sched_get_priority_max(int policy)
{
if (policy == SCHED_RR)
return 7;
return PH_MAX_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_max should return -1 and set errno to EINVAL if the policy is invalid or unsupported, rather than returning EINVAL directly as a positive integer.

int sched_get_priority_max(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MAX_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Comment thread pthread/pthread.c
Comment on lines 851 to 857
int sched_get_priority_min(int policy)
{
if (policy == SCHED_RR)
return 0;
return PH_MIN_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_min should return -1 and set errno to EINVAL if the policy is invalid or unsupported, rather than returning EINVAL directly as a positive integer.

int sched_get_priority_min(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MIN_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Comment thread pthread/pthread.c
Comment on lines +222 to +228
if (attrs->stacksize > SIZE_MAX - attrs->guardsize || attrs->stacksize + attrs->guardsize > SIZE_MAX - PAGE_SIZE) {
return EINVAL;
}

size_t stacksize = ALIGN(attrs->stacksize + attrs->guardsize, PAGE_SIZE);
/* FIXME: don't mmap when attrs->stackaddr is not null and just use that address as a stack */
void *stack = mmap(attrs->stackaddr, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to POSIX, if the stackaddr attribute has been set (i.e., the caller is allocating and managing their own thread stacks), the guardsize attribute must be ignored and no guard area should be created. Currently, guardsize is added to stacksize regardless of whether stackaddr is NULL or not.

	size_t guardsize = (attrs->stackaddr != NULL) ? 0 : attrs->guardsize;
	if (attrs->stacksize > SIZE_MAX - guardsize || attrs->stacksize + guardsize > SIZE_MAX - PAGE_SIZE) {
		return EINVAL;
	}

	size_t stacksize = ALIGN(attrs->stacksize + guardsize, PAGE_SIZE);
	/* FIXME: don't mmap when attrs->stackaddr is not null and just use that address as a stack */
	void *stack = mmap(attrs->stackaddr, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the pthread attribute implementation, introducing support for guard size and inherit scheduling attributes, updating the pthread_attr_t structure, and cleaning up function declarations. The feedback highlights POSIX compliance issues: sched_get_priority_max and sched_get_priority_min should return -1 and set errno on failure instead of returning the error code directly, and pthread_attr_setschedparam should return EINVAL rather than ENOTSUP for invalid scheduling priorities.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pthread/pthread.c
Comment on lines 842 to 848
int sched_get_priority_max(int policy)
{
if (policy == SCHED_RR)
return 7;
return PH_MAX_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_max should return -1 and set errno to EINVAL on failure, rather than returning the error code directly.

int sched_get_priority_max(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MAX_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Comment thread pthread/pthread.c
Comment on lines 851 to 857
int sched_get_priority_min(int policy)
{
if (policy == SCHED_RR)
return 0;
return PH_MIN_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_min should return -1 and set errno to EINVAL on failure, rather than returning the error code directly.

int sched_get_priority_min(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MIN_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Comment thread pthread/pthread.c
Comment on lines +612 to +615
if (param->sched_priority > sched_get_priority_max(attr->schedpolicy) ||
param->sched_priority < sched_get_priority_min(attr->schedpolicy)) {
return ENOTSUP;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

According to POSIX, pthread_attr_setschedparam should return EINVAL (not ENOTSUP) if the scheduling priority specified in param is invalid for the scheduling policy of attr.

	if (param->sched_priority > sched_get_priority_max(attr->schedpolicy) ||
			param->sched_priority < sched_get_priority_min(attr->schedpolicy)) {
		return EINVAL;
	}

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request refactors the pthread implementation by updating the pthread_attr_t structure, introducing support for guard size and scheduling inheritance, and adding corresponding getter and setter functions. The feedback highlights a critical issue where the guard area is not properly protected with PROT_NONE via mprotect, rendering it ineffective against stack overflows. Additionally, the reviewer points out that sched_get_priority_max and sched_get_priority_min should return -1 and set errno to EINVAL on failure to comply with POSIX standards.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread pthread/pthread.c
Comment on lines +222 to 231
if (attrs->stacksize > SIZE_MAX - attrs->guardsize || attrs->stacksize + attrs->guardsize > SIZE_MAX - PAGE_SIZE) {
return EINVAL;
}

size_t stacksize = ALIGN(attrs->stacksize + attrs->guardsize, PAGE_SIZE);
/* FIXME: don't mmap when attrs->stackaddr is not null and just use that address as a stack */
void *stack = mmap(attrs->stackaddr, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

if ((stack == MAP_FAILED) || (stack == NULL)) {
return EAGAIN;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

The guard area is currently allocated as part of the stack with PROT_READ | PROT_WRITE permissions, which means it does not actually protect against stack overflow (it just acts as extra stack space). To comply with POSIX and provide actual stack overflow protection, the guard area should be protected with PROT_NONE using mprotect.

	if (attrs->guardsize > SIZE_MAX - PAGE_SIZE || attrs->stacksize > SIZE_MAX - attrs->guardsize) {
		return EINVAL;
	}

	size_t guardsize = ALIGN(attrs->guardsize, PAGE_SIZE);
	if (attrs->stacksize > SIZE_MAX - guardsize || attrs->stacksize + guardsize > SIZE_MAX - PAGE_SIZE) {
		return EINVAL;
	}

	size_t stacksize = ALIGN(attrs->stacksize + guardsize, PAGE_SIZE);
	/* FIXME: don't mmap when attrs->stackaddr is not null and just use that address as a stack */
	void *stack = mmap(attrs->stackaddr, stacksize, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);

	if ((stack == MAP_FAILED) || (stack == NULL)) {
		return EAGAIN;
	}

	if (attrs->guardsize > 0) {
		if (mprotect(stack, guardsize, PROT_NONE) != 0) {
			munmap(stack, stacksize);
			return EAGAIN;
		}
	}

Comment thread pthread/pthread.c
Comment on lines 842 to 848
int sched_get_priority_max(int policy)
{
if (policy == SCHED_RR)
return 7;
return PH_MAX_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_max should return -1 and set errno to EINVAL if the policy is invalid, rather than returning EINVAL directly.

int sched_get_priority_max(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MAX_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Comment thread pthread/pthread.c
Comment on lines 851 to 857
int sched_get_priority_min(int policy)
{
if (policy == SCHED_RR)
return 0;
return PH_MIN_PRIO;

return EINVAL;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

high

According to POSIX, sched_get_priority_min should return -1 and set errno to EINVAL if the policy is invalid, rather than returning EINVAL directly.

int sched_get_priority_min(int policy)
{
	if (policy == SCHED_RR) {
		return PH_MIN_PRIO;
	}

	errno = EINVAL;
	return -1;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants