diff mbox series

[RFC,11/49] xen/sched: build a linked list of struct sched_item

Message ID 20190329150934.17694-12-jgross@suse.com (mailing list archive)
State Superseded
Headers show
Series xen: add core scheduling support | expand

Commit Message

Jürgen Groß March 29, 2019, 3:08 p.m. UTC
In order to make it easy to iterate over sched_item elements of a
domain build a single linked list and add an iterator for it. The new
list is guarded by the same mechanisms as the vcpu linked list as it
is modified only via vcpu_create() or vcpu_destroy().

For completeness add another iterator for_each_sched_item_vcpu() which
will iterate over all vcpus if a sched_item (right now only one). This
will be needed later for larger scheduling granularity (e.g. cores).

Signed-off-by: Juergen Gross <jgross@suse.com>
---
 xen/common/schedule.c      | 56 ++++++++++++++++++++++++++++++++++++++++------
 xen/include/xen/sched-if.h |  8 +++++++
 xen/include/xen/sched.h    |  1 +
 3 files changed, 58 insertions(+), 7 deletions(-)
diff mbox series

Patch

diff --git a/xen/common/schedule.c b/xen/common/schedule.c
index 819a78b646..e9d91d29cc 100644
--- a/xen/common/schedule.c
+++ b/xen/common/schedule.c
@@ -253,6 +253,52 @@  static void sched_spin_unlock_double(spinlock_t *lock1, spinlock_t *lock2,
     spin_unlock_irqrestore(lock1, flags);
 }
 
+static void sched_free_item(struct sched_item *item)
+{
+    struct sched_item *prev_item;
+    struct domain *d = item->vcpu->domain;
+
+    if ( d->sched_item_list == item )
+        d->sched_item_list = item->next_in_list;
+    else
+    {
+        for_each_sched_item(d, prev_item)
+        {
+            if ( prev_item->next_in_list == item )
+            {
+                prev_item->next_in_list = item->next_in_list;
+                break;
+            }
+        }
+    }
+
+    item->vcpu->sched_item = NULL;
+    xfree(item);
+}
+
+static struct sched_item *sched_alloc_item(struct vcpu *v)
+{
+    struct sched_item *item, **prev_item;
+    struct domain *d = v->domain;
+
+    if ( (item = xzalloc(struct sched_item)) == NULL )
+        return NULL;
+
+    v->sched_item = item;
+    item->vcpu = v;
+
+    for ( prev_item = &d->sched_item_list; *prev_item;
+          prev_item = &(*prev_item)->next_in_list )
+        if ( (*prev_item)->next_in_list &&
+             (*prev_item)->next_in_list->vcpu->vcpu_id > v->vcpu_id )
+            break;
+
+    item->next_in_list = *prev_item;
+    *prev_item = item;
+
+    return item;
+}
+
 int sched_init_vcpu(struct vcpu *v, unsigned int processor)
 {
     struct domain *d = v->domain;
@@ -260,10 +306,8 @@  int sched_init_vcpu(struct vcpu *v, unsigned int processor)
 
     v->processor = processor;
 
-    if ( (item = xzalloc(struct sched_item)) == NULL )
+    if ( (item = sched_alloc_item(v)) == NULL )
         return 1;
-    v->sched_item = item;
-    item->vcpu = v;
 
     /* Initialise the per-vcpu timers. */
     init_timer(&v->periodic_timer, vcpu_periodic_timer_fn,
@@ -276,8 +320,7 @@  int sched_init_vcpu(struct vcpu *v, unsigned int processor)
     item->priv = SCHED_OP(dom_scheduler(d), alloc_vdata, item, d->sched_priv);
     if ( item->priv == NULL )
     {
-        v->sched_item = NULL;
-        xfree(item);
+        sched_free_item(item);
         return 1;
     }
 
@@ -420,8 +463,7 @@  void sched_destroy_vcpu(struct vcpu *v)
         atomic_dec(&per_cpu(schedule_data, v->processor).urgent_count);
     SCHED_OP(vcpu_scheduler(v), remove_item, item);
     SCHED_OP(vcpu_scheduler(v), free_vdata, item->priv);
-    xfree(item);
-    v->sched_item = NULL;
+    sched_free_item(item);
 }
 
 int sched_init_domain(struct domain *d, int poolid)
diff --git a/xen/include/xen/sched-if.h b/xen/include/xen/sched-if.h
index 1fe87a73b4..4caade5b8b 100644
--- a/xen/include/xen/sched-if.h
+++ b/xen/include/xen/sched-if.h
@@ -51,8 +51,16 @@  DECLARE_PER_CPU(struct cpupool *, cpupool);
 struct sched_item {
     struct vcpu           *vcpu;
     void                  *priv;      /* scheduler private data */
+    struct sched_item     *next_in_list;
 };
 
+#define for_each_sched_item(d, e)                                         \
+    for ( (e) = (d)->sched_item_list; (e) != NULL; (e) = (e)->next_in_list )
+
+#define for_each_sched_item_vcpu(i, v)                                    \
+    for ( (v) = (i)->vcpu; (v) != NULL && (v)->sched_item == (i);         \
+          (v) = (v)->next_in_list )
+
 /*
  * Scratch space, for avoiding having too many cpumask_t on the stack.
  * Within each scheduler, when using the scratch mask of one pCPU:
diff --git a/xen/include/xen/sched.h b/xen/include/xen/sched.h
index 6acdc0f5be..2e9ced29a8 100644
--- a/xen/include/xen/sched.h
+++ b/xen/include/xen/sched.h
@@ -334,6 +334,7 @@  struct domain
 
     /* Scheduling. */
     void            *sched_priv;    /* scheduler-specific data */
+    struct sched_item *sched_item_list;
     struct cpupool  *cpupool;
 
     struct domain   *next_in_list;