bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] dev_pager: Implement offset


From: Joan Lledó
Subject: [PATCH] dev_pager: Implement offset
Date: Sun, 22 Aug 2021 12:51:10 +0200

From: Joan Lledó <jlledom@member.fsf.org>

* New structure for the internal hash table:
        * 127 slots identified by the device address,
          each one containing a queue of pagers belonging
          to that device.
        * New auxiliary index [pager: device] to quick search
          of pagers.

* dev_pager.c:
        * struct dev_pager: add offset field
        * struct dev_pager_entry: add offset field
        * struct dev_pager_hashtable:
          * is now an index [pager: device]
        * new hash table dev_device_hashtable
          * index [device: queue of pagers]
        * dev_pager_setup(): record the offset
        * device_map_page(): add the recorded offset on the fly
---
 device/dev_pager.c | 102 +++++++++++++++++++++++++++++++--------------
 1 file changed, 70 insertions(+), 32 deletions(-)

diff --git a/device/dev_pager.c b/device/dev_pager.c
index 37ec69fd..fe4a560c 100644
--- a/device/dev_pager.c
+++ b/device/dev_pager.c
@@ -113,6 +113,7 @@ struct dev_pager {
        ipc_port_t      pager;          /* pager port */
        ipc_port_t      pager_request;  /* Known request port */
        ipc_port_t      pager_name;     /* Known name port */
+       vm_offset_t     offset;         /* offset within the pager, in bytes*/
        mach_device_t   device;         /* Device handle */
        int             type;           /* to distinguish */
 #define DEV_PAGER_TYPE 0
@@ -150,24 +151,26 @@ void dev_pager_deallocate(dev_pager_t     ds)
  * A hash table of ports for device_pager backed objects.
  */
 
-#define        DEV_PAGER_HASH_COUNT            127
+#define        DEV_HASH_COUNT          127
 
 struct dev_pager_entry {
        queue_chain_t   links;
        ipc_port_t      name;
+       vm_offset_t     offset;
        dev_pager_t     pager_rec;
 };
 typedef struct dev_pager_entry *dev_pager_entry_t;
 
-queue_head_t   dev_pager_hashtable[DEV_PAGER_HASH_COUNT];
+queue_head_t   dev_device_hashtable[DEV_HASH_COUNT];
 struct kmem_cache      dev_pager_hash_cache;
+mach_device_t  dev_pager_hashtable[DEV_HASH_COUNT];
 decl_simple_lock_data(,
-               dev_pager_hash_lock)
+               dev_hash_lock)
 
-#define        dev_pager_hash(name_port) \
-               (((vm_offset_t)(name_port) & 0xffffff) % DEV_PAGER_HASH_COUNT)
+#define        dev_hash(key) \
+               (((vm_offset_t)(key) & 0xffffff) % DEV_HASH_COUNT)
 
-void dev_pager_hash_init(void)
+void dev_hash_init(void)
 {
        int             i;
        vm_size_t       size;
@@ -175,72 +178,106 @@ void dev_pager_hash_init(void)
        size = sizeof(struct dev_pager_entry);
        kmem_cache_init(&dev_pager_hash_cache, "dev_pager_entry", size, 0,
                        NULL, 0);
-       for (i = 0; i < DEV_PAGER_HASH_COUNT; i++)
-           queue_init(&dev_pager_hashtable[i]);
-       simple_lock_init(&dev_pager_hash_lock);
+       for (i = 0; i < DEV_HASH_COUNT; i++) {
+           queue_init(&dev_device_hashtable[i]);
+           dev_pager_hashtable[i] = MACH_DEVICE_NULL;
+       }
+       simple_lock_init(&dev_hash_lock);
 }
 
-void dev_pager_hash_insert(
-       const ipc_port_t        name_port,
+void dev_hash_insert(
+       const mach_device_t     device,
+       const vm_offset_t       offset,
        const dev_pager_t       rec)
 {
        dev_pager_entry_t new_entry;
 
        new_entry = (dev_pager_entry_t) kmem_cache_alloc(&dev_pager_hash_cache);
-       new_entry->name = name_port;
+       new_entry->name = rec->pager;
+       new_entry->offset = offset;
        new_entry->pager_rec = rec;
 
-       simple_lock(&dev_pager_hash_lock);
-       queue_enter(&dev_pager_hashtable[dev_pager_hash(name_port)],
+       simple_lock(&dev_hash_lock);
+       queue_enter(&dev_device_hashtable[dev_hash(device)],
                        new_entry, dev_pager_entry_t, links);
-       simple_unlock(&dev_pager_hash_lock);
+       dev_pager_hashtable[dev_hash(rec->pager)] = device;
+       simple_unlock(&dev_hash_lock);
 }
 
-void dev_pager_hash_delete(const ipc_port_t name_port)
+void dev_hash_delete(
+       const mach_device_t     device,
+       const vm_offset_t       offset)
 {
        queue_t                 bucket;
        dev_pager_entry_t       entry;
 
-       bucket = &dev_pager_hashtable[dev_pager_hash(name_port)];
+       bucket = &dev_device_hashtable[dev_hash(device)];
 
-       simple_lock(&dev_pager_hash_lock);
+       simple_lock(&dev_hash_lock);
        for (entry = (dev_pager_entry_t)queue_first(bucket);
             !queue_end(bucket, &entry->links);
             entry = (dev_pager_entry_t)queue_next(&entry->links)) {
-           if (entry->name == name_port) {
+           if (entry->offset == offset) {
                queue_remove(bucket, entry, dev_pager_entry_t, links);
+               dev_pager_hashtable[dev_hash(entry->pager_rec->pager)] = 
MACH_DEVICE_NULL;
                break;
            }
        }
-       simple_unlock(&dev_pager_hash_lock);
+       simple_unlock(&dev_hash_lock);
        if (entry)
            kmem_cache_free(&dev_pager_hash_cache, (vm_offset_t)entry);
 }
 
+dev_pager_t dev_device_hash_lookup(
+       const mach_device_t device,
+       vm_offset_t offset)
+{
+       queue_t                 bucket;
+       dev_pager_entry_t       entry;
+       dev_pager_t             pager;
+
+       bucket = &dev_device_hashtable[dev_hash(device)];
+
+       simple_lock(&dev_hash_lock);
+       for (entry = (dev_pager_entry_t)queue_first(bucket);
+            !queue_end(bucket, &entry->links);
+            entry = (dev_pager_entry_t)queue_next(&entry->links)) {
+           if (entry->offset == offset) {
+               pager = entry->pager_rec;
+               dev_pager_reference(pager);
+               simple_unlock(&dev_hash_lock);
+               return (pager);
+           }
+       }
+       simple_unlock(&dev_hash_lock);
+       return (DEV_PAGER_NULL);
+}
+
 dev_pager_t dev_pager_hash_lookup(const ipc_port_t name_port)
 {
+       mach_device_t           device;
        queue_t                 bucket;
        dev_pager_entry_t       entry;
        dev_pager_t             pager;
 
-       bucket = &dev_pager_hashtable[dev_pager_hash(name_port)];
+       device = dev_pager_hashtable[dev_hash(name_port)];
+       bucket = &dev_device_hashtable[dev_hash(device)];
 
-       simple_lock(&dev_pager_hash_lock);
+       simple_lock(&dev_hash_lock);
        for (entry = (dev_pager_entry_t)queue_first(bucket);
             !queue_end(bucket, &entry->links);
             entry = (dev_pager_entry_t)queue_next(&entry->links)) {
            if (entry->name == name_port) {
                pager = entry->pager_rec;
                dev_pager_reference(pager);
-               simple_unlock(&dev_pager_hash_lock);
+               simple_unlock(&dev_hash_lock);
                return (pager);
            }
        }
-       simple_unlock(&dev_pager_hash_lock);
+       simple_unlock(&dev_hash_lock);
        return (DEV_PAGER_NULL);
 }
 
-/* FIXME: This is not recording offset! */
 kern_return_t  device_pager_setup(
        const mach_device_t     device,
        int                     prot,
@@ -261,7 +298,7 @@ kern_return_t       device_pager_setup(
         *      and port to represent this object.
         */
 
-       d = dev_pager_hash_lookup((ipc_port_t)device);  /* HACK */
+       d = dev_device_hash_lookup(device, offset);
        if (d != DEV_PAGER_NULL) {
                *pager = (mach_port_t) ipc_port_make_send(d->pager);
                dev_pager_deallocate(d);
@@ -287,6 +324,7 @@ kern_return_t       device_pager_setup(
        d->client_count = 0;
        d->pager_request = IP_NULL;
        d->pager_name = IP_NULL;
+       d->offset = offset;
        d->device = device;
        mach_device_reference(device);
        d->prot = prot;
@@ -297,8 +335,7 @@ kern_return_t       device_pager_setup(
                d->type = CHAR_PAGER_TYPE;
        }
 
-       dev_pager_hash_insert(d->pager, d);
-       dev_pager_hash_insert((ipc_port_t)device, d);   /* HACK */
+       dev_hash_insert(d->device, d->offset, d);
 
        *pager = (mach_port_t) ipc_port_make_send(d->pager);
        return (KERN_SUCCESS);
@@ -424,7 +461,9 @@ vm_offset_t device_map_page(
 
        return pmap_phys_address(
                   (*(ds->device->dev_ops->d_mmap))
-                       (ds->device->dev_number, offset, ds->prot));
+                       (ds->device->dev_number,
+                       ds->offset + offset,
+                       ds->prot));
 }
 
 kern_return_t device_pager_init_pager(
@@ -493,8 +532,7 @@ kern_return_t device_pager_terminate(
        assert(ds->pager_request == pager_request);
        assert(ds->pager_name == pager_name);
 
-       dev_pager_hash_delete(ds->pager);
-       dev_pager_hash_delete((ipc_port_t)ds->device);  /* HACK */
+       dev_hash_delete(ds->device, ds->offset);
        mach_device_deallocate(ds->device);
 
        /* release the send rights we have saved from the init call */
@@ -553,5 +591,5 @@ void device_pager_init(void)
        /*
         *      Initialize the name port hashing stuff.
         */
-       dev_pager_hash_init();
+       dev_hash_init();
 }
-- 
2.31.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]