Skip to content

Commit a52605b

Browse files
committed
scheduler now infinitely loops
also blocked on a clang bug
1 parent 5f8d223 commit a52605b

File tree

20 files changed

+249
-80
lines changed

20 files changed

+249
-80
lines changed

arch/wasm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ config WASM
33
depends on !SMP && !BINFMT_ELF && !MMU && !MODULES && !COREDUMP && !SECCOMP && !UPROBES && !COMPAT
44
select ARCH_HAS_BINFMT_WASM
55
select ARCH_HAS_SYSCALL_WRAPPER
6+
select ARCH_NO_PREEMPT
67
select ARCH_NO_SWAP
78
select ARCH_USE_QUEUED_RWLOCKS
89
select ARCH_USE_QUEUED_SPINLOCKS

arch/wasm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ LD = wasm-ld
22

33
WASM_FEATURES = -matomics -mbulk-memory -mexception-handling -mextended-const -mmultivalue -mmutable-globals -mnontrapping-fptoint -mreference-types -mrelaxed-simd -msign-ext -msimd128
44

5-
cflags-y += -Wno-incompatible-library-redeclaration '-D__builtin_return_address=wasm_return_address' $(WASM_FEATURES)
5+
cflags-y += -Wno-incompatible-library-redeclaration '-D__builtin_return_address=wasm_return_address' $(WASM_FEATURES) -mllvm -wasm-enable-sjlj
66
ldflags-y += --import-memory --max-memory=4294967296 --shared-memory
77

88
KBUILD_CFLAGS += $(cflags-y)

arch/wasm/include/asm/thread_info.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,16 +9,17 @@
99
#define THREAD_SHIFT (PAGE_SHIFT << THREAD_SIZE_ORDER)
1010

1111
struct thread_info {
12-
struct task_struct *task;
1312
unsigned long flags;
1413
int preempt_count;
1514
// struct task_struct *from_sched;
16-
unsigned int cpu;
15+
// unsigned int cpu;
16+
unsigned int instance_id;
17+
void* jmpbuf;
1718
};
1819

19-
#define INIT_THREAD_INFO(tsk) \
20-
{ \
21-
.task = &tsk, .flags = 0, .preempt_count = INIT_PREEMPT_COUNT, \
20+
#define INIT_THREAD_INFO(tsk) \
21+
{ \
22+
.flags = 0, .preempt_count = INIT_PREEMPT_COUNT, \
2223
}
2324

2425
#define TIF_SYSCALL_TRACE 0 /* syscall trace active */

arch/wasm/include/asm/wasm_imports.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,10 @@ import("get_now_nsec") unsigned long long wasm_get_now_nsec(void);
2525

2626
import("get_stacktrace") void wasm_get_stacktrace(char *buf, size_t size);
2727

28+
// import("new_kernel_instance") unsigned int wasm_new_kernel_instance(void);
29+
// import("poll_kernel_instance") void wasm_poll_kernel_instance(unsigned int id);
30+
// import("poll_yield") void wasm_poll_yield(void);
31+
2832
#undef import
2933

3034
#endif

arch/wasm/include/uapi/asm/ptrace.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@
66

77
struct task_struct;
88

9-
#define user_mode(regs) 0
10-
#define kernel_mode(regs) 1
11-
#define profile_pc(regs) 0
12-
#define instruction_pointer(regs) 0
13-
#define user_stack_pointer(regs) 0
9+
#define user_mode(regs) (__builtin_trap(),0)
10+
#define kernel_mode(regs) (__builtin_trap(),0)
11+
#define profile_pc(regs) (__builtin_trap(),0)
12+
#define instruction_pointer(regs) (__builtin_trap(),0)
13+
#define user_stack_pointer(regs) (__builtin_trap(),0)
1414

1515
static inline long arch_ptrace(struct task_struct *child, long request,
1616
unsigned long addr, unsigned long data)

arch/wasm/kernel/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ obj-y += \
66
irq.o \
77
process.o \
88
ptrace.o \
9+
setjmp.o \
910
setup.o \
1011
stacktrace.o \
1112
time.o

arch/wasm/kernel/process.c

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
__asm__(".globaltype __stack_pointer, i32\n");
88

9+
int setjmp(void *buf) __attribute__((returns_twice));
10+
void longjmp(void *buf, int val) __attribute__((noreturn));
11+
912
static void *get_stack_pointer(void)
1013
{
1114
void *ptr;
@@ -26,28 +29,67 @@ struct task_struct *__switch_to(struct task_struct *from,
2629
{
2730
struct pt_regs *from_regs = task_pt_regs(from);
2831
struct pt_regs *to_regs = task_pt_regs(to);
32+
struct thread_info *from_info = task_thread_info(from);
33+
struct thread_info *to_info = task_thread_info(to);
34+
35+
// the following call crashes clang:
36+
// from_info->jmpbuf = kmalloc(40, 0);
2937

38+
// to_info->from_sched = from;
39+
current = to;
3040
from_regs->current_stack = get_stack_pointer();
3141

32-
pr_info("context switch PID: %u STACK: %p\n"
33-
"-> %u %p\n",
34-
from->pid, from_regs->current_stack, to->pid,
35-
to_regs->current_stack);
42+
43+
if (setjmp(from_info->jmpbuf) == 0) {
44+
set_stack_pointer(to_regs->current_stack);
45+
46+
schedule_tail(from);
47+
pr_info("switch %u -> %u\n", from->pid, to->pid);
48+
// if (to_info->from_sched)
49+
// schedule_tail(to_info->from_sched);
50+
// to_info->from_sched = NULL;
51+
52+
if (to_regs->fn) {
53+
int (*fn)(void *) = to_regs->fn;
54+
to_regs->fn = NULL;
55+
56+
// callback returns if the kernel thread execs a process?
57+
fn(to_regs->fn_arg);
58+
} else {
59+
longjmp(to_info->jmpbuf, 1);
60+
}
61+
}
62+
63+
kfree(from_info->jmpbuf);
64+
65+
// pr_info("hi %u %u %u\n", from->pid, to->pid, current->pid);
66+
// return current_thread_info()->from_sched;
67+
return from;
68+
69+
// from_regs->current_stack = get_stack_pointer();
3670

37-
set_stack_pointer(to_regs->current_stack);
71+
// if (setjmp(from_info->jmpbuf) == 0) {
72+
// pr_info("context switch %u %p\n"
73+
// " -> %u %p\n",
74+
// from->pid, from_regs->current_stack, to->pid,
75+
// to_regs->current_stack);
3876

39-
current = to;
77+
// set_stack_pointer(to_regs->current_stack);
78+
// pr_info("before jmp %u -> %u\n", current->pid, to->pid);
79+
// current = to;
4080

41-
schedule_tail(from);
81+
// schedule_tail(from);
4282

43-
pr_info("regs: %p\n", to_regs);
44-
BUG_ON(!to_regs->fn);
83+
// pr_info("regs: %p %p\n", to_regs, to_regs->fn);
4584

46-
pr_info("about to call %p %p\n", to_regs->fn, to_regs->fn_arg);
47-
to_regs->fn(to_regs->fn_arg);
48-
to_regs->fn = NULL;
85+
// longjmp(to_info->jmpbuf, 1);
86+
// }
4987

50-
return from;
88+
// set_stack_pointer(from_regs->current_stack);
89+
// pr_info("resuming from jmp %u -> %u\n", current->pid, from->pid);
90+
// current = from;
91+
92+
// return from;
5193
}
5294

5395
int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
@@ -56,12 +98,12 @@ int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
5698

5799
memset(childregs, 0, sizeof(struct pt_regs));
58100

59-
childregs->current_stack = childregs;
101+
childregs->current_stack = childregs - 1;
60102

61103
if (!args->fn)
62104
panic("can't copy userspace thread"); // yet
63105

64-
pr_info("copying thread %i %p\n", p->pid, childregs);
106+
// pr_info("copying thread %i %p\n", p->pid, childregs);
65107

66108
childregs->fn = args->fn;
67109
childregs->fn_arg = args->fn_arg;

arch/wasm/kernel/setjmp.c

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
* once https://github.com/llvm/llvm-project/pull/84137 is merged,
3+
* this file can become significantly less cursed
4+
*/
5+
6+
#include <linux/percpu.h>
7+
#include <linux/slab.h>
8+
#include <linux/types.h>
9+
10+
struct entry {
11+
uint32_t id;
12+
uint32_t label;
13+
};
14+
15+
// TODO(wasm): use pcpu_read
16+
static DEFINE_PER_CPU(
17+
struct state {
18+
uint32_t id;
19+
uint32_t size;
20+
struct arg {
21+
void *env;
22+
int val;
23+
} arg;
24+
},
25+
g_state);
26+
27+
/*
28+
* table is allocated at the entry of functions which call setjmp.
29+
*
30+
* table = malloc(40);
31+
* size = 4;
32+
* *(int *)table = 0;
33+
*/
34+
_Static_assert(sizeof(struct entry) * (4 + 1) <= 40, "entry size");
35+
36+
void *saveSetjmp(void *env, uint32_t label, void *table, uint32_t size)
37+
{
38+
struct state *state = &g_state;
39+
struct entry *e = table;
40+
uint32_t i;
41+
void *p;
42+
43+
for (i = 0; i < size; i++) {
44+
if (e[i].id == 0) {
45+
uint32_t id = ++state->id;
46+
*(uint32_t *)env = id;
47+
e[i].id = id;
48+
e[i].label = label;
49+
/*
50+
* note: only the first word is zero-initialized
51+
* by the caller.
52+
*/
53+
e[i + 1].id = 0;
54+
goto done;
55+
}
56+
}
57+
size *= 2;
58+
p = krealloc(table, sizeof(*e) * (size + 1), 0);
59+
if (!p)
60+
panic("uh oh\n");
61+
table = p;
62+
done:
63+
state->size = size;
64+
return table;
65+
}
66+
67+
uint32_t testSetjmp(unsigned int id, void *table, uint32_t size)
68+
{
69+
struct entry *e = table;
70+
uint32_t i;
71+
for (i = 0; i < size; i++) {
72+
if (e[i].id == id) {
73+
return e[i].label;
74+
}
75+
}
76+
return 0;
77+
}
78+
79+
uint32_t getTempRet0(void)
80+
{
81+
struct state *state = &g_state;
82+
return state->size;
83+
}
84+
85+
void __wasm_longjmp(void *env, int val)
86+
{
87+
struct state *state = &g_state;
88+
struct arg *arg = &state->arg;
89+
if (val == 0)
90+
val = 1;
91+
arg->env = env;
92+
arg->val = val;
93+
__builtin_wasm_throw(1, arg);
94+
}
95+
96+
void *malloc(size_t size)
97+
{
98+
return kmalloc(size, 0);
99+
}
100+
void free(void *ptr)
101+
{
102+
kfree(ptr);
103+
}

include/asm-generic/percpu.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,13 @@
66
#include <linux/threads.h>
77

88
#ifdef CONFIG_USE_PER_CPU_TLS
9+
10+
#ifdef CONFIG_SMP
911
#define PER_CPU_ATTRIBUTES _Thread_local
12+
#else
13+
#define PER_CPU_ATTRIBUTES
14+
#endif
15+
1016
#define PER_CPU_BASE_SECTION ""
1117

1218
bool __percpu_is_static(void *ptr);

include/asm-generic/preempt.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ static __always_inline int preempt_count(void)
1313

1414
static __always_inline volatile int *preempt_count_ptr(void)
1515
{
16+
early_printk("%i", preempt_count());
1617
return &current_thread_info()->preempt_count;
1718
}
1819

justfile

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
watchkernel:
2+
watchexec -r -f '**/*.c' -f '**/*.h' -f '**/Makefile*' just kernel '&&' notify-send -e kernel
3+
watchjs:
4+
watchexec -w tools/wasm/src just js
5+
6+
watchrun:
7+
watchexec -r -w tools/wasm/vmlinux.wasm -w tools/wasm/src --ignore-nothing just run
8+
watchrunnode:
9+
watchexec -r -w tools/wasm/vmlinux.wasm -w tools/wasm/dist --ignore-nothing just runnode
10+
11+
kernel:
12+
make -j16 tools/wasm/vmlinux.wasm
13+
js:
14+
make tools/wasm
15+
16+
run:
17+
tools/wasm/run.ts
18+
runnode:
19+
tools/wasm/index.js
20+
21+
serve:
22+
miniserve tools/wasm/ --index index.html \
23+
--header Cross-Origin-Opener-Policy:same-origin \
24+
--header Cross-Origin-Embedder-Policy:require-corp \
25+
--header Cross-Origin-Resource-Policy:cross-origin

kernel/kthread.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data),
429429
create->done = &done;
430430

431431
spin_lock(&kthread_create_lock);
432+
early_printk("adding kthread %p %s\n", threadfn, namefmt);
432433
list_add_tail(&create->list, &kthread_create_list);
433434
spin_unlock(&kthread_create_lock);
434435

kernel/sched/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6511,6 +6511,7 @@ static void __sched notrace __schedule(unsigned int sched_mode)
65116511
*
65126512
* After this, schedule() must not care about p->state any more.
65136513
*/
6514+
pr_info("deactivating %s %lx %u %u\n", prev->comm, prev_state, prev->pid, prev->sched_class->rank);
65146515
deactivate_task(rq, prev, DEQUEUE_SLEEP | DEQUEUE_NOCLOCK);
65156516

65166517
if (prev->in_iowait) {

kernel/sched/fair.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6076,6 +6076,8 @@ enqueue_task_fair(struct rq *rq, struct task_struct *p, int flags)
60766076
int idle_h_nr_running = task_has_idle_policy(p);
60776077
int task_new = !(flags & ENQUEUE_WAKEUP);
60786078

6079+
early_printk("enqueue %u %s\n", p->pid, p->comm);
6080+
60796081
/*
60806082
* The code below (indirectly) updates schedutil which looks at
60816083
* the cfs_rq utilization to select a frequency.
@@ -6170,6 +6172,9 @@ static void dequeue_task_fair(struct rq *rq, struct task_struct *p, int flags)
61706172
int idle_h_nr_running = task_has_idle_policy(p);
61716173
bool was_sched_idle = sched_idle_rq(rq);
61726174

6175+
early_printk("dequeue %u %s\n", p->pid, p->comm);
6176+
wasm_breakpoint();
6177+
61736178
util_est_dequeue(&rq->cfs, p);
61746179

61756180
for_each_sched_entity(se) {

kernel/sched/swait.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ void swake_up_locked(struct swait_queue_head *q)
2626
return;
2727

2828
curr = list_first_entry(&q->task_list, typeof(*curr), task_list);
29+
pr_info("curr: %p %p\n", curr, &curr->task);
2930
wake_up_process(curr->task);
3031
list_del_init(&curr->task_list);
3132
}

scripts/link-vmlinux.sh

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ kallsyms_step()
197197
mksysmap()
198198
{
199199
info NM ${2}
200-
# ${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
200+
${CONFIG_SHELL} "${srctree}/scripts/mksysmap" ${1} ${2}
201201
}
202202

203203
sorttable()
@@ -286,7 +286,8 @@ if is_enabled CONFIG_DEBUG_INFO_BTF && is_enabled CONFIG_BPF; then
286286
${RESOLVE_BTFIDS} vmlinux
287287
fi
288288

289-
mksysmap vmlinux System.map
289+
# TODO(wasm): add conditional
290+
# mksysmap vmlinux System.map
290291

291292
if is_enabled CONFIG_BUILDTIME_TABLE_SORT; then
292293
info SORTTAB vmlinux

0 commit comments

Comments
 (0)