Skip to content

Commit 4ae96ca

Browse files
committed
fs/dmgr: use dmgr for file descriptors again
1 parent 9852983 commit 4ae96ca

File tree

8 files changed

+162
-209
lines changed

8 files changed

+162
-209
lines changed

include/ng/dmgr.h

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,15 @@
66
struct dmgr {
77
int cap;
88
void **data;
9-
mutex_t lock;
9+
spinlock_t lock;
1010
};
1111

1212
BEGIN_DECLS
1313

14-
void dmgr_init(struct dmgr *d);
15-
int dmgr_insert(struct dmgr *d, void *ptr);
16-
void *dmgr_get(struct dmgr *d, int handle);
17-
18-
void *dmgr_set(struct dmgr *d, int handle, void *newptr);
19-
void *dmgr_drop(struct dmgr *d, int handle);
14+
int dmgr_insert(struct dmgr *, void *ptr);
15+
void *dmgr_get(struct dmgr *, int handle);
16+
void *dmgr_set(struct dmgr *, int handle, void *newptr);
17+
void *dmgr_drop(struct dmgr *, int handle);
18+
void dmgr_clone(struct dmgr *child, struct dmgr *parent);
2019

2120
END_DECLS

include/ng/fs/file.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ ssize_t readlink_vnode(struct vnode *vnode, char *buffer, size_t len);
5757

5858
struct process;
5959
struct file *clone_file(struct file *file);
60-
struct file **clone_all_files(struct process *proc);
60+
struct dmgr clone_all_files(struct process *proc);
6161
void close_all_files(struct process *proc);
6262
void close_all_cloexec_files(struct process *proc);
6363

include/ng/thread.h

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -68,10 +68,8 @@ struct process {
6868

6969
struct process *parent;
7070

71-
// struct dmgr fds;
71+
struct dmgr fds;
7272

73-
int n_files;
74-
struct file **files;
7573
struct dentry *root;
7674

7775
list children;

kernel/CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ add_executable(nightingale_kernel
5555
lib/trace.c
5656
lib/ubsan.c
5757
main.c
58-
mem/dmgr.c
58+
lib/dmgr.c
5959
mem/mman.c
6060
mem/pmm.c
6161
mem/ringbuf.c

kernel/fs/file.c

Lines changed: 38 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -88,95 +88,63 @@ bool read_permission(struct vnode *i) { return !!(i->mode & USR_READ); }
8888
bool execute_permission(struct vnode *i) { return !!(i->mode & USR_EXEC); }
8989

9090
struct file *get_file(int fd) {
91-
if (fd > running_process->n_files || fd < 0) {
92-
return nullptr;
93-
}
94-
if (running_process->files[fd])
95-
assert(running_process->files[fd]->magic == FILE_MAGIC);
96-
97-
return running_process->files[fd];
98-
}
99-
100-
static int expand_fds(int new_max) {
101-
struct file **fds = running_process->files;
102-
103-
int prev_max = running_process->n_files;
104-
if (new_max == 0)
105-
new_max = prev_max * 2;
91+
struct file *file = dmgr_get(&running_process->fds, fd);
92+
if (file)
93+
assert(file->magic == FILE_MAGIC);
10694

107-
struct file **new_memory = zrealloc(fds, new_max * sizeof(struct file *));
108-
if (!new_memory)
109-
return -ENOMEM;
110-
running_process->files = new_memory;
111-
running_process->n_files = new_max;
112-
return 0;
95+
return file;
11396
}
11497

11598
int add_file(struct file *file) {
11699
file->magic = FILE_MAGIC;
117-
struct file **fds = running_process->files;
118-
int i;
119-
for (i = 0; i < running_process->n_files; i++) {
120-
if (!fds[i]) {
121-
fds[i] = file;
122-
return i;
123-
}
124-
}
100+
int new_fd = dmgr_insert(&running_process->fds, file);
125101

126-
int err;
127-
if ((err = expand_fds(0)))
128-
return err;
129-
running_process->files[i] = file;
130-
return i;
102+
return new_fd;
131103
}
132104

133105
int add_file_at(struct file *file, int at) {
134106
file->magic = FILE_MAGIC;
135-
struct file **fds = running_process->files;
136-
137-
int err;
138-
if (at < 0)
139-
return -EBADF;
140-
if (at >= running_process->n_files && (err = expand_fds(at + 1)))
141-
return err;
107+
dmgr_set(&running_process->fds, at, file);
142108

143-
running_process->files[at] = file;
144109
return at;
145110
}
146111

147112
struct file *p_remove_file(struct process *proc, int fd) {
148-
if (fd > proc->n_files || fd < 0)
149-
return nullptr;
150-
151-
struct file **fds = proc->files;
152-
153-
struct file *file = fds[fd];
113+
struct file *file = dmgr_drop(&proc->fds, fd);
154114
if (file)
155115
assert(file->magic == FILE_MAGIC);
156116

157-
fds[fd] = 0;
158117
return file;
159118
}
160119

161120
struct file *remove_file(int fd) { return p_remove_file(running_process, fd); }
162121

163122
void close_all_files(struct process *proc) {
164-
struct file *file;
165-
for (int i = 0; i < proc->n_files; i++) {
166-
if ((file = p_remove_file(proc, i)))
123+
spin_lock(&proc->fds.lock);
124+
125+
for (int i = 0; i < proc->fds.cap; i++) {
126+
struct file *file = proc->fds.data[i];
127+
if (file) {
128+
proc->fds.data[i] = nullptr;
167129
close_file(file);
130+
}
168131
}
169-
free(proc->files); // ?
132+
133+
spin_unlock(&proc->fds.lock);
170134
}
171135

172136
void close_all_cloexec_files(struct process *proc) {
173-
struct file *file;
174-
for (int i = 0; i < proc->n_files; i++) {
175-
if ((file = proc->files[i]) && (file->flags & O_CLOEXEC)) {
176-
file = p_remove_file(proc, i);
137+
spin_lock(&proc->fds.lock);
138+
139+
for (int i = 0; i < proc->fds.cap; i++) {
140+
struct file *file = proc->fds.data[i];
141+
if (file && file->flags & O_CLOEXEC) {
142+
proc->fds.data[i] = nullptr;
177143
close_file(file);
178144
}
179145
}
146+
147+
spin_unlock(&proc->fds.lock);
180148
}
181149

182150
struct file *clone_file(struct file *file) {
@@ -187,19 +155,20 @@ struct file *clone_file(struct file *file) {
187155
return new;
188156
}
189157

190-
struct file **clone_all_files(struct process *proc) {
191-
struct file **fds = proc->files;
192-
size_t n_fds = proc->n_files;
193-
if (n_fds == 0 || n_fds > 1000000) {
194-
printf("process %i has %li fds\n", proc->pid, n_fds);
195-
return nullptr;
196-
}
197-
struct file **newfds = calloc(n_fds, sizeof(struct file *));
198-
for (int i = 0; i < n_fds; i++) {
199-
if (fds[i])
200-
newfds[i] = clone_file(fds[i]);
158+
struct dmgr clone_all_files(struct process *proc) {
159+
struct dmgr new_fds = {};
160+
spin_lock(&proc->fds.lock);
161+
162+
for (int i = 0; i < proc->fds.cap; i++) {
163+
struct file *file = proc->fds.data[i];
164+
if (file) {
165+
struct file *new = clone_file(file);
166+
dmgr_set(&new_fds, i, new);
167+
}
201168
}
202-
return newfds;
169+
170+
spin_unlock(&proc->fds.lock);
171+
return new_fds;
203172
}
204173

205174
ssize_t read_file(struct file *file, char *buffer, size_t len) {

kernel/lib/dmgr.c

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
#include <ng/common.h>
2+
#include <ng/debug.h>
3+
#include <ng/dmgr.h>
4+
#include <ng/string.h>
5+
#include <ng/sync.h>
6+
#include <stdlib.h>
7+
8+
#define DMGR_INITIAL_CAPACITY 16
9+
10+
static void dmgr_resize(struct dmgr *d, int new_cap) {
11+
void **new_data = zrealloc(d->data, new_cap * sizeof(void *));
12+
if (new_data) {
13+
d->data = new_data;
14+
d->cap = new_cap;
15+
} else {
16+
panic("dmgr_expand_internal: realloc failed");
17+
}
18+
}
19+
20+
static void dmgr_expand(struct dmgr *d) {
21+
size_t new_cap = MAX(d->cap * 3 / 2, DMGR_INITIAL_CAPACITY);
22+
dmgr_resize(d, new_cap);
23+
}
24+
25+
static void dmgr_expand_to(struct dmgr *d, int cap) {
26+
size_t new_cap = MAX(d->cap, cap + 16);
27+
if (new_cap > d->cap)
28+
dmgr_resize(d, new_cap);
29+
}
30+
31+
int dmgr_insert(struct dmgr *d, void *ptr) {
32+
spin_lock(&d->lock);
33+
int i = 0;
34+
35+
for (;; i++) {
36+
if (i >= d->cap)
37+
dmgr_expand(d);
38+
if (!d->data[i]) {
39+
d->data[i] = ptr;
40+
break;
41+
}
42+
}
43+
44+
spin_unlock(&d->lock);
45+
return i;
46+
}
47+
48+
void *dmgr_get(struct dmgr *d, int handle) {
49+
if (handle > d->cap)
50+
return nullptr;
51+
52+
return d->data[handle];
53+
}
54+
55+
void *dmgr_set(struct dmgr *d, int handle, void *ptr) {
56+
if (handle >= d->cap)
57+
dmgr_expand_to(d, handle);
58+
59+
spin_lock(&d->lock);
60+
void *current = d->data[handle];
61+
62+
d->data[handle] = ptr;
63+
64+
spin_unlock(&d->lock);
65+
return current;
66+
}
67+
68+
void *dmgr_drop(struct dmgr *d, int handle) {
69+
if (handle > d->cap)
70+
return nullptr;
71+
72+
spin_lock(&d->lock);
73+
74+
void *v = d->data[handle];
75+
d->data[handle] = 0;
76+
77+
spin_unlock(&d->lock);
78+
return v;
79+
}
80+
81+
void dmgr_clone(struct dmgr *child, struct dmgr *parent) {
82+
spin_lock(&parent->lock);
83+
84+
*child = (struct dmgr){
85+
.cap = parent->cap,
86+
.data = nullptr,
87+
.lock = {},
88+
};
89+
90+
child->data = malloc(parent->cap * sizeof(void *));
91+
memcpy(child->data, parent->data, parent->cap * sizeof(void *));
92+
93+
spin_unlock(&parent->lock);
94+
}
95+
96+
void dmgr_free(struct dmgr *d) {
97+
free(d->data);
98+
}
99+
100+
void dmgr_dump(struct dmgr *d) {
101+
spin_lock(&d->lock);
102+
103+
printf("dmgr %p { .cap = %d, .data = %p }\n", (void *)d, d->cap,
104+
(void *)d->data);
105+
for (int i = 0; i < d->cap; i++) {
106+
if (d->data[i]) {
107+
printf(" %p: [%i] = %p\n", (void *)&d->data[i], i,
108+
(void *)d->data[i]);
109+
}
110+
}
111+
112+
spin_unlock(&d->lock);
113+
}

0 commit comments

Comments
 (0)