hv: sched: fix bug when reboot vm

BVT schedule rule:
When a new thread is wakeup and added to runqueue, it will get the
smallest avt (svt) from runqueue to initiate its avt. If the svt is
smaller than it's avt, it will keep the original avt. With the svt, it
can prevent a thread from claiming an excessive share of CPU after
sleepting for a long time.

For the reboot issue, when the VM is reboot, it means a new vcpu thread
is wakeup, but at this time, the Service VM's vcpu thread is blocked,
and removed from the runqueue, and the runqueue is empty, so the svt is
0. The new vcpu thread will get avt=0. avt=0 means very high priority,
and can run for a very long time until it catch up with other thread's
avt in runqueue.
At this time, when Service VM's vcpu thread wakeup, it will check the
svt, but the svt is very small, so will not update it's avt according to
the rule, thus has a very low priority and cannot be scheduled.

To fix it, update svt in pick_next handler to make sure svt is align
with the avt of the first obj in runqueue.

Tracked-On: #7944
Signed-off-by: Conghui <conghui.chen@intel.com>
Reviewed-by: Eddie Dong <eddie.dong@intel.com>
Reviewed-by: Wang, Yu1 <yu1.wang@intel.com>
This commit is contained in:
Conghui 2022-07-27 19:35:37 +08:00 committed by acrnsi-robot
parent b7d70385d9
commit 51e6dc5864
2 changed files with 20 additions and 9 deletions

View File

@ -42,6 +42,21 @@ static bool is_inqueue(struct thread_object *obj)
return !list_empty(&data->list);
}
/*
* @pre bvt_ctl != NULL
*/
static void update_svt(struct sched_bvt_control *bvt_ctl)
{
struct sched_bvt_data *obj_data;
struct thread_object *tmp_obj;
if (!list_empty(&bvt_ctl->runqueue)) {
tmp_obj = get_first_item(&bvt_ctl->runqueue, struct thread_object, data);
obj_data = (struct sched_bvt_data *)tmp_obj->data;
bvt_ctl->svt = obj_data->avt;
}
}
/*
* @pre obj != NULL
* @pre obj->data != NULL
@ -102,16 +117,8 @@ static void runqueue_remove(struct thread_object *obj)
static int64_t get_svt(struct thread_object *obj)
{
struct sched_bvt_control *bvt_ctl = (struct sched_bvt_control *)obj->sched_ctl->priv;
struct sched_bvt_data *obj_data;
struct thread_object *tmp_obj;
int64_t svt = 0;
if (!list_empty(&bvt_ctl->runqueue)) {
tmp_obj = get_first_item(&bvt_ctl->runqueue, struct thread_object, data);
obj_data = (struct sched_bvt_data *)tmp_obj->data;
svt = obj_data->avt;
}
return svt;
return bvt_ctl->svt;
}
static void sched_tick_handler(void *param)
@ -236,6 +243,8 @@ static struct thread_object *sched_bvt_pick_next(struct sched_control *ctl)
if (!is_idle_thread(current)) {
update_vt(current);
}
/* always align the svt with the avt of the first thread object in runqueue.*/
update_svt(bvt_ctl);
if (!list_empty(&bvt_ctl->runqueue)) {
first = bvt_ctl->runqueue.next;

View File

@ -105,6 +105,8 @@ extern struct acrn_scheduler sched_bvt;
struct sched_bvt_control {
struct list_head runqueue;
struct hv_timer tick_timer;
/* The minimum AVT of any runnable threads */
int64_t svt;
};
extern struct acrn_scheduler sched_prio;