Martin Mares wrote:
Hello!
But it executed C++ code within a few cycles of entering the reset
vector (no standard BIOS), including but not limited to: programming the
memory controller (430MX chipset), servicing interrupts, hardware
accelerated 2D graphics (C&T 65550), IDE driver, simple filesystem,
simple windowing GUI, network driver (Tulip) etc.
I really don't claim it's impossible to write kernels in C++ -- it's
clearly possible given that everything you can do in C, you can do in
C++ as well. But what I argued about is whether kernel programming in C++
can be easier and more efficient, which is why I wanted you to show
some examples. Real code speaks better than thousand theories.
Here are three versions of do_sendfile(). When you read it, please
assume you know light_file_ptr as well as you know f{get,put}_light, etc.
The (IMO) improvement is not dramatic since this is fairly much straight line code.
static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
size_t count, loff_t max)
{
struct file * in_file, * out_file;
struct inode * in_inode, * out_inode;
loff_t pos;
ssize_t retval;
int fput_needed_in, fput_needed_out;
/*
* Get input file, and verify that it is ok..
*/
retval = -EBADF;
in_file = fget_light(in_fd, &fput_needed_in);
if (!in_file)
goto out;
if (!(in_file->f_mode & FMODE_READ))
goto fput_in;
retval = -EINVAL;
in_inode = in_file->f_dentry->d_inode;
if (!in_inode)
goto fput_in;
if (!in_file->f_op || !in_file->f_op->sendfile)
goto fput_in;
retval = -ESPIPE;
if (!ppos)
ppos = &in_file->f_pos;
else
if (!(in_file->f_mode & FMODE_PREAD))
goto fput_in;
retval = rw_verify_area(READ, in_file, ppos, count);
if (retval < 0)
goto fput_in;
count = retval;
retval = security_file_permission (in_file, MAY_READ);
if (retval)
goto fput_in;
/*
* Get output file, and verify that it is ok..
*/
retval = -EBADF;
out_file = fget_light(out_fd, &fput_needed_out);
if (!out_file)
goto fput_in;
if (!(out_file->f_mode & FMODE_WRITE))
goto fput_out;
retval = -EINVAL;
if (!out_file->f_op || !out_file->f_op->sendpage)
goto fput_out;
out_inode = out_file->f_dentry->d_inode;
retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
if (retval < 0)
goto fput_out;
count = retval;
retval = security_file_permission (out_file, MAY_WRITE);
if (retval)
goto fput_out;
if (!max)
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
pos = *ppos;
retval = -EINVAL;
if (unlikely(pos < 0))
goto fput_out;
if (unlikely(pos + count > max)) {
retval = -EOVERFLOW;
if (pos >= max)
goto fput_out;
count = max - pos;
}
retval = in_file->f_op->sendfile(in_file, ppos, count, file_send_actor, out_file);
if (retval > 0) {
current->rchar += retval;
current->wchar += retval;
}
current->syscr++;
current->syscw++;
if (*ppos > max)
retval = -EOVERFLOW;
fput_out:
fput_light(out_file, fput_needed_out);
fput_in:
fput_light(in_file, fput_needed_in);
out:
return retval;
}
static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
size_t count, loff_t max)
{
loff_t pos;
ssize_t retval;
/*
* Get input file, and verify that it is ok..
*/
light_file_ptr in_file(in_fd);
if (!in_file.valid())
return -EBADF;
if (!in_file->readable())
return -EBADF;
retval = -EINVAL;
struct inode *in_inode = in_file->dentry()->inode();
if (!in_inode)
return -EINVAL;
// I'm assuming here that the default sendfile() returns -EINVAL
if (!ppos)
ppos = &in_file->f_pos;
else
if (!(in_file->mode() & FMODE_PREAD))
return -ESPIPE;
retval = rw_verify_area(READ, in_file, ppos, count);
if (retval < 0)
return retval;
count = retval;
retval = security_file_permission (in_file, MAY_READ);
if (retval)
return retval;
/*
* Get output file, and verify that it is ok..
*/
light_file_ptr out_file(out_fd);
if (!out_file)
return -EBADF;
if (!(out_file->writable())
return -EBADF;
// Again, assuming default sendpage returns -EINVAL
struct inode *out_inode = out_file->dentry()->inode();
retval = rw_verify_area(WRITE, out_file, &out_file->f_pos, count);
if (retval < 0)
return retval;
count = retval;
retval = security_file_permission (out_file, MAY_WRITE);
if (retval)
return retval;
if (!max)
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
pos = *ppos;
if (unlikely(pos < 0))
return -EINVAL;
if (unlikely(pos + count > max)) {
if (pos >= max)
return -EOVERFLOW;
count = max - pos;
}
retval = in_file->sendfile(ppos, count, file_send_actor, out_file);
if (retval > 0) {
current->rchar += retval;
current->wchar += retval;
}
current->syscr++;
current->syscw++;
if (*ppos > max)
return -EOVERFLOW;
return retval;
}
// now, with exceptions
static ssize_t do_sendfile(int out_fd, int in_fd, loff_t *ppos,
size_t count, loff_t max)
{
loff_t pos;
/*
* Get input file, and verify that it is ok..
*/
light_file_ptr in_file(in_fd);
in_file->verify_readable();
struct inode *in_inode = in_file->dentry()->inode();
if (!in_inode)
throw EINVAL;
// I'm assuming here that the default sendfile() returns -EINVAL
if (!ppos)
ppos = &in_file->f_pos;
else
in_file->verify_preadable();
count = in_file->verify_area(READ, ppos, count);
in_file->security_verify_permission(MAY_READ);
/*
* Get output file, and verify that it is ok..
*/
light_file_ptr out_file(out_fd);
out_file->verify_writable();
// Again, assuming default sendpage returns -EINVAL
struct inode *out_inode = out_file->dentry()->inode();
count = out_file->verify_area(WRITE, &out_file->f_pos, count);
out_file->security_verify_permission(MAY_WRITE);
if (!max)
max = min(in_inode->i_sb->s_maxbytes, out_inode->i_sb->s_maxbytes);
pos = *ppos;
if (unlikely(pos < 0))
throw EINVAL;
if (unlikely(pos + count > max)) {
if (pos >= max)
throw EOVERFLOW;
count = max - pos;
}
count = in_file->sendfile(ppos, count, file_send_actor, out_file);
current->rchar += count;
current->wchar += count;
current->syscr++;
current->syscw++;
if (*ppos > max)
throw EOVERFLOW;
return count;
}
--
Do not meddle in the internals of kernels, for they are subtle and quick to panic.
-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
[Index of Archives]
[Kernel Newbies]
[Netfilter]
[Bugtraq]
[Photo]
[Stuff]
[Gimp]
[Yosemite News]
[MIPS Linux]
[ARM Linux]
[Linux Security]
[Linux RAID]
[Video 4 Linux]
[Linux for the blind]
[Linux Resources]