Commit a7d2c5cb authored by Christopher Friedt's avatar Christopher Friedt Committed by Fabio Baltieri
Browse files

posix: implement pthread_getguardsize() pthread_setguardsize()

Implement pthread_getguardsize() and pthread_setguardsize().

pthread_getguardsize() and pthread_setguardsize() are required
by the POSIX_THREADS_EXT Option Group as detailed in Section
E.1 of IEEE-1003.1-2017. However, they were formerly part of
XSI_THREADS_EXT.

The XSI_THREADS_EXT Option Group was required for PSE51, PSE52,
PSE53, and PSE54 conformance.

Signed-off-by: default avatarChristopher Friedt <cfriedt@meta.com>
parent eb7e4bed
Loading
Loading
Loading
Loading
+2 −0
Changes for include/zephyr/posix/posix_types.h: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -39,8 +39,10 @@ typedef unsigned long timer_t;
struct pthread_attr {
	void *stack;
	uint16_t stacksize;
	uint16_t guardsize;
	int8_t priority;
	uint8_t schedpolicy: 2;
	uint8_t guardsize_msbit: 1;
	bool initialized: 1;
	bool cancelstate: 1;
	bool detachstate: 1;
+2 −0
Changes for include/zephyr/posix/pthread.h: 2 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -428,7 +428,9 @@ static inline int pthread_rwlockattr_init(pthread_rwlockattr_t *attr)
	return 0;
}

int pthread_attr_getguardsize(const pthread_attr_t *ZRESTRICT attr, size_t *ZRESTRICT guardsize);
int pthread_attr_getstacksize(const pthread_attr_t *attr, size_t *stacksize);
int pthread_attr_setguardsize(pthread_attr_t *attr, size_t guardsize);
int pthread_attr_setstacksize(pthread_attr_t *attr, size_t stacksize);
int pthread_attr_setschedpolicy(pthread_attr_t *attr, int policy);
int pthread_attr_getschedpolicy(const pthread_attr_t *attr, int *policy);
+13 −0
Changes for lib/posix/Kconfig.pthread: 13 added lines, 0 removed lines.
Original line number Diff line number Diff line
@@ -27,4 +27,17 @@ config PTHREAD_RECYCLER_DELAY_MS
	  Note: this option should be considered temporary and will likely be
	  removed once a more synchronous solution is available.

config POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT
	int "Default size of stack guard area"
	range 0 65536
	default 0
	help
	  This is the default amount of space to reserve at the overflow end of a
	  pthread stack. Since Zephyr already supports both software-based stack
	  protection (canaries) and hardware-based stack protection (MMU or MPU),
	  this is set to 0 by default. However, a conforming application would be
	  required to set this to PAGESIZE. Eventually, this option might
	  facilitate a more dynamic approach to guard areas (via software or
	  hardware) but for now it simply increases the size of thread stacks.

endif
+42 −2
Changes for lib/posix/pthread.c: 42 added lines, 2 removed lines.
Original line number Diff line number Diff line
@@ -50,6 +50,17 @@ static inline void __set_attr_stacksize(struct pthread_attr *attr, size_t size)
	attr->stacksize = size - 1;
}

static inline size_t __get_attr_guardsize(const struct pthread_attr *attr)
{
	return (attr->guardsize_msbit * BIT(16)) | attr->guardsize;
}

static inline void __set_attr_guardsize(struct pthread_attr *attr, size_t size)
{
	attr->guardsize_msbit = size == PTHREAD_STACK_MAX;
	attr->guardsize = size & BIT_MASK(16);
}

struct __pthread_cleanup {
	void (*routine)(void *arg);
	void *arg;
@@ -85,8 +96,10 @@ static int pthread_concurrency;
static const struct pthread_attr init_pthread_attrs = {
	.stack = NULL,
	.stacksize = 0,
	.guardsize = (BIT_MASK(16) & CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT),
	.priority = DEFAULT_PTHREAD_PRIORITY,
	.schedpolicy = DEFAULT_PTHREAD_POLICY,
	.guardsize_msbit = (BIT(16) & CONFIG_POSIX_PTHREAD_ATTR_GUARDSIZE_DEFAULT),
	.initialized = true,
	.cancelstate = PTHREAD_CANCEL_ENABLE,
	.detachstate = PTHREAD_CREATE_JOINABLE,
@@ -253,7 +266,7 @@ int pthread_attr_setschedparam(pthread_attr_t *_attr, const struct sched_param *
	int priority = schedparam->sched_priority;

	if (attr == NULL || !attr->initialized ||
	    is_posix_policy_prio_valid(priority, attr->schedpolicy == false)) {
	    !is_posix_policy_prio_valid(priority, attr->schedpolicy)) {
		LOG_ERR("Invalid pthread_attr_t or sched_param");
		return EINVAL;
	}
@@ -436,7 +449,8 @@ int pthread_create(pthread_t *th, const pthread_attr_t *_attr, void *(*threadrou
		attr = &attr_storage;
		BUILD_ASSERT(DYNAMIC_STACK_SIZE <= PTHREAD_STACK_MAX);
		__set_attr_stacksize(attr, DYNAMIC_STACK_SIZE);
		attr->stack = k_thread_stack_alloc(__get_attr_stacksize(attr),
		attr->stack = k_thread_stack_alloc(__get_attr_stacksize(attr) +
							   __get_attr_guardsize(attr),
						   k_is_user_context() ? K_USER : 0);
		if (attr->stack == NULL) {
			LOG_ERR("Unable to allocate stack of size %u", DYNAMIC_STACK_SIZE);
@@ -988,6 +1002,32 @@ int pthread_attr_getstack(const pthread_attr_t *_attr, void **stackaddr, size_t
	return 0;
}

int pthread_attr_getguardsize(const pthread_attr_t *ZRESTRICT _attr, size_t *ZRESTRICT guardsize)
{
	struct pthread_attr *const attr = (struct pthread_attr *)_attr;

	if (attr == NULL || guardsize == NULL || !attr->initialized) {
		return EINVAL;
	}

	*guardsize = __get_attr_guardsize(attr);

	return 0;
}

int pthread_attr_setguardsize(pthread_attr_t *_attr, size_t guardsize)
{
	struct pthread_attr *const attr = (struct pthread_attr *)_attr;

	if (attr == NULL || !attr->initialized || guardsize > PTHREAD_STACK_MAX) {
		return EINVAL;
	}

	__set_attr_guardsize(attr, guardsize);

	return 0;
}

/**
 * @brief Get thread attributes object scheduling parameters.
 *