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
|
#pragma once
#include <hashtbl.h>
#include <mutex.h>
#include <paging.h>
#define PAGE_PINNED 0x01
#define PAGE_ACCESSED 0x02
#define PAGE_DIRTY 0x04
typedef struct pager pager_t;
typedef struct user_region user_region_t;
typedef struct fs_node fs_node_t;
typedef struct fs_handle fs_handle_t;
typedef struct {
size_t (*read)(fs_node_t* data, size_t offset, size_t len, char* ptr);
size_t (*write)(fs_node_t* data, size_t offset, size_t len, const char* ptr);
bool (*resize)(fs_node_t* data, size_t new_size);
} vfs_pager_ops_t;
typedef struct {
void (*page_in)(pager_t *p, size_t offset, size_t len); // allocates the pages
void (*page_commit)(pager_t *p, size_t offset, size_t len); // writes pages back to storage (if applicable)
void (*page_out)(pager_t *p, size_t offset, size_t len); // frees the pages (no need to write back)
void (*page_release)(pager_t *p, size_t offset, size_t len); // called on delete/resize
bool (*resize)(pager_t *p, size_t new_size);
} pager_ops_t;
typedef struct pager {
pager_ops_t *ops;
union {
struct {
bool allow_resize;
} swap_pager;
struct {
fs_node_t* node;
vfs_pager_ops_t *ops;
} vfs_pager;
struct {
void* phys_offset;
} device_pager;
};
size_t size;
hashtbl_t *pages;
mutex_t lock;
user_region_t *maps;
} pager_t;
pager_t* new_swap_pager(size_t size, bool allow_resize);
pager_t* new_vfs_pager(size_t size, fs_node_t* vfs_node, vfs_pager_ops_t *vfs_ops);
pager_t* new_device_pager(size_t size, void* phys_offset);
void change_device_pager(pager_t *p, size_t new_size, void* new_phys_offset);
void delete_pager(pager_t *p);
bool pager_resize(pager_t *p, size_t newsize);
// implement later, when we implement freeing
// void pager_pin_region(pager_t *pager, size_t offset, size_t len);
// void pager_unpin_region(pager_t *pager, size_t offset, size_t len);
void pager_access(pager_t *p, size_t offset, size_t len, bool accessed, bool dirty);
void pager_commit_dirty(pager_t *p);
int pager_get_frame(pager_t *p, size_t offset);
size_t pager_read(pager_t *p, size_t offset, size_t len, char* buf);
size_t pager_write(pager_t *p, size_t offset, size_t len, const char* buf);
void pager_add_map(pager_t *p, user_region_t *reg);
void pager_rm_map(pager_t *p, user_region_t *reg);
// for use by files that use a pager for caching
size_t fs_read_from_pager(fs_handle_t *f, size_t offset, size_t len, char* buf);
size_t fs_write_to_pager(fs_handle_t *f, size_t offset, size_t len, const char* buf);
/* vim: set ts=4 sw=4 tw=0 noet :*/
|