[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