[bus] Introduce work item queue and processing
authorShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Wed, 15 Dec 2010 01:33:17 +0000 (20:33 -0500)
committerShao Miller <Shao.Miller@yrdsb.edu.on.ca>
Wed, 15 Dec 2010 01:33:17 +0000 (20:33 -0500)
bus__add_work_item_() will add a work item.

bus__get_work_item_() will get and dequeue a work item.

bus__process_work_items() will walk the work item queue
and process each work item.

src/include/bus.h
src/winvblock/bus/bus.c

index f5f42c1..574fe2f 100644 (file)
@@ -40,6 +40,8 @@ struct bus__type {
     UNICODE_STRING dev_name;
     UNICODE_STRING dos_dev_name;
     winvblock__bool named;
+    LIST_ENTRY work_items;
+    KSPIN_LOCK work_items_lock;
   };
 
 /* Exports. */
@@ -55,5 +57,6 @@ extern winvblock__lib_func winvblock__bool STDCALL bus__add_child(
     IN struct device__type *
   );
 extern winvblock__lib_func struct bus__type * bus__get(struct device__type *);
+extern winvblock__lib_func void bus__process_work_items(struct bus__type *);
 
 #endif  /* _BUS_H */
index a5dda3f..7316e1d 100644 (file)
@@ -260,6 +260,8 @@ winvblock__lib_func struct bus__type * bus__create(void) {
     dev_ptr->irp_mj = &bus__irp_mj_;
     dev_ptr->IsBus = TRUE;
     KeInitializeSpinLock(&bus_ptr->SpinLock);
+    KeInitializeSpinLock(&bus_ptr->work_items_lock);
+    InitializeListHead(&bus_ptr->work_items);
 
     return bus_ptr;
 
@@ -362,3 +364,89 @@ extern winvblock__lib_func struct bus__type * bus__get(
   ) {
     return dev->ext;
   }
+
+enum bus__work_item_type_ {
+    bus__work_item_type_add_pdo_,
+    bus__work_item_type_del_pdo_,
+    bus__work_item_types_
+  };
+
+struct bus__work_item_ {
+    LIST_ENTRY list_entry;
+    enum bus__work_item_type_ type;
+    union {
+        PDEVICE_OBJECT dev_obj;
+      } context;
+  };
+
+/**
+ * Add a work item for a bus to process.
+ *
+ * @v bus                       The bus to process the work item.
+ * @v work_item                 The work item to add.
+ * @ret winvblock__bool         TRUE if added, else FALSE
+ */
+static winvblock__bool bus__add_work_item_(
+    struct bus__type * bus,
+    struct bus__work_item_ * work_item
+  ) {
+    if (!bus || !work_item)
+      return FALSE;
+
+    ExInterlockedInsertTailList(
+        &bus->work_items,
+        &work_item->list_entry,
+        &bus->work_items_lock
+      );
+
+    return TRUE;
+  }
+
+/**
+ * Get (and dequeue) a work item from a bus' queue.
+ *
+ * @v bus                       The bus processing the work item.
+ * @ret bus__work_item_         The work item, or NULL for an empty queue.
+ */
+static struct bus__work_item_ * bus__get_work_item_(
+    struct bus__type * bus
+  ) {
+    PLIST_ENTRY list_entry;
+
+    if (!bus)
+      return NULL;
+
+    list_entry = ExInterlockedRemoveHeadList(
+        &bus->work_items,
+        &bus->work_items_lock
+      );
+    if (!list_entry)
+      return NULL;
+
+    return CONTAINING_RECORD(list_entry, struct bus__work_item_, list_entry);
+  }
+
+/**
+ * Process work items for a bus.
+ *
+ * @v bus               The bus to process its work items.
+ */
+winvblock__lib_func void bus__process_work_items(struct bus__type * bus) {
+    struct bus__work_item_ * work_item;
+
+    while (work_item = bus__get_work_item_(bus)) {
+        switch (work_item->type) {
+            case bus__work_item_type_add_pdo_:
+              DBG("Adding PDO...\n");
+              break;
+
+            case bus__work_item_type_del_pdo_:
+              DBG("Deleting PDO...\n");
+              break;
+
+            default:
+              DBG("Unknown work item type!\n");
+          }
+      }
+    return;
+  }