summaryrefslogtreecommitdiff
path: root/src/kernel/handle.c
blob: d95962c0448fde60b90881c1e697098df7d7f8be (plain)
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
#include <kernel/handle.h>
#include <kernel/mem/alloc.h>
#include <kernel/panic.h>
#include <kernel/pipe.h>
#include <kernel/proc.h>
#include <kernel/vfs/request.h>
#include <shared/mem.h>

struct handle *handle_init(enum handle_type type) {
	struct handle *h = kzalloc(sizeof *h);
	h->type = type;
	h->refcount = 1;
	return h;
}

void handle_close(struct handle *h) {
	if (!h) return;
	assert(h->refcount > 0);
	if (--(h->refcount) > 0) return;

	if (h->type == HANDLE_FILE) {
		vfsreq_create((struct vfs_request) {
				.type = VFSOP_CLOSE,
				.id = h->file_id,
				.caller = NULL,
				.backend = h->backend,
			});
	} else if (h->type == HANDLE_PIPE) {
		assert(!h->pipe.queued);
		if (h->pipe.sister) {
			pipe_invalidate_end(h->pipe.sister);
			h->pipe.sister->pipe.sister = NULL;
		}
	}

	if (h->backend)
		vfs_backend_refdown(h->backend);

	// TODO sanity check to check if refcount is true. handle_sanity?

	h->type = HANDLE_INVALID;
	kfree(h);
}