Skip to content

Commit

Permalink
phtread: call pthread_exit implicitely on return from start function
Browse files Browse the repository at this point in the history
pthread_exit fix destroying ctx on JOINABLE thread.
Rework handling of detached threads.

JIRA: RTOS-654
  • Loading branch information
badochov committed Oct 27, 2023
1 parent 79d01b8 commit 1755420
Showing 1 changed file with 86 additions and 50 deletions.
136 changes: 86 additions & 50 deletions pthread/pthread.c
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ typedef struct pthread_ctx {
size_t stacksize;
struct pthread_ctx *next;
struct pthread_ctx *prev;
int detached;
int is_detached;
int cancelstate;
struct __errno_t e;
int refcount;
Expand All @@ -65,6 +65,10 @@ static struct {
pthread_cond_t pthread_once_cond;
pthread_ctx *pthread_list;
pthread_fork_handlers_t *pthread_fork_handlers;
struct {
void *stack;
size_t stacksize;
} to_cleanup;
} pthread_common;


Expand Down Expand Up @@ -121,19 +125,19 @@ static void pthread_ctx_put(pthread_ctx *ctx)
}


static void start_point(void *args)
static void pthread_start_point(void *args)
{
pthread_ctx *ctx = (pthread_ctx *)args;

_errno_new(&ctx->e);

ctx->retval = (void *)(ctx->start_routine(ctx->arg));
void *retval = (void *)(ctx->start_routine(ctx->arg));

endthread();
pthread_exit(retval);
}


static pthread_ctx *find_pthread(handle_t id)
static pthread_ctx *pthread_find(handle_t id)
{
mutexLock(pthread_common.pthread_list_lock);
pthread_ctx *ctx = pthread_common.pthread_list;
Expand Down Expand Up @@ -165,15 +169,13 @@ static int pthread_create_main(void)
ctx->retval = NULL;
ctx->stack = NULL;
ctx->stacksize = 0;
ctx->detached = pthread_attr_default.detached;
ctx->is_detached = (pthread_attr_default.detached == PTHREAD_CREATE_DETACHED) ? 1 : 0;
ctx->cancelstate = PTHREAD_CANCEL_ENABLE;
ctx->refcount = 1;
ctx->key_data_list = NULL;
ctx->exiting = 0;

mutexLock(pthread_common.pthread_list_lock);
LIST_ADD(&pthread_common.pthread_list, ctx);
mutexUnlock(pthread_common.pthread_list_lock);

return 0;
}
Expand All @@ -184,14 +186,16 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
{
const pthread_attr_t *attrs = &pthread_attr_default;

if (attr != NULL)
if (attr != NULL) {
attrs = attr;
}

void *stack = mmap(attrs->stackaddr, attrs->stacksize,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, NULL, 0);

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

pthread_ctx *ctx = (pthread_ctx *)malloc(sizeof(pthread_ctx));

Expand All @@ -202,7 +206,7 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

ctx->refcount = 1;
ctx->retval = NULL;
ctx->detached = attrs->detached;
ctx->is_detached = (pthread_attr_default.detached == PTHREAD_CREATE_DETACHED) ? 1 : 0;
ctx->start_routine = start_routine;
ctx->arg = arg;
ctx->stack = stack;
Expand All @@ -213,32 +217,60 @@ int pthread_create(pthread_t *thread, const pthread_attr_t *attr,

mutexLock(pthread_common.pthread_list_lock);

int err = beginthreadex(start_point, attrs->priority, stack,
int err = beginthreadex(pthread_start_point, attrs->priority, stack,
attrs->stacksize, (void *)ctx, &ctx->id);

if (err != 0) {
munmap(stack, attrs->stacksize);
_pthread_ctx_put(ctx);
thread = NULL;
munmap(stack, attrs->stacksize);
}
else {
if (ctx->detached == PTHREAD_CREATE_JOINABLE) {
if (pthread_common.pthread_list != NULL && pthread_common.pthread_list->id == 0) {
pthread_common.pthread_list = NULL;
}
LIST_ADD(&pthread_common.pthread_list, ctx);
}
LIST_ADD(&pthread_common.pthread_list, ctx);
mutexUnlock(pthread_common.pthread_list_lock);
}

return -err;
}


static void _pthread_release(pthread_ctx *ctx, int self)
{
void *prev_stack = NULL, *stack = NULL;
size_t prev_stacksize, stacksize;

_errno_remove(&ctx->e);

LIST_REMOVE(&pthread_common.pthread_list, ctx);

prev_stack = pthread_common.to_cleanup.stack;
prev_stacksize = pthread_common.to_cleanup.stacksize;
pthread_common.to_cleanup.stack = NULL;

if (self == 0) {
stack = ctx->stack;
stacksize = ctx->stacksize;
}
else {
pthread_common.to_cleanup.stack = ctx->stack;
pthread_common.to_cleanup.stacksize = ctx->stacksize;
}

_pthread_ctx_put(ctx);

if (prev_stack != NULL) {
munmap(prev_stack, prev_stacksize);
}
if (stack != NULL) {
munmap(stack, stacksize);
}
}


int pthread_join(pthread_t thread, void **value_ptr)
{
if (thread == pthread_self())
if (pthread_equal(thread, pthread_self())) {
return EDEADLK;
}

pthread_ctx *ctx = (pthread_ctx *)thread;

Expand All @@ -248,31 +280,29 @@ int pthread_join(pthread_t thread, void **value_ptr)

mutexLock(pthread_common.pthread_list_lock);

if (ctx->detached != PTHREAD_CREATE_DETACHED) {
int err, id = ctx->id;
if (ctx->is_detached != 0) {
mutexUnlock(pthread_common.pthread_list_lock);
return EINVAL;
}

do {
err = threadJoin(id, 0);
} while (err == -EINTR);
int err, id = ctx->id;
mutexUnlock(pthread_common.pthread_list_lock);

if (err < 0) {
return err;
}
mutexLock(pthread_common.pthread_list_lock);
do {
err = threadJoin(id, 0);
} while (err == -EINTR);

if (err < 0) {
return err;
}
mutexLock(pthread_common.pthread_list_lock);


if (value_ptr != NULL) {
*value_ptr = ctx->retval;
}

_errno_remove(&ctx->e);

LIST_REMOVE(&pthread_common.pthread_list, ctx);
mutexUnlock(pthread_common.pthread_list_lock);

munmap(ctx->stack, ctx->stacksize);
pthread_ctx_put(ctx);
_pthread_release(ctx, 0);

return 0;
}
Expand All @@ -288,14 +318,14 @@ int pthread_detach(pthread_t thread)
return ESRCH;
}

if (ctx->detached != PTHREAD_CREATE_JOINABLE) {
if (ctx->is_detached != 0) {
mutexUnlock(pthread_common.pthread_list_lock);
return EINVAL;
}

LIST_REMOVE(&pthread_common.pthread_list, ctx);
ctx->is_detached = 1;

_pthread_ctx_put(ctx);
mutexUnlock(pthread_common.pthread_list_lock);

return 0;
}
Expand Down Expand Up @@ -388,8 +418,7 @@ int pthread_cancel(pthread_t thread)
id = ctx->id;
mutexUnlock(pthread_common.pthread_list_lock);
pthread_key_cleanup(ctx);
mutexLock(pthread_common.pthread_list_lock);
_pthread_ctx_put(ctx);
pthread_ctx_put(ctx);
err = signalPost(getpid(), id, signal_cancel);
}
else {
Expand All @@ -403,7 +432,7 @@ int pthread_cancel(pthread_t thread)

pthread_t pthread_self(void)
{
pthread_ctx *ctx = find_pthread(gettid());
pthread_ctx *ctx = pthread_find(gettid());
if (ctx != NULL) {
pthread_ctx_put(ctx);
}
Expand All @@ -423,9 +452,13 @@ __attribute__((noreturn)) void pthread_exit(void *value_ptr)

if (ctx != NULL) {
pthread_key_cleanup(ctx);
mutexLock(pthread_common.pthread_list_lock);
ctx->retval = value_ptr;
_pthread_ctx_put(ctx);
if (ctx->is_detached == 0) {
ctx->retval = value_ptr;
}
else {
mutexLock(pthread_common.pthread_list_lock);
_pthread_release(ctx, 1);
}
}

endthread();
Expand Down Expand Up @@ -575,9 +608,10 @@ int pthread_attr_getscope(const pthread_attr_t *attr,

int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
{
if (detachstate != PTHREAD_CREATE_DETACHED ||
detachstate != PTHREAD_CREATE_JOINABLE)
if ((detachstate != PTHREAD_CREATE_DETACHED) ||
(detachstate != PTHREAD_CREATE_JOINABLE)) {
return EINVAL;
}

attr->detached = detachstate;

Expand All @@ -588,8 +622,9 @@ int pthread_attr_setdetachstate(pthread_attr_t *attr, int detachstate)
int pthread_attr_getdetachstate(const pthread_attr_t *attr,
int *detachstate)
{
if (attr == NULL)
if (attr == NULL) {
return EINVAL;
}

*detachstate = attr->detached;

Expand Down Expand Up @@ -978,7 +1013,7 @@ int pthread_key_delete(pthread_key_t key)
int err = EINVAL;
mutexLock(pthread_common.pthread_list_lock);

pthread_ctx *first = pthread_common.pthread_list, *curr = first;
pthread_ctx *first = pthread_common.pthread_list, *curr = pthread_common.pthread_list;

if (first != NULL) {
mutexLock(pthread_common.pthread_key_lock);
Expand Down Expand Up @@ -1180,4 +1215,5 @@ void _pthread_init(void)
pthread_common.pthread_list = NULL;
pthread_common.pthread_fork_handlers = NULL;
pthread_create_main();
pthread_common.to_cleanup.stack = NULL;
}

0 comments on commit 1755420

Please sign in to comment.