From a38f2cc91837f6c938bd3bf8420dc263a13f07ac Mon Sep 17 00:00:00 2001 From: Conghui Chen Date: Mon, 10 Feb 2020 13:55:35 +0000 Subject: [PATCH] hv: sched_bvt: add wakeup and sleep handler In the wakeup handler, the vcpu_thread object will be inserted into the runqueue, and in the sleep handler, it will be removed from the queue. vcpu_thread object is ordered by EVT (effective virtual time). Tracked-On: #4410 Signed-off-by: Conghui Chen Signed-off-by: Shuo A Liu Acked-by: Eddie Dong --- hypervisor/common/sched_bvt.c | 100 +++++++++++++++++++++++++++++++++- 1 file changed, 98 insertions(+), 2 deletions(-) diff --git a/hypervisor/common/sched_bvt.c b/hypervisor/common/sched_bvt.c index 2746ddcfc..330ca07b3 100644 --- a/hypervisor/common/sched_bvt.c +++ b/hypervisor/common/sched_bvt.c @@ -30,6 +30,88 @@ struct sched_bvt_data { uint64_t start_tsc; }; +/* + * @pre obj != NULL + * @pre obj->data != NULL + */ +static bool is_inqueue(struct thread_object *obj) +{ + struct sched_bvt_data *data = (struct sched_bvt_data *)obj->data; + return !list_empty(&data->list); +} + +/* + * @pre obj != NULL + * @pre obj->data != NULL + * @pre obj->sched_ctl != NULL + * @pre obj->sched_ctl->priv != NULL + */ +static void runqueue_add(struct thread_object *obj) +{ + struct sched_bvt_control *bvt_ctl = + (struct sched_bvt_control *)obj->sched_ctl->priv; + struct sched_bvt_data *data = (struct sched_bvt_data *)obj->data; + struct list_head *pos; + struct thread_object *iter_obj; + struct sched_bvt_data *iter_data; + + /* + * the earliest evt has highest priority, + * the runqueue is ordered by priority. + */ + + if (list_empty(&bvt_ctl->runqueue)) { + list_add(&data->list, &bvt_ctl->runqueue); + } else { + list_for_each(pos, &bvt_ctl->runqueue) { + iter_obj = list_entry(pos, struct thread_object, data); + iter_data = (struct sched_bvt_data *)iter_obj->data; + if (iter_data->evt > data->evt) { + list_add_node(&data->list, pos->prev, pos); + break; + } + } + if (!is_inqueue(obj)) { + list_add_tail(&data->list, &bvt_ctl->runqueue); + } + } +} + +/* + * @pre obj != NULL + * @pre obj->data != NULL + */ +static void runqueue_remove(struct thread_object *obj) +{ + struct sched_bvt_data *data = (struct sched_bvt_data *)obj->data; + + list_del_init(&data->list); +} + +/* + * @brief Get the SVT (scheduler virtual time) which indicates the + * minimum AVT of any runnable threads. + * @pre obj != NULL + * @pre obj->data != NULL + * @pre obj->sched_ctl != NULL + * @pre obj->sched_ctl->priv != NULL + */ + +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; +} + static void sched_tick_handler(__unused void *param) { } @@ -83,12 +165,26 @@ static struct thread_object *sched_bvt_pick_next(__unused struct sched_control * return NULL; } -static void sched_bvt_sleep(__unused struct thread_object *obj) +static void sched_bvt_sleep(struct thread_object *obj) { + runqueue_remove(obj); } -static void sched_bvt_wake(__unused struct thread_object *obj) +static void sched_bvt_wake(struct thread_object *obj) { + struct sched_bvt_data *data; + int64_t svt, threshold; + + data = (struct sched_bvt_data *)obj->data; + svt = get_svt(obj); + threshold = svt - BVT_CSA_MCU; + /* adjusting AVT for a thread after a long sleep */ + data->avt = (data->avt > threshold) ? data->avt : svt; + /* TODO: evt = avt - (warp ? warpback : 0U) */ + data->evt = data->avt; + /* add to runqueue in order */ + runqueue_add(obj); + } struct acrn_scheduler sched_bvt = {