Skip to content

Commit f04c491

Browse files
Shuo A Liuwenlingz
authored andcommitted
hv: sched: decouple scheduler from schedule framework
This patch decouple some scheduling logic and abstract into a scheduler. Then we have scheduler, schedule framework. From modulization perspective, schedule framework provides some APIs for other layers to use, also interact with scheduler through scheduler interaces. Tracked-On: #3813 Signed-off-by: Jason Chen CJ <jason.cj.chen@intel.com> Signed-off-by: Yu Wang <yu1.wang@intel.com> Signed-off-by: Shuo A Liu <shuo.a.liu@intel.com> Acked-by: Eddie Dong <eddie.dong@intel.com>
1 parent cad195c commit f04c491

File tree

10 files changed

+156
-35
lines changed

10 files changed

+156
-35
lines changed

hypervisor/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,7 @@ HW_C_SRCS += arch/x86/cat.c
216216
HW_C_SRCS += arch/x86/sgx.c
217217
HW_C_SRCS += common/softirq.c
218218
HW_C_SRCS += common/schedule.c
219+
HW_C_SRCS += common/sched_noop.c
219220
HW_C_SRCS += hw/pci.c
220221
HW_C_SRCS += arch/x86/configs/vm_config.c
221222
HW_C_SRCS += arch/x86/configs/$(CONFIG_BOARD)/board.c

hypervisor/arch/x86/cpu.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -409,6 +409,7 @@ void cpu_dead(void)
409409
int32_t halt = 1;
410410
uint16_t pcpu_id = get_pcpu_id();
411411

412+
deinit_sched(pcpu_id);
412413
if (bitmap_test(pcpu_id, &pcpu_active_bitmap)) {
413414
/* clean up native stuff */
414415
vmx_off();

hypervisor/arch/x86/guest/vcpu.c

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -729,17 +729,14 @@ static void context_switch_in(struct thread_object *next)
729729
vcpu->running = true;
730730
}
731731

732-
void schedule_vcpu(struct acrn_vcpu *vcpu)
732+
void launch_vcpu(struct acrn_vcpu *vcpu)
733733
{
734734
uint16_t pcpu_id = pcpuid_from_vcpu(vcpu);
735735

736736
vcpu->state = VCPU_RUNNING;
737737
pr_dbg("vcpu%hu scheduled on pcpu%hu", vcpu->vcpu_id, pcpu_id);
738738

739-
get_schedule_lock(pcpu_id);
740-
insert_thread_obj(&vcpu->thread_obj, pcpu_id);
741-
make_reschedule_request(pcpu_id, DEL_MODE_IPI);
742-
release_schedule_lock(pcpu_id);
739+
wake_thread(&vcpu->thread_obj);
743740
}
744741

745742
/* help function for vcpu create */
@@ -761,6 +758,7 @@ int32_t prepare_vcpu(struct acrn_vm *vm, uint16_t pcpu_id)
761758
vcpu->thread_obj.host_sp = build_stack_frame(vcpu);
762759
vcpu->thread_obj.switch_out = context_switch_out;
763760
vcpu->thread_obj.switch_in = context_switch_in;
761+
init_thread_data(&vcpu->thread_obj);
764762
}
765763

766764
return ret;

hypervisor/arch/x86/guest/vlapic.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1172,7 +1172,7 @@ vlapic_process_init_sipi(struct acrn_vcpu* target_vcpu, uint32_t mode, uint32_t
11721172
set_vcpu_startup_entry(target_vcpu, (icr_low & APIC_VECTOR_MASK) << 12U);
11731173
/* init vmcs after set_vcpu_startup_entry */
11741174
init_vmcs(target_vcpu);
1175-
schedule_vcpu(target_vcpu);
1175+
launch_vcpu(target_vcpu);
11761176
}
11771177
}
11781178
} else {

hypervisor/arch/x86/guest/vm.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -642,7 +642,7 @@ void start_vm(struct acrn_vm *vm)
642642
/* Only start BSP (vid = 0) and let BSP start other APs */
643643
bsp = vcpu_from_vid(vm, BOOT_CPU_ID);
644644
init_vmcs(bsp);
645-
schedule_vcpu(bsp);
645+
launch_vcpu(bsp);
646646
}
647647

648648
/**
@@ -766,7 +766,7 @@ void resume_vm_from_s3(struct acrn_vm *vm, uint32_t wakeup_vec)
766766
set_vcpu_startup_entry(bsp, wakeup_vec);
767767

768768
init_vmcs(bsp);
769-
schedule_vcpu(bsp);
769+
launch_vcpu(bsp);
770770
}
771771

772772
/**

hypervisor/common/sched_noop.c

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*
2+
* Copyright (C) 2019 Intel Corporation. All rights reserved.
3+
*
4+
* SPDX-License-Identifier: BSD-3-Clause
5+
*/
6+
7+
#include <per_cpu.h>
8+
#include <schedule.h>
9+
10+
static int32_t sched_noop_init(struct sched_control *ctl)
11+
{
12+
struct sched_noop_control *noop_ctl = &per_cpu(sched_noop_ctl, ctl->pcpu_id);
13+
ctl->priv = noop_ctl;
14+
15+
return 0;
16+
}
17+
18+
static struct thread_object *sched_noop_pick_next(struct sched_control *ctl)
19+
{
20+
struct sched_noop_control *noop_ctl = (struct sched_noop_control *)ctl->priv;
21+
struct thread_object *next = NULL;
22+
23+
if (noop_ctl->noop_thread_obj != NULL) {
24+
next = noop_ctl->noop_thread_obj;
25+
} else {
26+
next = &get_cpu_var(idle);
27+
}
28+
return next;
29+
}
30+
31+
static void sched_noop_sleep(struct thread_object *obj)
32+
{
33+
struct sched_noop_control *noop_ctl = (struct sched_noop_control *)obj->sched_ctl->priv;
34+
35+
if (noop_ctl->noop_thread_obj == obj) {
36+
noop_ctl->noop_thread_obj = NULL;
37+
}
38+
}
39+
40+
static void sched_noop_wake(struct thread_object *obj)
41+
{
42+
struct sched_noop_control *noop_ctl = (struct sched_noop_control *)obj->sched_ctl->priv;
43+
44+
if (noop_ctl->noop_thread_obj == NULL) {
45+
noop_ctl->noop_thread_obj = obj;
46+
}
47+
}
48+
49+
struct acrn_scheduler sched_noop = {
50+
.name = "sched_noop",
51+
.init = sched_noop_init,
52+
.pick_next = sched_noop_pick_next,
53+
.sleep = sched_noop_sleep,
54+
.wake = sched_noop_wake,
55+
};

hypervisor/common/schedule.c

Lines changed: 54 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,24 @@ static inline void set_thread_status(struct thread_object *obj, enum thread_obje
3939
obj->status = status;
4040
}
4141

42+
void get_schedule_lock(uint16_t pcpu_id)
43+
{
44+
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
45+
spinlock_obtain(&ctl->scheduler_lock);
46+
}
47+
48+
void release_schedule_lock(uint16_t pcpu_id)
49+
{
50+
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
51+
spinlock_release(&ctl->scheduler_lock);
52+
}
53+
54+
static struct acrn_scheduler *get_scheduler(uint16_t pcpu_id)
55+
{
56+
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
57+
return ctl->scheduler;
58+
}
59+
4260
/**
4361
* @pre obj != NULL
4462
*/
@@ -55,37 +73,40 @@ void init_sched(uint16_t pcpu_id)
5573
ctl->flags = 0UL;
5674
ctl->curr_obj = NULL;
5775
ctl->pcpu_id = pcpu_id;
76+
ctl->scheduler = &sched_noop;
77+
if (ctl->scheduler->init != NULL) {
78+
ctl->scheduler->init(ctl);
79+
}
5880
}
5981

60-
void get_schedule_lock(uint16_t pcpu_id)
82+
void deinit_sched(uint16_t pcpu_id)
6183
{
6284
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
63-
spinlock_obtain(&ctl->scheduler_lock);
64-
}
6585

66-
void release_schedule_lock(uint16_t pcpu_id)
67-
{
68-
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
69-
spinlock_release(&ctl->scheduler_lock);
86+
if (ctl->scheduler->deinit != NULL) {
87+
ctl->scheduler->deinit(ctl);
88+
}
7089
}
7190

72-
void insert_thread_obj(struct thread_object *obj, uint16_t pcpu_id)
91+
void init_thread_data(struct thread_object *obj)
7392
{
74-
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
75-
76-
ctl->thread_obj = obj;
93+
struct acrn_scheduler *scheduler = get_scheduler(obj->pcpu_id);
94+
get_schedule_lock(obj->pcpu_id);
95+
if (scheduler->init_data != NULL) {
96+
scheduler->init_data(obj);
97+
}
98+
/* initial as BLOCKED status, so we can wake it up to run */
99+
set_thread_status(obj, THREAD_STS_BLOCKED);
100+
release_schedule_lock(obj->pcpu_id);
77101
}
78102

79-
void remove_thread_obj(__unused struct thread_object *obj, uint16_t pcpu_id)
103+
void deinit_thread_data(struct thread_object *obj)
80104
{
81-
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
105+
struct acrn_scheduler *scheduler = get_scheduler(obj->pcpu_id);
82106

83-
ctl->thread_obj = NULL;
84-
}
85-
86-
static struct thread_object *get_next_sched_obj(const struct sched_control *ctl)
87-
{
88-
return ctl->thread_obj == NULL ? &get_cpu_var(idle) : ctl->thread_obj;
107+
if (scheduler->deinit_data != NULL) {
108+
scheduler->deinit_data(obj);
109+
}
89110
}
90111

91112
struct thread_object *sched_get_current(uint16_t pcpu_id)
@@ -142,11 +163,13 @@ void schedule(void)
142163
{
143164
uint16_t pcpu_id = get_pcpu_id();
144165
struct sched_control *ctl = &per_cpu(sched_ctl, pcpu_id);
145-
struct thread_object *next = NULL;
166+
struct thread_object *next = &per_cpu(idle, pcpu_id);
146167
struct thread_object *prev = ctl->curr_obj;
147168

148169
get_schedule_lock(pcpu_id);
149-
next = get_next_sched_obj(ctl);
170+
if (ctl->scheduler->pick_next != NULL) {
171+
next = ctl->scheduler->pick_next(ctl);
172+
}
150173
bitmap_clear_lock(NEED_RESCHEDULE, &ctl->flags);
151174

152175
/* Don't change prev object's status if it's not running */
@@ -168,9 +191,12 @@ void schedule(void)
168191
void sleep_thread(struct thread_object *obj)
169192
{
170193
uint16_t pcpu_id = obj->pcpu_id;
194+
struct acrn_scheduler *scheduler = get_scheduler(pcpu_id);
171195

172196
get_schedule_lock(pcpu_id);
173-
remove_thread_obj(obj, pcpu_id);
197+
if (scheduler->sleep != NULL) {
198+
scheduler->sleep(obj);
199+
}
174200
if (is_running(obj)) {
175201
if (obj->notify_mode == SCHED_NOTIFY_INIT) {
176202
make_reschedule_request(pcpu_id, DEL_MODE_INIT);
@@ -185,10 +211,14 @@ void sleep_thread(struct thread_object *obj)
185211
void wake_thread(struct thread_object *obj)
186212
{
187213
uint16_t pcpu_id = obj->pcpu_id;
214+
struct acrn_scheduler *scheduler;
188215

189216
get_schedule_lock(pcpu_id);
190217
if (is_blocked(obj)) {
191-
insert_thread_obj(obj, pcpu_id);
218+
scheduler = get_scheduler(pcpu_id);
219+
if (scheduler->wake != NULL) {
220+
scheduler->wake(obj);
221+
}
192222
set_thread_status(obj, THREAD_STS_RUNNABLE);
193223
make_reschedule_request(pcpu_id, DEL_MODE_IPI);
194224
}
@@ -197,6 +227,7 @@ void wake_thread(struct thread_object *obj)
197227

198228
void run_thread(struct thread_object *obj)
199229
{
230+
init_thread_data(obj);
200231
get_schedule_lock(obj->pcpu_id);
201232
get_cpu_var(sched_ctl).curr_obj = obj;
202233
set_thread_status(obj, THREAD_STS_RUNNING);

hypervisor/include/arch/x86/guest/vcpu.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ void resume_vcpu(struct acrn_vcpu *vcpu);
634634
*
635635
* @return None
636636
*/
637-
void schedule_vcpu(struct acrn_vcpu *vcpu);
637+
void launch_vcpu(struct acrn_vcpu *vcpu);
638638

639639
/**
640640
* @brief create a vcpu for the vm and mapped to the pcpu.

hypervisor/include/arch/x86/per_cpu.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ struct per_cpu_region {
3737
#endif
3838
struct per_cpu_timers cpu_timers;
3939
struct sched_control sched_ctl;
40+
struct sched_noop_control sched_noop_ctl;
4041
struct thread_object idle;
4142
struct host_gdt gdt;
4243
struct tss_64 tss;

hypervisor/include/common/schedule.h

Lines changed: 37 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
#define DEL_MODE_INIT (1U)
1414
#define DEL_MODE_IPI (2U)
1515

16+
#define THREAD_DATA_SIZE (256U)
17+
1618
enum thread_object_state {
1719
THREAD_STS_RUNNING = 1,
1820
THREAD_STS_RUNNABLE,
@@ -38,27 +40,59 @@ struct thread_object {
3840
uint64_t host_sp;
3941
switch_t switch_out;
4042
switch_t switch_in;
43+
44+
uint8_t data[THREAD_DATA_SIZE];
4145
};
4246

4347
struct sched_control {
4448
uint16_t pcpu_id;
4549
uint64_t flags;
4650
struct thread_object *curr_obj;
4751
spinlock_t scheduler_lock; /* to protect sched_control and thread_object */
52+
struct acrn_scheduler *scheduler;
53+
void *priv;
54+
};
55+
56+
#define SCHEDULER_MAX_NUMBER 4U
57+
struct acrn_scheduler {
58+
char name[16];
59+
60+
/* init scheduler */
61+
int32_t (*init)(struct sched_control *ctl);
62+
/* init private data of scheduler */
63+
void (*init_data)(struct thread_object *obj);
64+
/* pick the next thread object */
65+
struct thread_object* (*pick_next)(struct sched_control *ctl);
66+
/* put thread object into sleep */
67+
void (*sleep)(struct thread_object *obj);
68+
/* wake up thread object from sleep status */
69+
void (*wake)(struct thread_object *obj);
70+
/* yield current thread object */
71+
void (*yield)(struct sched_control *ctl);
72+
/* prioritize the thread object */
73+
void (*prioritize)(struct thread_object *obj);
74+
/* deinit private data of scheduler */
75+
void (*deinit_data)(struct thread_object *obj);
76+
/* deinit scheduler */
77+
void (*deinit)(struct sched_control *ctl);
78+
};
79+
extern struct acrn_scheduler sched_noop;
4880

49-
struct thread_object *thread_obj;
81+
struct sched_noop_control {
82+
struct thread_object *noop_thread_obj;
5083
};
5184

5285
bool is_idle_thread(const struct thread_object *obj);
5386
uint16_t sched_get_pcpuid(const struct thread_object *obj);
5487
struct thread_object *sched_get_current(uint16_t pcpu_id);
5588

5689
void init_sched(uint16_t pcpu_id);
90+
void deinit_sched(uint16_t pcpu_id);
5791
void get_schedule_lock(uint16_t pcpu_id);
5892
void release_schedule_lock(uint16_t pcpu_id);
5993

60-
void insert_thread_obj(struct thread_object *obj, uint16_t pcpu_id);
61-
void remove_thread_obj(struct thread_object *obj, uint16_t pcpu_id);
94+
void init_thread_data(struct thread_object *obj);
95+
void deinit_thread_data(struct thread_object *obj);
6296

6397
void make_reschedule_request(uint16_t pcpu_id, uint16_t delmode);
6498
bool need_reschedule(uint16_t pcpu_id);

0 commit comments

Comments
 (0)