Re: [RFC PATCH v2 2/7] hv: sched: simple completion implemention


Eddie Dong
 

Hi Shuo:
It seems to be simple :)
From abstraction p.o.v., the APIs are still coupled with the event we are using now. If we can have a neutral event wait/signal APIs, + 2 specific event, that will be great!

In here we may 1) use neutral name, i.e. wait_event, but not wait_vcpu_event. Actually these APIs are for thread, not VCPU specific. 2) the event mechanism may couple with scheduler, but not the specific usage/EVENT we use here.

Thx, Eddie

-----Original Message-----
From: acrn-dev@... <acrn-dev@...> On
Behalf Of Shuo A Liu
Sent: Tuesday, December 31, 2019 2:52 PM
To: acrn-dev@...
Cc: Liu, Shuo A <shuo.a.liu@...>
Subject: [acrn-dev] [RFC PATCH v2 2/7] hv: sched: simple completion
implemention

This simple completion implemention can only support exclusive waiting at
same time. It mainly used by thread who want to wait for some event
happens.
Thread A who want to wait for some events calls
wait_for_completion(struct sched_completion *,
void *action(void *), void *data);
where 'action' is the callback when do wait.

Thread B who can give the completion signal calls
complete(struct sched_completion *,
void *action(void *), void *data);
where 'action' is the callback when do complete.

Signed-off-by: Shuo A Liu <shuo.a.liu@...>
---
hypervisor/common/schedule.c | 45
++++++++++++++++++++++++++++++++++++
hypervisor/include/common/schedule.h | 13 +++++++++++
2 files changed, 58 insertions(+)

diff --git a/hypervisor/common/schedule.c b/hypervisor/common/schedule.c
index 3ce6a41..e74f739 100644
--- a/hypervisor/common/schedule.c
+++ b/hypervisor/common/schedule.c
@@ -274,3 +274,48 @@ void run_thread(struct thread_object *obj)
obj->thread_entry(obj);
}
}
+
+void init_completion(struct sched_completion *completion) {
+ spinlock_init(&completion->lock);
+ completion->done = 0UL;
+ completion->waiting_thread = NULL;
+}
+
+void reset_completion(struct sched_completion *completion) {
+ uint64_t rflag;
+
+ spinlock_irqsave_obtain(&completion->lock, &rflag);
+ completion->done = 0UL;
+ completion->waiting_thread = NULL;
+ spinlock_irqrestore_release(&completion->lock, rflag); }
+
+/* support exclusive waiting only */
+void wait_for_completion(struct sched_completion *completion, wait_fn
+action, void *data) {
+ uint64_t rflag;
+
+ spinlock_irqsave_obtain(&completion->lock, &rflag);
+ ASSERT((completion->waiting_thread == NULL), "only support exclusive
waiting");
+ if (completion->done == 0UL) {
+ completion->waiting_thread = sched_get_current(get_pcpu_id());
+ action(data);
+ }
+ spinlock_irqrestore_release(&completion->lock, rflag); }
+
+void complete(struct sched_completion *completion, complete_fn action,
+void *data) {
+ uint64_t rflag;
+
+ spinlock_irqsave_obtain(&completion->lock, &rflag);
+ completion->done++;
+ if (completion->waiting_thread != NULL) {
+ action(data);
+ completion->done = 0UL;
+ completion->waiting_thread = NULL;
+ }
+ spinlock_irqrestore_release(&completion->lock, rflag); }
diff --git a/hypervisor/include/common/schedule.h
b/hypervisor/include/common/schedule.h
index 1526865..224ad48 100644
--- a/hypervisor/include/common/schedule.h
+++ b/hypervisor/include/common/schedule.h
@@ -90,6 +90,19 @@ struct sched_iorr_control {
struct hv_timer tick_timer;
};

+struct sched_completion {
+ spinlock_t lock;
+ uint32_t done;
+ struct thread_object* waiting_thread;
+};
+
+typedef void (*wait_fn)(void *data);
+typedef void (*complete_fn)(void *data); void init_completion(struct
+sched_completion *completion); void reset_completion(struct
+sched_completion *completion); void wait_for_completion(struct
+sched_completion *completion, wait_fn action, void *data); void
+complete(struct sched_completion *completion, complete_fn action, void
+*data);
+
bool is_idle_thread(const struct thread_object *obj); uint16_t
sched_get_pcpuid(const struct thread_object *obj); struct thread_object
*sched_get_current(uint16_t pcpu_id);
--
2.8.3


Join acrn-dev@lists.projectacrn.org to automatically receive all group messages.