Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
script3r
GitHub Repository: script3r/os161
Path: blob/master/kern/vm/swap.c
2093 views
1
#include <types.h>
2
#include <kern/errno.h>
3
#include <kern/fcntl.h>
4
#include <kern/stat.h>
5
#include <lib.h>
6
#include <uio.h>
7
#include <bitmap.h>
8
#include <synch.h>
9
#include <thread.h>
10
#include <current.h>
11
#include <mainbus.h>
12
#include <addrspace.h>
13
#include <vm.h>
14
#include <vm/swap.h>
15
#include <vm/page.h>
16
#include <machine/coremap.h>
17
#include <vfs.h>
18
#include <vnode.h>
19
20
struct bitmap *bm_sw;
21
struct lock *lk_sw;
22
struct swap_stats ss_sw;
23
struct vnode *vn_sw;
24
struct lock *giant_paging_lock;
25
26
static
27
bool
28
swap_device_suficient( size_t ram_size, size_t *swap_size ) {
29
size_t min_size;
30
struct stat stat;
31
32
min_size = ram_size * SWAP_MIN_FACTOR;
33
VOP_STAT( vn_sw, &stat );
34
35
*swap_size = stat.st_size;
36
return stat.st_size >= min_size;
37
}
38
39
static
40
void
41
swap_init_stats( size_t swap_size ) {
42
ss_sw.ss_total = swap_size / PAGE_SIZE;
43
ss_sw.ss_free = ss_sw.ss_total;
44
ss_sw.ss_reserved = 0;
45
}
46
47
48
static
49
void
50
swap_io( paddr_t paddr, off_t offset, enum uio_rw op ) {
51
struct iovec iov;
52
struct uio uio;
53
vaddr_t vaddr;
54
int res;
55
56
KASSERT( lock_do_i_hold( giant_paging_lock ) );
57
KASSERT( curthread->t_vmp_count == 0 || curthread->t_clone );
58
59
//get the virtual address.
60
vaddr = PADDR_TO_KVADDR( paddr );
61
62
//init the uio request.
63
uio_kinit( &iov, &uio, (char *)vaddr, PAGE_SIZE, offset, op );
64
65
//perform the request.
66
res = (op == UIO_READ) ? VOP_READ( vn_sw, &uio ) : VOP_WRITE( vn_sw, &uio );
67
68
//if we have a problem ... bail.
69
if( res )
70
panic( "swap_io: failed to perform a VOP." );
71
}
72
73
void
74
swap_bootstrap() {
75
char sdevice[64];
76
int res;
77
size_t ram_size;
78
size_t swap_size;
79
80
//get the ram size.
81
ram_size = ROUNDUP( mainbus_ramsize(), PAGE_SIZE );
82
83
//prepare to open the swap device.
84
strcpy( sdevice, SWAP_DEVICE );
85
86
//open.
87
res = vfs_open( sdevice, O_RDWR, 0, &vn_sw );
88
if( res )
89
panic( "swap_bootstrap: could not open swapping partition." );
90
91
//make sure it is of suficient size.
92
if( !swap_device_suficient( ram_size, &swap_size ) )
93
panic( "swap_bootstrap: the swap partition is not large enough." );
94
95
//init the stats.
96
swap_init_stats( swap_size );
97
98
//create the bitmap to manage the swap partition.
99
bm_sw = bitmap_create( ss_sw.ss_total );
100
if( bm_sw == NULL )
101
panic( "swap_bootstrap: could not create the swap bitmap." );
102
103
lk_sw = lock_create( "lk_sw" );
104
if( lk_sw == NULL )
105
panic( "swap_bootstrap: could not create the swap lock." );
106
//remove the first page.
107
bitmap_mark( bm_sw, 0 );
108
109
//update stats.
110
--ss_sw.ss_free;
111
}
112
113
off_t
114
swap_alloc() {
115
unsigned ix;
116
int res;
117
118
LOCK_SWAP();
119
res = bitmap_alloc( bm_sw, &ix );
120
if( res ) {
121
UNLOCK_SWAP();
122
return INVALID_SWAPADDR;
123
}
124
125
//update stats
126
--ss_sw.ss_free;
127
128
UNLOCK_SWAP();
129
130
return ix * PAGE_SIZE;
131
}
132
133
void
134
swap_dealloc( off_t offset ) {
135
int ix;
136
137
//the index is simply the offset divided by page size.
138
ix = offset / PAGE_SIZE;
139
140
//lock the swap.
141
LOCK_SWAP();
142
143
//mark this index as unused.
144
bitmap_unmark( bm_sw, ix );
145
146
//update stats.
147
++ss_sw.ss_free;
148
149
//unlock the swap.
150
UNLOCK_SWAP();
151
}
152
153
void
154
swap_in( paddr_t target, off_t source ) {
155
swap_io( target, source, UIO_READ );
156
}
157
158
void
159
swap_out( paddr_t source, off_t target ) {
160
swap_io( source, target, UIO_WRITE );
161
}
162
163
int
164
swap_reserve( unsigned npages ) {
165
LOCK_SWAP();
166
167
KASSERT( ss_sw.ss_free <= ss_sw.ss_total );
168
KASSERT( ss_sw.ss_reserved <= ss_sw.ss_free );
169
170
//if we don't have enough free pages
171
if( ss_sw.ss_free - ss_sw.ss_reserved < npages ) {
172
UNLOCK_SWAP();
173
return ENOSPC;
174
}
175
176
//update the number of reserved pages.
177
ss_sw.ss_reserved += npages;
178
179
UNLOCK_SWAP();
180
return 0;
181
}
182
183
void
184
swap_unreserve( unsigned npages ) {
185
LOCK_SWAP();
186
187
KASSERT( ss_sw.ss_free <= ss_sw.ss_total );
188
KASSERT( ss_sw.ss_reserved <= ss_sw.ss_free );
189
190
//make sure there are at lest npages that are reserved.
191
KASSERT( npages <= ss_sw.ss_reserved );
192
193
//unreserved.
194
ss_sw.ss_reserved -= npages;
195
196
UNLOCK_SWAP();
197
}
198
199