diff --git a/hurd/default_pager.defs b/hurd/default_pager.defs index 8ad82dc..4885503 100644 --- a/hurd/default_pager.defs +++ b/hurd/default_pager.defs @@ -36,6 +36,10 @@ subsystem default_pager 2275; import ; /* XXX */ +#ifdef DEFAULT_PAGER_IMPORTS +DEFAULT_PAGER_IMPORTS +#endif + routine default_pager_object_create( default_pager : mach_port_t; out memory_object : memory_object_t = @@ -90,6 +94,6 @@ routine default_pager_paging_storage( to fix the object's maximum size. Any references to pages beyond the limit will fail. */ routine default_pager_object_set_size( - memory_object : mach_port_t; + memory_object : memory_object_t; msgseqno seqno : mach_port_seqno_t; object_size_limit : vm_size_t); diff --git a/mach-defpager/Makefile b/mach-defpager/Makefile index e38a0be..09debed 100644 --- a/mach-defpager/Makefile +++ b/mach-defpager/Makefile @@ -29,9 +29,10 @@ OBJS := $(SRCS:.c=.o) \ memory_object default_pager memory_object_default exc) \ default_pager_replyUser.o +HURDLIBS:= ihash OTHERLIBS:= -lpthread LDFLAGS += -static include ../Makeconf -MIGSFLAGS = -DSEQNOS +MIGSFLAGS = -DSEQNOS -imacros $(srcdir)/mig-mutate.h diff --git a/mach-defpager/default_pager.c b/mach-defpager/default_pager.c index 8f8e13e..77caa4a 100644 --- a/mach-defpager/default_pager.c +++ b/mach-defpager/default_pager.c @@ -38,14 +38,17 @@ #include #include +#include #include #include -#include -#include -#include -#include +#include + +#include "queue.h" +#include "wiring.h" +#include "kalloc.h" +#include "default_pager.h" #include #include @@ -60,6 +63,8 @@ #include "default_pager_S.h" #include "exc_S.h" +#include "priv.h" + #define debug 0 static char my_name[] = "(default pager):"; @@ -106,47 +111,6 @@ synchronized_printf (const char *fmt, ...) #define ptoa(p) ((p)*vm_page_size) #define atop(a) ((a)/vm_page_size) -/* - * Bitmap allocation. - */ -typedef unsigned int bm_entry_t; -#define NB_BM 32 -#define BM_MASK 0xffffffff - -#define howmany(a,b) (((a) + (b) - 1)/(b)) - -/* - * Value to indicate no block assigned - */ -#define NO_BLOCK ((vm_offset_t)-1) - -/* - * 'Partition' structure for each paging area. - * Controls allocation of blocks within paging area. - */ -struct part { - pthread_mutex_t p_lock; /* for bitmap/free */ - vm_size_t total_size; /* total number of blocks */ - vm_size_t free; /* number of blocks free */ - unsigned int id; /* named lookup */ - bm_entry_t *bitmap; /* allocation map */ - boolean_t going_away; /* destroy attempt in progress */ - struct file_direct *file; /* file paged to */ -}; -typedef struct part *partition_t; - -struct { - pthread_mutex_t lock; - int n_partitions; - partition_t *partition_list;/* array, for quick mapping */ -} all_partitions; /* list of all such */ - -typedef unsigned char p_index_t; - -#define P_INDEX_INVALID ((p_index_t)-1) - -#define no_partition(x) ((x) == P_INDEX_INVALID) - partition_t partition_of(x) int x; { @@ -632,81 +596,6 @@ ddprintf ("pager_dealloc_page(%d,%x,%d)\n",pindex,page,lock_it); } /* - * Allocation info for each paging object. - * - * Most operations, even pager_write_offset and pager_put_checksum, - * just need a read lock. Higher-level considerations prevent - * conflicting operations on a single page. The lock really protects - * the underlying size and block map memory, so pager_extend needs a - * write lock. - * - * An object can now span multiple paging partitions. The allocation - * info we keep is a pair (offset,p_index) where the index is in the - * array of all partition ptrs, and the offset is partition-relative. - * Size wise we are doing ok fitting the pair into a single integer: - * the offset really is in pages so we have vm_page_size bits available - * for the partition index. - */ -#define DEBUG_READER_CONFLICTS 0 - -#if DEBUG_READER_CONFLICTS -int default_pager_read_conflicts = 0; -#endif - -union dp_map { - - struct { - unsigned int p_offset : 24, - p_index : 8; - } block; - - union dp_map *indirect; -}; -typedef union dp_map *dp_map_t; - -/* quick check for part==block==invalid */ -#define no_block(e) ((e).indirect == (dp_map_t)NO_BLOCK) -#define invalidate_block(e) ((e).indirect = (dp_map_t)NO_BLOCK) - -struct dpager { - pthread_mutex_t lock; /* lock for extending block map */ - /* XXX should be read-write lock */ -#if DEBUG_READER_CONFLICTS - int readers; - boolean_t writer; -#endif - dp_map_t map; /* block map */ - vm_size_t size; /* size of paging object, in pages */ - vm_size_t limit; /* limit (bytes) allowed to grow to */ - vm_size_t byte_limit; /* limit, which wasn't - rounded to page boundary */ - p_index_t cur_partition; -#ifdef CHECKSUM - vm_offset_t *checksum; /* checksum - parallel to block map */ -#define NO_CHECKSUM ((vm_offset_t)-1) -#endif /* CHECKSUM */ -}; -typedef struct dpager *dpager_t; - -/* - * A paging object uses either a one- or a two-level map of offsets - * into a paging partition. - */ -#define PAGEMAP_ENTRIES 64 - /* number of pages in a second-level map */ -#define PAGEMAP_SIZE(npgs) ((npgs)*sizeof(vm_offset_t)) - -#define INDIRECT_PAGEMAP_ENTRIES(npgs) \ - ((((npgs)-1)/PAGEMAP_ENTRIES) + 1) -#define INDIRECT_PAGEMAP_SIZE(npgs) \ - (INDIRECT_PAGEMAP_ENTRIES(npgs) * sizeof(vm_offset_t *)) -#define INDIRECT_PAGEMAP(size) \ - (size > PAGEMAP_ENTRIES) - -#define ROUNDUP_TO_PAGEMAP(npgs) \ - (((npgs) + PAGEMAP_ENTRIES - 1) & ~(PAGEMAP_ENTRIES - 1)) - -/* * Object sizes are rounded up to the next power of 2, * unless they are bigger than a given maximum size. */ @@ -1885,40 +1774,6 @@ default_has_page(ds, offset) return ( ! no_block(pager_read_offset(ds, offset)) ); } -/* - * Mapping between pager port and paging object. - */ -struct dstruct { - queue_chain_t links; /* Link in pager-port list */ - - pthread_mutex_t lock; /* Lock for the structure */ - pthread_cond_t - waiting_seqno, /* someone waiting on seqno */ - waiting_read, /* someone waiting on readers */ - waiting_write, /* someone waiting on writers */ - waiting_refs; /* someone waiting on refs */ - - memory_object_t pager; /* Pager port */ - mach_port_seqno_t seqno; /* Pager port sequence number */ - mach_port_t pager_request; /* Request port */ - mach_port_urefs_t request_refs; /* Request port user-refs */ - mach_port_t pager_name; /* Name port */ - mach_port_urefs_t name_refs; /* Name port user-refs */ - boolean_t external; /* Is an external object? */ - - unsigned int readers; /* Reads in progress */ - unsigned int writers; /* Writes in progress */ - - /* This is the reply port of an outstanding - default_pager_object_set_size call. */ - mach_port_t lock_request; - - unsigned int errors; /* Pageout error count */ - struct dpager dpager; /* Actual pager */ -}; -typedef struct dstruct * default_pager_t; -#define DEFAULT_PAGER_NULL ((default_pager_t)0) - #if PARALLEL #define dstruct_lock_init(ds) pthread_mutex_init(&ds->lock, NULL) #define dstruct_lock(ds) pthread_mutex_lock(&ds->lock) @@ -1929,25 +1784,14 @@ typedef struct dstruct * default_pager_t; #define dstruct_unlock(ds) #endif /* PARALLEL */ -/* - * List of all pagers. A specific pager is - * found directly via its port, this list is - * only used for monitoring purposes by the - * default_pager_object* calls - */ -struct pager_port { - queue_head_t queue; - pthread_mutex_t lock; - int count; /* saves code */ - queue_head_t leak_queue; -} all_pagers; +struct pager_port all_pagers; #define pager_port_list_init() \ { \ pthread_mutex_init(&all_pagers.lock, NULL); \ - queue_init(&all_pagers.queue); \ + hurd_ihash_init (&all_pagers.htable, \ + offsetof (struct dstruct, htable_locp)); \ queue_init(&all_pagers.leak_queue); \ - all_pagers.count = 0; \ } void pager_port_list_insert(port, ds) @@ -1955,28 +1799,18 @@ void pager_port_list_insert(port, ds) default_pager_t ds; { pthread_mutex_lock(&all_pagers.lock); - queue_enter(&all_pagers.queue, ds, default_pager_t, links); - all_pagers.count++; + hurd_ihash_add (&all_pagers.htable, + (hurd_ihash_key_t) port, + (hurd_ihash_value_t) ds); pthread_mutex_unlock(&all_pagers.lock); } -/* given a data structure return a good port-name to associate it to */ -#define pnameof(_x_) (((vm_offset_t)(_x_))+1) -/* reverse, assumes no-odd-pointers */ -#define dnameof(_x_) (((vm_offset_t)(_x_))&~1) - -/* The magic typecast */ -#define pager_port_lookup(_port_) \ - ((! MACH_PORT_VALID(_port_) || \ - ((default_pager_t)dnameof(_port_))->pager != (_port_)) ? \ - DEFAULT_PAGER_NULL : (default_pager_t)dnameof(_port_)) - void pager_port_list_delete(ds) default_pager_t ds; { pthread_mutex_lock(&all_pagers.lock); - queue_remove(&all_pagers.queue, ds, default_pager_t, links); - all_pagers.count--; + hurd_ihash_locp_remove (&all_pagers.htable, + ds->htable_locp); pthread_mutex_unlock(&all_pagers.lock); } @@ -2023,7 +1857,8 @@ dprintf("Partition x%x (id x%x) for %s, all_ok %d\n", part, id, name, all_ok); pthread_mutex_lock(&part->p_lock); pthread_mutex_lock(&all_pagers.lock); - queue_iterate(&all_pagers.queue, entry, default_pager_t, links) { + HURD_IHASH_ITERATE (&all_pagers.htable, val) { + entry = (default_pager_t) val; dstruct_lock(entry); @@ -2397,7 +2232,6 @@ seqnos_memory_object_create(old_pager, seqno, new_pager, new_size, vm_size_t new_page_size; { default_pager_t ds; - kern_return_t kr; assert(old_pager == default_pager_default_port); assert(MACH_PORT_VALID(new_pager_request)); @@ -2405,24 +2239,6 @@ seqnos_memory_object_create(old_pager, seqno, new_pager, new_size, assert(new_page_size == vm_page_size); ds = pager_port_alloc(new_size); -rename_it: - kr = mach_port_rename( default_pager_self, - new_pager, (mach_port_t)pnameof(ds)); - if (kr != KERN_SUCCESS) { - default_pager_t ds1; - - if (kr != KERN_NAME_EXISTS) - panic("%s m_o_create", my_name); - ds1 = (default_pager_t) kalloc(sizeof *ds1); - *ds1 = *ds; - pthread_mutex_lock(&all_pagers.lock); - queue_enter(&all_pagers.leak_queue, ds, default_pager_t, links); - pthread_mutex_unlock(&all_pagers.lock); - ds = ds1; - goto rename_it; - } - - new_pager = (mach_port_t) pnameof(ds); /* * Set up associations between these ports @@ -2450,15 +2266,14 @@ memory_object_copy_strategy_t default_pager_copy_strategy = MEMORY_OBJECT_COPY_DELAY; kern_return_t -seqnos_memory_object_init(pager, seqno, pager_request, pager_name, +seqnos_memory_object_init(ds, seqno, pager_request, pager_name, pager_page_size) - mach_port_t pager; + default_pager_t ds; mach_port_seqno_t seqno; mach_port_t pager_request; mach_port_t pager_name; vm_size_t pager_page_size; { - default_pager_t ds; kern_return_t kr; static char here[] = "%sinit"; @@ -2466,7 +2281,6 @@ seqnos_memory_object_init(pager, seqno, pager_request, pager_name, assert(MACH_PORT_VALID(pager_name)); assert(pager_page_size == vm_page_size); - ds = pager_port_lookup(pager); if (ds == DEFAULT_PAGER_NULL) panic(here, my_name); pager_port_lock(ds, seqno); @@ -2512,7 +2326,7 @@ seqnos_memory_object_terminate(pager, seqno, pager_request, pager_name) * not send rights. */ - ds = pager_port_lookup(pager); + ds = begin_using_default_pager(pager); if (ds == DEFAULT_PAGER_NULL) panic(here, my_name); ddprintf ("seqnos_memory_object_terminate <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n", @@ -2578,7 +2392,7 @@ void default_pager_no_senders(pager, seqno, mscount) */ - ds = pager_port_lookup(pager); + ds = begin_using_default_pager(pager); if (ds == DEFAULT_PAGER_NULL) panic(here,my_name); pager_port_lock(ds, seqno); @@ -2639,16 +2453,15 @@ int default_pager_pageout_count = 0; static __thread default_pager_thread_t *dpt; kern_return_t -seqnos_memory_object_data_request(pager, seqno, reply_to, offset, +seqnos_memory_object_data_request(ds, seqno, reply_to, offset, length, protection_required) - memory_object_t pager; + default_pager_t ds; mach_port_seqno_t seqno; mach_port_t reply_to; vm_offset_t offset; vm_size_t length; vm_prot_t protection_required; { - default_pager_t ds; vm_offset_t addr; unsigned int errors; kern_return_t rc; @@ -2657,7 +2470,6 @@ seqnos_memory_object_data_request(pager, seqno, reply_to, offset, if (length != vm_page_size) panic(here,my_name); - ds = pager_port_lookup(pager); if (ds == DEFAULT_PAGER_NULL) panic(here,my_name); ddprintf ("seqnos_memory_object_data_request <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n", @@ -2742,9 +2554,9 @@ ddprintf ("seqnos_memory_object_data_request <%p>: pager_port_unlock: <%p>[s:%d, * also assumes that the default_pager is single-threaded. */ kern_return_t -seqnos_memory_object_data_initialize(pager, seqno, pager_request, +seqnos_memory_object_data_initialize(ds, seqno, pager_request, offset, addr, data_cnt) - memory_object_t pager; + default_pager_t ds; mach_port_seqno_t seqno; mach_port_t pager_request; register @@ -2754,14 +2566,12 @@ seqnos_memory_object_data_initialize(pager, seqno, pager_request, vm_size_t data_cnt; { vm_offset_t amount_sent; - default_pager_t ds; static char here[] = "%sdata_initialize"; #ifdef lint pager_request++; #endif /* lint */ - ds = pager_port_lookup(pager); if (ds == DEFAULT_PAGER_NULL) panic(here,my_name); ddprintf ("seqnos_memory_object_data_initialize <%p>: pager_port_lock: <%p>[s:%d,r:%d,w:%d,l:%d], %d\n", @@ -2804,9 +2614,9 @@ ddprintf ("seqnos_memory_object_data_initialize <%p>: pager_port_unlock: <%p>[s: * into individual pages and pass them off to default_write. */ kern_return_t -seqnos_memory_object_data_write(pager, seqno, pager_request, +seqnos_memory_object_data_write(ds, seqno, pager_request, offset, addr, data_cnt) - memory_object_t pager; + default_pager_t ds; mach_port_seqno_t seqno; mach_port_t pager_request; register @@ -2817,7 +2627,6 @@ seqnos_memory_object_data_write(pager, seqno, pager_request, { register vm_size_t amount_sent; - default_pager_t ds; static char here[] = "%sdata_write"; int err; @@ -2828,7 +2637,6 @@ seqnos_memory_object_data_write(pager, seqno, pager_request, if ((data_cnt % vm_page_size) != 0) panic(here,my_name); - ds = pager_port_lookup(pager); if (ds == DEFAULT_PAGER_NULL) panic(here,my_name); @@ -2888,7 +2696,7 @@ seqnos_memory_object_data_write(pager, seqno, pager_request, kern_return_t seqnos_memory_object_copy(old_memory_object, seqno, old_memory_control, offset, length, new_memory_object) - memory_object_t old_memory_object; + default_pager_t old_memory_object; mach_port_seqno_t seqno; memory_object_control_t old_memory_control; @@ -2916,7 +2724,7 @@ seqnos_memory_object_lock_completed (memory_object_t pager, kern_return_t seqnos_memory_object_data_unlock(pager, seqno, pager_request, offset, length, protection_required) - memory_object_t pager; + default_pager_t pager; mach_port_seqno_t seqno; mach_port_t pager_request; vm_offset_t offset; @@ -2931,7 +2739,7 @@ kern_return_t seqnos_memory_object_supply_completed(pager, seqno, pager_request, offset, length, result, error_offset) - memory_object_t pager; + mach_port_t pager; mach_port_seqno_t seqno; mach_port_t pager_request; vm_offset_t offset; @@ -2949,10 +2757,10 @@ seqnos_memory_object_supply_completed(pager, seqno, pager_request, * into individual pages and pass them off to default_write. */ kern_return_t -seqnos_memory_object_data_return(pager, seqno, pager_request, +seqnos_memory_object_data_return(ds, seqno, pager_request, offset, addr, data_cnt, dirty, kernel_copy) - memory_object_t pager; + default_pager_t ds; mach_port_seqno_t seqno; mach_port_t pager_request; vm_offset_t offset; @@ -2962,7 +2770,7 @@ seqnos_memory_object_data_return(pager, seqno, pager_request, boolean_t kernel_copy; { - return seqnos_memory_object_data_write (pager, seqno, pager_request, + return seqnos_memory_object_data_write (ds, seqno, pager_request, offset, addr, data_cnt); } @@ -3364,23 +3172,14 @@ S_default_pager_object_create (mach_port_t pager, return KERN_INVALID_ARGUMENT; ds = pager_port_alloc(size); -rename_it: - port = (mach_port_t) pnameof(ds); - result = mach_port_allocate_name(default_pager_self, - MACH_PORT_RIGHT_RECEIVE, port); - if (result != KERN_SUCCESS) { - default_pager_t ds1; - - if (result != KERN_NAME_EXISTS) return (result); - - ds1 = (default_pager_t) kalloc(sizeof *ds1); - *ds1 = *ds; - pthread_mutex_lock(&all_pagers.lock); - queue_enter(&all_pagers.leak_queue, ds, default_pager_t, links); - pthread_mutex_unlock(&all_pagers.lock); - ds = ds1; - goto rename_it; - } + result = mach_port_allocate (default_pager_self, + MACH_PORT_RIGHT_RECEIVE, + &port); + if (result != KERN_SUCCESS) + { + kfree ((char *) ds, sizeof *ds); + return result; + } /* * Set up associations between these ports @@ -3454,7 +3253,7 @@ S_default_pager_objects (mach_port_t pager, /* * We will send no more than this many */ - actual = all_pagers.count; + actual = all_pagers.htable.nr_items; pthread_mutex_unlock(&all_pagers.lock); if (opotential < actual) { @@ -3496,7 +3295,8 @@ S_default_pager_objects (mach_port_t pager, pthread_mutex_lock(&all_pagers.lock); num_pagers = 0; - queue_iterate(&all_pagers.queue, entry, default_pager_t, links) { + HURD_IHASH_ITERATE (&all_pagers.htable, val) { + entry = (default_pager_t) val; mach_port_t port; vm_size_t size; @@ -3674,7 +3474,8 @@ S_default_pager_object_pages (mach_port_t pager, default_pager_t entry; pthread_mutex_lock(&all_pagers.lock); - queue_iterate(&all_pagers.queue, entry, default_pager_t, links) { + HURD_IHASH_ITERATE (&all_pagers.htable, val) { + entry = (default_pager_t) val; dstruct_lock(entry); if (entry->pager_name == object) { pthread_mutex_unlock(&all_pagers.lock); @@ -3756,14 +3557,12 @@ S_default_pager_object_pages (mach_port_t pager, kern_return_t -S_default_pager_object_set_size (mach_port_t pager, +S_default_pager_object_set_size (default_pager_t ds, mach_port_seqno_t seqno, vm_size_t limit) { kern_return_t kr = KERN_SUCCESS; - default_pager_t ds; - ds = pager_port_lookup(pager); if (ds == DEFAULT_PAGER_NULL) return KERN_INVALID_ARGUMENT; diff --git a/mach-defpager/main.c b/mach-defpager/main.c index fe6f735..e33c2b3 100644 --- a/mach-defpager/main.c +++ b/mach-defpager/main.c @@ -43,7 +43,7 @@ #include /* XXX */ -#include +#include "default_pager.h" mach_port_t bootstrap_master_device_port; /* local name */ mach_port_t bootstrap_master_host_port; /* local name */ diff --git a/mach-defpager/mig-decls.h b/mach-defpager/mig-decls.h new file mode 100644 index 0000000..8118d61 --- /dev/null +++ b/mach-defpager/mig-decls.h @@ -0,0 +1,34 @@ +/* + Copyright (C) 2014 Free Software Foundation, Inc. + Written by Justus Winter. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see . */ + +#ifndef __MACH_DEFPAGER_MIG_DECLS_H__ +#define __MACH_DEFPAGER_MIG_DECLS_H__ + +#include "priv.h" + +/* Called by server stub functions. */ + +static inline struct dstruct * __attribute__ ((unused)) +begin_using_default_pager (mach_port_t port) +{ + return (default_pager_t) hurd_ihash_find (&all_pagers.htable, + (hurd_ihash_key_t) port); +} + +#endif /* __MACH_DEFPAGER_MIG_DECLS_H__ */ diff --git a/mach-defpager/mig-mutate.h b/mach-defpager/mig-mutate.h new file mode 100644 index 0000000..54aeeba --- /dev/null +++ b/mach-defpager/mig-mutate.h @@ -0,0 +1,22 @@ +/* + Copyright (C) 2014 Free Software Foundation, Inc. + Written by Justus Winter. + + This file is part of the GNU Hurd. + + The GNU Hurd is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2, or (at + your option) any later version. + + The GNU Hurd is distributed in the hope that it will be useful, but + WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + General Public License for more details. + + You should have received a copy of the GNU General Public License + along with the GNU Hurd. If not, see . */ + +#define MEMORY_OBJECT_INTRAN default_pager_t begin_using_default_pager (mach_port_t) +#define MEMORY_OBJECT_IMPORTS import "mig-decls.h"; +#define DEFAULT_PAGER_IMPORTS import "mig-decls.h"; diff --git a/mach-defpager/priv.h b/mach-defpager/priv.h new file mode 100644 index 0000000..3684565 --- /dev/null +++ b/mach-defpager/priv.h @@ -0,0 +1,200 @@ +/* + * Mach Operating System + * Copyright (c) 1993-1989 Carnegie Mellon University + * All Rights Reserved. + * + * Permission to use, copy, modify and distribute this software and its + * documentation is hereby granted, provided that both the copyright + * notice and this permission notice appear in all copies of the + * software, derivative works or modified versions, and any portions + * thereof, and that both notices appear in supporting documentation. + * + * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS" + * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR + * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. + * + * Carnegie Mellon requests users of this software to return to + * + * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU + * School of Computer Science + * Carnegie Mellon University + * Pittsburgh PA 15213-3890 + * + * any improvements or extensions that they make and grant Carnegie Mellon + * the rights to redistribute these changes. + */ + +#ifndef __MACH_DEFPAGER_PRIV_H__ +#define __MACH_DEFPAGER_PRIV_H__ + +#include +#include +#include + +/* + * Bitmap allocation. + */ +typedef unsigned int bm_entry_t; +#define NB_BM 32 +#define BM_MASK 0xffffffff + +#define howmany(a,b) (((a) + (b) - 1)/(b)) + +/* + * Value to indicate no block assigned + */ +#define NO_BLOCK ((vm_offset_t)-1) + +/* + * 'Partition' structure for each paging area. + * Controls allocation of blocks within paging area. + */ +struct part { + pthread_mutex_t p_lock; /* for bitmap/free */ + vm_size_t total_size; /* total number of blocks */ + vm_size_t free; /* number of blocks free */ + unsigned int id; /* named lookup */ + bm_entry_t *bitmap; /* allocation map */ + boolean_t going_away; /* destroy attempt in progress */ + struct file_direct *file; /* file paged to */ +}; +typedef struct part *partition_t; + +struct { + pthread_mutex_t lock; + int n_partitions; + partition_t *partition_list;/* array, for quick mapping */ +} all_partitions; /* list of all such */ + +typedef unsigned char p_index_t; + +#define P_INDEX_INVALID ((p_index_t)-1) + +#define no_partition(x) ((x) == P_INDEX_INVALID) + +/* + * Allocation info for each paging object. + * + * Most operations, even pager_write_offset and pager_put_checksum, + * just need a read lock. Higher-level considerations prevent + * conflicting operations on a single page. The lock really protects + * the underlying size and block map memory, so pager_extend needs a + * write lock. + * + * An object can now span multiple paging partitions. The allocation + * info we keep is a pair (offset,p_index) where the index is in the + * array of all partition ptrs, and the offset is partition-relative. + * Size wise we are doing ok fitting the pair into a single integer: + * the offset really is in pages so we have vm_page_size bits available + * for the partition index. + */ +#define DEBUG_READER_CONFLICTS 0 + +#if DEBUG_READER_CONFLICTS +int default_pager_read_conflicts = 0; +#endif + +union dp_map { + + struct { + unsigned int p_offset : 24, + p_index : 8; + } block; + + union dp_map *indirect; +}; +typedef union dp_map *dp_map_t; + +/* quick check for part==block==invalid */ +#define no_block(e) ((e).indirect == (dp_map_t)NO_BLOCK) +#define invalidate_block(e) ((e).indirect = (dp_map_t)NO_BLOCK) + +struct dpager { + pthread_mutex_t lock; /* lock for extending block map */ + /* XXX should be read-write lock */ +#if DEBUG_READER_CONFLICTS + int readers; + boolean_t writer; +#endif + dp_map_t map; /* block map */ + vm_size_t size; /* size of paging object, in pages */ + vm_size_t limit; /* limit (bytes) allowed to grow to */ + vm_size_t byte_limit; /* limit, which wasn't + rounded to page boundary */ + p_index_t cur_partition; +#ifdef CHECKSUM + vm_offset_t *checksum; /* checksum - parallel to block map */ +#define NO_CHECKSUM ((vm_offset_t)-1) +#endif /* CHECKSUM */ +}; +typedef struct dpager *dpager_t; + +/* + * A paging object uses either a one- or a two-level map of offsets + * into a paging partition. + */ +#define PAGEMAP_ENTRIES 64 + /* number of pages in a second-level map */ +#define PAGEMAP_SIZE(npgs) ((npgs)*sizeof(vm_offset_t)) + +#define INDIRECT_PAGEMAP_ENTRIES(npgs) \ + ((((npgs)-1)/PAGEMAP_ENTRIES) + 1) +#define INDIRECT_PAGEMAP_SIZE(npgs) \ + (INDIRECT_PAGEMAP_ENTRIES(npgs) * sizeof(vm_offset_t *)) +#define INDIRECT_PAGEMAP(size) \ + (size > PAGEMAP_ENTRIES) + +#define ROUNDUP_TO_PAGEMAP(npgs) \ + (((npgs) + PAGEMAP_ENTRIES - 1) & ~(PAGEMAP_ENTRIES - 1)) + +/* + * Mapping between pager port and paging object. + */ +struct dstruct { + hurd_ihash_locp_t htable_locp; /* for the ihash table */ + queue_chain_t links; /* Link in pager-port list */ + + pthread_mutex_t lock; /* Lock for the structure */ + pthread_cond_t + waiting_seqno, /* someone waiting on seqno */ + waiting_read, /* someone waiting on readers */ + waiting_write, /* someone waiting on writers */ + waiting_refs; /* someone waiting on refs */ + + memory_object_t pager; /* Pager port */ + mach_port_seqno_t seqno; /* Pager port sequence number */ + mach_port_t pager_request; /* Request port */ + mach_port_urefs_t request_refs; /* Request port user-refs */ + mach_port_t pager_name; /* Name port */ + mach_port_urefs_t name_refs; /* Name port user-refs */ + boolean_t external; /* Is an external object? */ + + unsigned int readers; /* Reads in progress */ + unsigned int writers; /* Writes in progress */ + + /* This is the reply port of an outstanding + default_pager_object_set_size call. */ + mach_port_t lock_request; + + unsigned int errors; /* Pageout error count */ + struct dpager dpager; /* Actual pager */ +}; +typedef struct dstruct * default_pager_t; +#define DEFAULT_PAGER_NULL ((default_pager_t)0) + +/* + * List of all pagers. A specific pager is + * found directly via its port, this list is + * only used for monitoring purposes by the + * default_pager_object* calls + */ +struct pager_port { + struct hurd_ihash htable; + pthread_mutex_t lock; + queue_head_t leak_queue; +}; + +/* The list of pagers. */ +extern struct pager_port all_pagers; + +#endif /* __MACH_DEFPAGER_PRIV_H__ */ diff --git a/mach-defpager/setup.c b/mach-defpager/setup.c index 7c1afbc..e4ec8d9 100644 --- a/mach-defpager/setup.c +++ b/mach-defpager/setup.c @@ -25,8 +25,8 @@ #include #include -#include -#include +#include "default_pager.h" +#include "kalloc.h" #include "file_io.h" #include "default_pager_S.h"