Skip to content

Commit

Permalink
Merge pull request torvalds#231 from tavip/small-fixes
Browse files Browse the repository at this point in the history
A couple of small fixes and scheduling simplification
  • Loading branch information
tavip authored Sep 20, 2016
2 parents 0c98882 + c9a19fc commit 6bce11d
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 63 deletions.
11 changes: 4 additions & 7 deletions arch/lkl/include/asm/thread_info.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,23 +6,20 @@
#ifndef __ASSEMBLY__
#include <asm/types.h>
#include <asm/processor.h>
#include <asm/host_ops.h>

typedef struct {
unsigned long seg;
} mm_segment_t;

struct thread_exit_info {
bool dead;
void *sched_sem;
};

struct thread_info {
struct task_struct *task;
unsigned long flags;
int preempt_count;
mm_segment_t addr_limit;
void *sched_sem;
struct thread_exit_info *exit_info;
struct lkl_sem *sched_sem;
bool dead;
lkl_thread_t tid;
struct task_struct *prev_sched;
unsigned long stackend;
};
Expand Down
76 changes: 30 additions & 46 deletions arch/lkl/kernel/threads.c
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@

static volatile int threads_counter;

static int init_ti(struct thread_info *ti)
{
ti->sched_sem = lkl_ops->sem_alloc(0);
if (!ti->sched_sem)
return -ENOMEM;

ti->dead = false;
ti->prev_sched = NULL;
ti->tid = 0;

return 0;
}

unsigned long *alloc_thread_stack_node(struct task_struct *task, int node)
{
struct thread_info *ti;
Expand All @@ -13,14 +26,12 @@ unsigned long *alloc_thread_stack_node(struct task_struct *task, int node)
if (!ti)
return NULL;

ti->exit_info = NULL;
ti->prev_sched = NULL;
ti->sched_sem = lkl_ops->sem_alloc(0);
ti->task = task;
if (!ti->sched_sem) {
if (init_ti(ti)) {
kfree(ti);
return NULL;
}
ti->task = task;


return (unsigned long *)ti;
}
Expand All @@ -39,22 +50,21 @@ void setup_thread_stack(struct task_struct *p, struct task_struct *org)
ti->addr_limit = org_ti->addr_limit;
}

static void kill_thread(struct thread_exit_info *ei)
static void kill_thread(struct thread_info *ti)
{
if (WARN_ON(!ei))
return;
ti->dead = true;
lkl_ops->sem_up(ti->sched_sem);
lkl_ops->thread_join(ti->tid);
lkl_ops->sem_free(ti->sched_sem);

ei->dead = true;
lkl_ops->sem_up(ei->sched_sem);
}

void free_thread_stack(unsigned long *stack)
{
struct thread_info *ti = (struct thread_info *)stack;
struct thread_exit_info *ei = ti->exit_info;

kill_thread(ti);
kfree(ti);
kill_thread(ei);
}

struct thread_info *_current_thread_info = &init_thread_union.thread_info;
Expand All @@ -76,34 +86,19 @@ struct task_struct *__switch_to(struct task_struct *prev,
* ksoftirqd0 -> swapper: returned prev is swapper
*/
static struct task_struct *abs_prev = &init_task;
/*
* We need to free the thread_info structure in free_thread_info to
* avoid races between the dying thread and other threads. We also need
* to cleanup sched_sem and signal to the prev thread that it needs to
* exit, and we use this stack varible to pass this info.
*/
struct thread_exit_info ei = {
.dead = false,
.sched_sem = _prev->sched_sem,
};

_current_thread_info = task_thread_info(next);
_next->prev_sched = prev;
abs_prev = prev;
_prev->exit_info = &ei;

lkl_ops->sem_up(_next->sched_sem);
/* _next may be already gone so use ei instead */
lkl_ops->sem_down(ei.sched_sem);
lkl_ops->sem_down(_prev->sched_sem);

if (ei.dead) {
lkl_ops->sem_free(ei.sched_sem);
if (_prev->dead) {
__sync_fetch_and_sub(&threads_counter, 1);
lkl_ops->thread_exit();
}

_prev->exit_info = NULL;

return abs_prev;
}

Expand All @@ -120,11 +115,6 @@ static void thread_bootstrap(void *_tba)
int (*f)(void *) = tba->f;
void *arg = tba->arg;

/* Our lifecycle is managed by the LKL kernel, so we want to
* detach here in order to free up host resources when we're
* killed */
lkl_ops->thread_detach();

lkl_ops->sem_down(ti->sched_sem);
kfree(tba);
if (ti->prev_sched)
Expand All @@ -139,7 +129,6 @@ int copy_thread(unsigned long clone_flags, unsigned long esp,
{
struct thread_info *ti = task_thread_info(p);
struct thread_bootstrap_arg *tba;
int ret;

tba = kmalloc(sizeof(*tba), GFP_KERNEL);
if (!tba)
Expand All @@ -149,8 +138,8 @@ int copy_thread(unsigned long clone_flags, unsigned long esp,
tba->arg = (void *)unused;
tba->ti = ti;

ret = lkl_ops->thread_create(thread_bootstrap, tba);
if (!ret) {
ti->tid = lkl_ops->thread_create(thread_bootstrap, tba);
if (!ti->tid) {
kfree(tba);
return -ENOMEM;
}
Expand All @@ -177,16 +166,11 @@ static inline void pr_early(const char *str)
int threads_init(void)
{
struct thread_info *ti = &init_thread_union.thread_info;
int ret = 0;

ti->exit_info = NULL;
ti->prev_sched = NULL;
int ret;

ti->sched_sem = lkl_ops->sem_alloc(0);
if (!ti->sched_sem) {
ret = init_ti(ti);
if (ret < 0)
pr_early("lkl: failed to allocate init schedule semaphore\n");
ret = -ENOMEM;
}

return ret;
}
Expand All @@ -204,7 +188,7 @@ void threads_cleanup(void)
WARN(p->state == TASK_RUNNING,
"thread %s still running while halting\n", p->comm);

kill_thread(ti->exit_info);
kill_thread(ti);
}

while (threads_counter)
Expand Down
21 changes: 12 additions & 9 deletions tools/lkl/tests/boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -673,9 +673,10 @@ static int test_lo_ifup(char *str, int len)
static int test_mutex(char *str, int len)
{
long ret = TEST_SUCCESS;
/* Can't do much to verify that this works, so we'll just let
* Valgrind warn us on CI if we've made bad memory
* accesses. */
/*
* Can't do much to verify that this works, so we'll just let Valgrind
* warn us on CI if we've made bad memory accesses.
*/

struct lkl_mutex *mutex = lkl_host_ops.mutex_alloc();
lkl_host_ops.mutex_lock(mutex);
Expand All @@ -690,9 +691,10 @@ static int test_mutex(char *str, int len)
static int test_semaphore(char *str, int len)
{
long ret = TEST_SUCCESS;
/* Can't do much to verify that this works, so we'll just let
* Valgrind warn us on CI if we've made bad memory
* accesses. */
/*
* Can't do much to verify that this works, so we'll just let Valgrind
* warn us on CI if we've made bad memory accesses.
*/

struct lkl_sem *sem = lkl_host_ops.sem_alloc(1);
lkl_host_ops.sem_down(sem);
Expand Down Expand Up @@ -893,6 +895,10 @@ int main(int argc, char **argv)

lkl_host_ops.print = printk;

TEST(mutex);
TEST(semaphore);
TEST(join);

if (cla.disk_filename)
TEST(disk_add);
#ifndef __MINGW32__
Expand Down Expand Up @@ -934,11 +940,8 @@ int main(int argc, char **argv)
TEST(umount_dev);
}
TEST(lo_ifup);
TEST(mutex);
TEST(semaphore);
TEST(gettid);
TEST(syscall_thread);
TEST(join);
/*
* Wine has an issue where the FlsCallback is not called when the thread
* terminates which makes testing the automatic syscall threads cleanup
Expand Down
2 changes: 1 addition & 1 deletion tools/lkl/tests/test.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
static int g_test_pass = 0;
#define TEST(name, ...) \
{ \
char str[MAX_MSG_LEN]; \
char str[MAX_MSG_LEN] = { 0, }; \
int (*fn)(char *str, int len, ...); \
int ret; \
\
Expand Down

0 comments on commit 6bce11d

Please sign in to comment.