1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
|
/*
* 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 <mach.h>
#include <queue.h>
#include <hurd/ihash.h>
/*
* 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 */
char *name; /* name */
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__ */
|