Skip to content

Commit

Permalink
Merge pull request #1 from authmillenon/fork-setjmp
Browse files Browse the repository at this point in the history
Use setjmp for fork.
  • Loading branch information
Jakob Pfender committed Sep 17, 2014
2 parents e06dd0d + 1170b4a commit 1053929
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 81 deletions.
11 changes: 0 additions & 11 deletions core/include/arch/thread_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@
#define thread_print_stack thread_arch_print_stack
#define cpu_switch_context_exit thread_arch_start_threading
#define thread_yield thread_arch_yield
#define thread_get_ip thread_arch_get_ip
#define thread_set_ip thread_arch_set_ip
#endif
/** @} */

Expand Down Expand Up @@ -66,15 +64,6 @@ void thread_arch_start_threading(void) NORETURN;
*/
void thread_arch_yield(void);

/**
* @brief Get current instruction pointer
*/
void *thread_arch_get_ip(void);

/**
* @brief Set instruction pointer
*/
void thread_arch_set_ip(void *ip);

#endif /* __THREAD_ARCH_H */
/** @} */
12 changes: 0 additions & 12 deletions cpu/cortex-m3_common/thread_arch.c
Original file line number Diff line number Diff line change
Expand Up @@ -177,15 +177,3 @@ __attribute__((naked)) void isr_pendsv(void)
sched_run();
context_restore();
}

void *thread_arch_get_ip(void)
{
void *ip;
asm("mov %0 r15" : "=r"(ip));
return ip;
}

void thread_arch_set_ip(void *ip)
{
asm("mov r15 %0" : : "r"(ip));
}
90 changes: 32 additions & 58 deletions sys/posix/fork.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,50 +13,35 @@
* @brief Provide POSIX-compliant forking capabilities for processes
* @author Jakob Pfender <jakob.pfender@fu-berlin.de>
*/
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <thread.h>

#include "fork.h"

typedef unsigned int pid_t;
static sem_t fork_sem;
static mutex_t fork_mutex;

typedef struct {
unsigned char in_use;
char stack[FORK_MAX_STACKSIZE];
} fork_stack_t;

static fork_stack_t fork_stacks[FORK_MAXTHREADS];
uint8_t fork_stacks_len = sizeof(fork_stacks) / sizeof(fork_stack_t);
void *fork_reentry_point;
jmp_buf fork_point;

static void fork_init(void)
{
for (i = 0; i < fork_stacks_len; i++) {
fork_stacks[i]->in_use = 0;
}
for (i = 0; i < fork_stacks_len; i++) {
fork_stacks[i]->in_use = 0;
}
}

static pid_t fork_entry(void)
static void fork_entry(void)
{
/* signal original thread that new thread has been created, then
* sleep
*/
sem_post(fork_sem);
thread_sleep();

/* after wakeup, stack and sp have been copied. now go to reentry
* label (return 0) in fork() method
*/
thread_set_ip(fork_reentry_point);

/* this is never reached */
return thread_pid;
longjmp(fork_point, 1);
}

void *fork_alloc()
void *fork_alloc(void)
{
void *ptr = NULL;

Expand All @@ -72,56 +57,45 @@ void *fork_alloc()

pid_t _fork(void)
{
pid_t new_pid = -1;

tcb_t *current = (tcb_t *) active_thread;

/* create new stack for the forked thread */
char *new_stack = (current->stack_size < FORK_MAX_STACKSIZE) ? fork_alloc() : NULL;

if (!new_stack) {
errno = ENOMEM;
return -1;
}

/* create new thread with fork_entry as entry point */
new_pid = thread_create(new_stack, current->stack_size, current->priority, 0, fork_entry, current->name);
tcb_t new_thread = (tcb_t *) sched_threads[new_pid];

/* wait for new thread to be created */
sem_wait(&fork_sem);
if (!setjmp(buf)) {
pid_t new_pid = -1;

/* now we know the new thread is in fork_entry */
tcb_t *current = (tcb_t *) active_thread;

/* duplicate stack */
memcpy(new_stack, current->sp, current->stack_size);
/* create new stack for the forked thread */
char *new_stack = (current->stack_size < FORK_MAX_STACKSIZE) ? fork_alloc() : NULL;

/* duplicate stack pointer */
new_thread->sp = current->sp;
if (!new_stack) {
errno = ENOMEM;
return -1;
}

mutex_lock(&fork_mutex);
/* create new thread with fork_entry as entry point */
new_pid = thread_create(new_stack, current->stack_size, current->priority, 0, fork_entry, current->name);
tcb_t new_thread = (tcb_t *) sched_threads[new_pid];

/* save reentry label for new thread in global variable */
fork_reentry_point = &&fork_reentry;
/* now we know the new thread is in fork_entry */

thread_wakeup(new_thread->pid);
/* duplicate stack */
memcpy(new_stack, current->sp, current->stack_size);

/* this point is only reached by original thread */
return new_pid;
/* duplicate stack pointer */
new_thread->sp = current->sp;

fork_reentry:
/* new thread reenters here */
mutex_unlock(&fork_mutex);
return 0;
return new_pid;
}
else {
return 0;
}
}

int fork_free(int pid)
{
int retval = -1;

if (i < fork_stacks_len) {
fork_stacks[i]->in_use = 0;
retval = 0;
fork_stacks[i]->in_use = 0;
retval = 0;
}

return retval;
Expand Down

0 comments on commit 1053929

Please sign in to comment.