AquilaOS documentation
How it works, and its code
Loading...
Searching...
No Matches
read.c
Go to the documentation of this file.
1
5
6#include <core/system.h>
7
8#include <fs/vfs.h>
9#include <fs/iobuf.h>
10#include <core/arch.h>
11#include <dev/dev.h>
12#include <sys/sched.h>
13
14#include <aquila/fcntl.h>
15#include <aquila/errno.h>
16#include <aquila/dirent.h>
17
30{
31 if (file->flags & O_WRONLY) /* not open for reading */
32 return -EBADF;
33
34 if (!io->resid)
35 return 0;
36
37 /* a device may limit the wait (a terminal's VTIME) */
38 uint64_t until = 0;
39 struct fops *fops = ISDEV(file->vnode) ? kdev_fops(&VNODE_DEV(file->vnode)) :
40 file->vnode->fs ? &file->vnode->fs->fops : NULL;
41
42 if (fops && fops->read_timeout) {
43 uint64_t timeout = fops->read_timeout(file);
44
45 if (timeout)
46 until = arch_rtime_ns() + timeout;
47 }
48
49 int retval;
50 for (;;) {
51 if ((retval = vfs_read_io(file->vnode, file->offset, io)) > 0) {
52 file->offset += retval;
53
54 /* there's room now: wake up the writers waiting for some */
55 if (file->vnode->write_queue)
56 waitq_wakeup(file->vnode->write_queue);
57
58 return retval;
59 } else if (retval < 0) {
60 return retval;
61 } else if (vfs_file_eof(file)) {
62 return 0;
63 } else if (file->flags & O_NONBLOCK) {
64 /* the read would have to wait */
65 return -EAGAIN;
66 } else if (!file->vnode->read_queue) {
67 /* nothing would wake a reader up, there is no more to read */
68 return 0;
69 } else {
70 /* wait until there is data, the time is up (0 bytes), or a
71 * signal comes */
72 int r = sched_wait(file->vnode->read_queue, until);
73
74 if (r)
75 return r < 0 ? r : 0;
76 }
77 }
78}
#define VNODE_DEV(vnode)
Definition dev.h:79
int vfs_file_eof(struct file *file)
Says whether an open file is at its end, so that a read returns 0 rather than waiting.
Definition fops.c:325
struct fops * kdev_fops(struct devid *dd)
Returns the file operations of a device.
Definition kdev.c:52
ssize_t posix_file_read(struct file *file, struct iobuf *io)
Reads from an open file at its offset, and moves the offset past what was read.
Definition read.c:29
ssize_t vfs_read_io(struct vnode *vnode, off_t off, struct iobuf *io)
Reads from a vnode into an iobuf (user or kernel memory).
Definition read.c:20
int sched_wait(struct waitq *waitq, uint64_t until)
Puts the current thread to sleep on a wait queue until it is woken up, a signal ends the sleep,...
Definition sched.c:187
#define NULL
Definition stddef.h:27
unsigned long long int uint64_t
Definition stddef.h:23
An open file (POSIX's "open file description", fs/file.c).
Definition vfs.h:157
off_t offset
Definition vfs.h:163
int flags
Definition vfs.h:164
An open file's operations.
Definition vfs.h:28
uint64_t(*) read_timeout(struct file *)
Definition vfs.h:45
An iobuf.
Definition iobuf.h:35
size_t resid
Definition iobuf.h:38
uint64_t arch_rtime_ns(void)
Reads the monotonic clock, which starts at boot.
Definition timer.c:56
long int ssize_t
Definition types.h:12
#define ISDEV(vnode)
Definition vfs.h:209
void waitq_wakeup(struct waitq *waitq)
Wakes up every thread sleeping on a wait queue, and every thread polling it.
Definition waitq.c:178