mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-11 05:31:28 +00:00
libc: pipe plugin
A libc plugin which implements pipes using a ring buffer. Fixes #1947
This commit is contained in:
parent
f81867f208
commit
ea726a1f48
@ -235,7 +235,7 @@ set boot_modules {
|
|||||||
freetype.lib.so
|
freetype.lib.so
|
||||||
gallium.lib.so
|
gallium.lib.so
|
||||||
icu.lib.so
|
icu.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -87,7 +87,7 @@ install_config $config
|
|||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer
|
core init timer
|
||||||
nic_drv
|
nic_drv
|
||||||
ld.lib.so libc.lib.so lwip.lib.so libc_lock_pipe.lib.so
|
ld.lib.so libc.lib.so lwip.lib.so libc_pipe.lib.so
|
||||||
tcp_terminal
|
tcp_terminal
|
||||||
test-terminal_echo
|
test-terminal_echo
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,3 @@
|
|||||||
TARGET = tcp_terminal
|
TARGET = tcp_terminal
|
||||||
SRC_CC = main.cc
|
SRC_CC = main.cc
|
||||||
LIBS = libc libc_lwip_nic_dhcp libc_lock_pipe
|
LIBS = libc libc_lwip_nic_dhcp libc_pipe
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
SRC_CC = plugin.cc
|
SRC_CC = plugin.cc
|
||||||
LIBS += libc
|
LIBS += libc
|
||||||
|
|
||||||
vpath %.cc $(REP_DIR)/src/lib/libc_lock_pipe
|
vpath %.cc $(REP_DIR)/src/lib/libc_pipe
|
||||||
|
|
||||||
SHARED_LIB = yes
|
SHARED_LIB = yes
|
@ -35,4 +35,4 @@ INC_DIR += $(REP_DIR)/include/qt5/qtbase/QtCore/private \
|
|||||||
$(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore \
|
$(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore \
|
||||||
$(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore/private
|
$(QT5_CONTRIB_DIR)/qtbase/include/QtCore/$(QT_VERSION)/QtCore/private
|
||||||
|
|
||||||
LIBS += qt5_host_tools launchpad zlib icu libc libm alarm libc_lock_pipe pthread
|
LIBS += qt5_host_tools launchpad zlib icu libc libm alarm libc_pipe pthread
|
||||||
|
41
repos/libports/run/libc_pipe.run
Normal file
41
repos/libports/run/libc_pipe.run
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
build "core init test/libc_pipe"
|
||||||
|
|
||||||
|
create_boot_directory
|
||||||
|
|
||||||
|
install_config {
|
||||||
|
<config>
|
||||||
|
<parent-provides>
|
||||||
|
<service name="ROM"/>
|
||||||
|
<service name="RAM"/>
|
||||||
|
<service name="IRQ"/>
|
||||||
|
<service name="IO_MEM"/>
|
||||||
|
<service name="IO_PORT"/>
|
||||||
|
<service name="CAP"/>
|
||||||
|
<service name="PD"/>
|
||||||
|
<service name="RM"/>
|
||||||
|
<service name="CPU"/>
|
||||||
|
<service name="LOG"/>
|
||||||
|
</parent-provides>
|
||||||
|
<default-route>
|
||||||
|
<any-service> <parent/> <any-child/> </any-service>
|
||||||
|
</default-route>
|
||||||
|
<start name="test-libc_pipe">
|
||||||
|
<resource name="RAM" quantum="4M"/>
|
||||||
|
<config>
|
||||||
|
<libc stdout="/dev/log" stderr="/dev/log">
|
||||||
|
<vfs> <dir name="dev"> <log/> </dir> </vfs>
|
||||||
|
</libc>
|
||||||
|
</config>
|
||||||
|
</start>
|
||||||
|
</config>
|
||||||
|
}
|
||||||
|
|
||||||
|
build_boot_image {
|
||||||
|
core init test-libc_pipe
|
||||||
|
ld.lib.so libc.lib.so libc_pipe.lib.so pthread.lib.so
|
||||||
|
}
|
||||||
|
|
||||||
|
append qemu_args " -nographic -m 64 "
|
||||||
|
|
||||||
|
run_genode_until "child .* exited with exit value 0.*\n" 10
|
||||||
|
|
@ -90,7 +90,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -80,7 +80,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -67,7 +67,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -66,7 +66,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -66,7 +66,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -78,7 +78,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libcrypto.lib.so
|
libcrypto.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
|
@ -70,7 +70,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libcrypto.lib.so
|
libcrypto.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
|
@ -70,7 +70,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libcrypto.lib.so
|
libcrypto.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
|
@ -66,7 +66,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -129,7 +129,7 @@ append boot_modules {
|
|||||||
icu.lib.so
|
icu.lib.so
|
||||||
ld.lib.so
|
ld.lib.so
|
||||||
libc.lib.so
|
libc.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
libm.lib.so
|
libm.lib.so
|
||||||
libpng.lib.so
|
libpng.lib.so
|
||||||
jpeg.lib.so
|
jpeg.lib.so
|
||||||
|
@ -1,22 +1,25 @@
|
|||||||
/*
|
/*
|
||||||
* \brief Pipe plugin implementation
|
* \brief Pipe plugin implementation
|
||||||
* \author Christian Prochaska
|
* \author Christian Prochaska
|
||||||
* \date 2010-03-17
|
* \date 2014-07-11
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (C) 2010-2013 Genode Labs GmbH
|
* Copyright (C) 2014-2016 Genode Labs GmbH
|
||||||
*
|
*
|
||||||
* This file is part of the Genode OS framework, which is distributed
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
* under the terms of the GNU General Public License version 2.
|
* under the terms of the GNU General Public License version 2.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
/* Genode includes */
|
/* Genode includes */
|
||||||
#include <base/env.h>
|
#include <base/env.h>
|
||||||
#include <base/printf.h>
|
#include <base/printf.h>
|
||||||
|
#include <os/ring_buffer.h>
|
||||||
#include <util/misc_math.h>
|
#include <util/misc_math.h>
|
||||||
|
|
||||||
/* libc includes */
|
/* libc includes */
|
||||||
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -30,22 +33,27 @@
|
|||||||
extern void (*libc_select_notify)();
|
extern void (*libc_select_notify)();
|
||||||
|
|
||||||
|
|
||||||
namespace {
|
namespace Libc_pipe {
|
||||||
|
|
||||||
|
using namespace Genode;
|
||||||
|
|
||||||
enum Type { READ_END, WRITE_END };
|
enum Type { READ_END, WRITE_END };
|
||||||
enum { PIPE_BUF_SIZE = 4096 };
|
enum { PIPE_BUF_SIZE = 4096 };
|
||||||
|
|
||||||
|
typedef Ring_buffer<unsigned char, PIPE_BUF_SIZE+1> Pipe_buffer;
|
||||||
|
|
||||||
class Plugin_context : public Libc::Plugin_context
|
class Plugin_context : public Libc::Plugin_context
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
Type _type;
|
Type _type;
|
||||||
char *_buffer;
|
|
||||||
|
Pipe_buffer *_buffer;
|
||||||
|
|
||||||
Libc::File_descriptor *_partner;
|
Libc::File_descriptor *_partner;
|
||||||
Genode::Lock *_lock;
|
Genode::Semaphore *_write_avail_sem;
|
||||||
Genode::Cancelable_lock::State *_lock_state;
|
|
||||||
|
bool _nonblock = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
@ -62,20 +70,13 @@ namespace {
|
|||||||
~Plugin_context();
|
~Plugin_context();
|
||||||
|
|
||||||
Type type() const { return _type; }
|
Type type() const { return _type; }
|
||||||
char *buffer() const { return _buffer; }
|
Pipe_buffer *buffer() const { return _buffer; }
|
||||||
Libc::File_descriptor *partner() const { return _partner; }
|
Libc::File_descriptor *partner() const { return _partner; }
|
||||||
Genode::Lock *lock() const { return _lock; }
|
Genode::Semaphore *write_avail_sem() const { return _write_avail_sem; }
|
||||||
Genode::Cancelable_lock::State *lock_state() { return _lock_state; }
|
bool nonblock() const { return _nonblock; }
|
||||||
|
|
||||||
void set_partner(Libc::File_descriptor *partner)
|
void set_partner(Libc::File_descriptor *partner) { _partner = partner; }
|
||||||
{
|
void set_nonblock(bool nonblock) { _nonblock = nonblock; }
|
||||||
_partner = partner;
|
|
||||||
}
|
|
||||||
|
|
||||||
void set_lock_state(Genode::Cancelable_lock::State lock_state)
|
|
||||||
{
|
|
||||||
*_lock_state = lock_state;
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -88,20 +89,22 @@ namespace {
|
|||||||
*/
|
*/
|
||||||
Plugin();
|
Plugin();
|
||||||
|
|
||||||
bool supports_pipe();
|
bool supports_pipe() override;
|
||||||
bool supports_select(int nfds,
|
bool supports_select(int nfds,
|
||||||
fd_set *readfds,
|
fd_set *readfds,
|
||||||
fd_set *writefds,
|
fd_set *writefds,
|
||||||
fd_set *exceptfds,
|
fd_set *exceptfds,
|
||||||
struct timeval *timeout);
|
struct timeval *timeout) override;
|
||||||
|
|
||||||
int close(Libc::File_descriptor *pipefdo);
|
int close(Libc::File_descriptor *pipefdo) override;
|
||||||
int fcntl(Libc::File_descriptor *pipefdo, int cmd, long arg);
|
int fcntl(Libc::File_descriptor *pipefdo, int cmd, long arg) override;
|
||||||
int pipe(Libc::File_descriptor *pipefdo[2]);
|
int pipe(Libc::File_descriptor *pipefdo[2]) override;
|
||||||
ssize_t read(Libc::File_descriptor *pipefdo, void *buf, ::size_t count);
|
ssize_t read(Libc::File_descriptor *pipefdo, void *buf,
|
||||||
|
::size_t count) override;
|
||||||
int select(int nfds, fd_set *readfds, fd_set *writefds,
|
int select(int nfds, fd_set *readfds, fd_set *writefds,
|
||||||
fd_set *exceptfds, struct timeval *timeout);
|
fd_set *exceptfds, struct timeval *timeout) override;
|
||||||
ssize_t write(Libc::File_descriptor *pipefdo, const void *buf, ::size_t count);
|
ssize_t write(Libc::File_descriptor *pipefdo, const void *buf,
|
||||||
|
::size_t count) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -138,30 +141,15 @@ namespace {
|
|||||||
|
|
||||||
/* allocate shared resources */
|
/* allocate shared resources */
|
||||||
|
|
||||||
_buffer = (char*)malloc(PIPE_BUF_SIZE);
|
_buffer = new (Genode::env()->heap()) Pipe_buffer;
|
||||||
if (!_buffer) {
|
_write_avail_sem = new (Genode::env()->heap()) Genode::Semaphore(PIPE_BUF_SIZE);
|
||||||
PERR("pipe buffer allocation failed");
|
|
||||||
}
|
|
||||||
Genode::memset(_buffer, 0, PIPE_BUF_SIZE);
|
|
||||||
|
|
||||||
_lock_state = new (Genode::env()->heap())
|
|
||||||
Genode::Cancelable_lock::State(Genode::Lock::LOCKED);
|
|
||||||
|
|
||||||
if (!_lock_state) {
|
|
||||||
PERR("pipe lock_state allocation failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
_lock = new (Genode::env()->heap()) Genode::Lock(*_lock_state);
|
|
||||||
if (!_lock) {
|
|
||||||
PERR("pipe lock allocation failed");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* get shared resource pointers from partner */
|
/* get shared resource pointers from partner */
|
||||||
|
|
||||||
_buffer = context(_partner)->buffer();
|
_buffer = context(_partner)->buffer();
|
||||||
_lock_state = context(_partner)->lock_state();
|
_write_avail_sem = context(_partner)->write_avail_sem();
|
||||||
_lock = context(_partner)->lock();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -169,13 +157,15 @@ namespace {
|
|||||||
Plugin_context::~Plugin_context()
|
Plugin_context::~Plugin_context()
|
||||||
{
|
{
|
||||||
if (_partner) {
|
if (_partner) {
|
||||||
|
|
||||||
/* remove the fd this context belongs to from the partner's context */
|
/* remove the fd this context belongs to from the partner's context */
|
||||||
context(_partner)->set_partner(0);
|
context(_partner)->set_partner(0);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* partner fd is already destroyed -> free shared resources */
|
/* partner fd is already destroyed -> free shared resources */
|
||||||
free(_buffer);
|
destroy(Genode::env()->heap(), _buffer);
|
||||||
destroy(Genode::env()->heap(), _lock);
|
destroy(Genode::env()->heap(), _write_avail_sem);
|
||||||
destroy(Genode::env()->heap(), _lock_state);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,15 +197,18 @@ namespace {
|
|||||||
* the sets belongs to this plugin
|
* the sets belongs to this plugin
|
||||||
*/
|
*/
|
||||||
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
|
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
|
||||||
if (FD_ISSET(libc_fd, readfds) || FD_ISSET(libc_fd, writefds)
|
|
||||||
|| FD_ISSET(libc_fd, exceptfds)) {
|
if (FD_ISSET(libc_fd, readfds) ||
|
||||||
|
FD_ISSET(libc_fd, writefds) ||
|
||||||
|
FD_ISSET(libc_fd, exceptfds)) {
|
||||||
|
|
||||||
Libc::File_descriptor *fdo =
|
Libc::File_descriptor *fdo =
|
||||||
Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
|
Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
|
||||||
if (fdo && (fdo->plugin == this)) {
|
|
||||||
|
if (fdo && (fdo->plugin == this))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -232,11 +225,7 @@ namespace {
|
|||||||
int Plugin::fcntl(Libc::File_descriptor *pipefdo, int cmd, long arg)
|
int Plugin::fcntl(Libc::File_descriptor *pipefdo, int cmd, long arg)
|
||||||
{
|
{
|
||||||
switch (cmd) {
|
switch (cmd) {
|
||||||
case F_GETFL:
|
|
||||||
if (is_write_end(pipefdo))
|
|
||||||
return O_WRONLY;
|
|
||||||
else
|
|
||||||
return O_RDONLY;
|
|
||||||
case F_SETFD:
|
case F_SETFD:
|
||||||
{
|
{
|
||||||
const long supported_flags = FD_CLOEXEC;
|
const long supported_flags = FD_CLOEXEC;
|
||||||
@ -247,11 +236,38 @@ namespace {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
default:
|
|
||||||
PERR("fcntl(): command %d arg %ld not supported - pipe",
|
case F_GETFL:
|
||||||
cmd, arg);
|
|
||||||
|
if (is_write_end(pipefdo))
|
||||||
|
return O_WRONLY;
|
||||||
|
else
|
||||||
|
return O_RDONLY;
|
||||||
|
|
||||||
|
case F_SETFL:
|
||||||
|
{
|
||||||
|
constexpr long supported_flags = O_NONBLOCK;
|
||||||
|
|
||||||
|
context(pipefdo)->set_nonblock(arg & O_NONBLOCK);
|
||||||
|
|
||||||
|
if ((arg & ~supported_flags) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* unsupported flags present */
|
||||||
|
|
||||||
|
PERR("%s: command F_SETFL arg %ld not fully supported",
|
||||||
|
__PRETTY_FUNCTION__, arg);
|
||||||
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
|
||||||
|
PERR("%s: command %d arg %ld not supported", __PRETTY_FUNCTION__, cmd, arg);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -271,21 +287,40 @@ namespace {
|
|||||||
{
|
{
|
||||||
if (!is_read_end(fdo)) {
|
if (!is_read_end(fdo)) {
|
||||||
PERR("Cannot read from write end of pipe.");
|
PERR("Cannot read from write end of pipe.");
|
||||||
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
context(fdo)->set_lock_state(Genode::Lock::LOCKED);
|
if (!context(fdo)->partner())
|
||||||
context(fdo)->lock()->lock();
|
|
||||||
|
|
||||||
if ((count > 0) && buf)
|
|
||||||
Genode::memcpy(buf, context(fdo)->buffer(),
|
|
||||||
Genode::min(count, (::size_t)PIPE_BUF_SIZE));
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
if (context(fdo)->nonblock() && context(fdo)->buffer()->empty()) {
|
||||||
|
errno = EAGAIN;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* blocking mode, read at least one byte */
|
||||||
|
|
||||||
|
ssize_t num_bytes_read = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
|
||||||
|
((unsigned char*)buf)[num_bytes_read] =
|
||||||
|
context(fdo)->buffer()->get();
|
||||||
|
|
||||||
|
num_bytes_read++;
|
||||||
|
|
||||||
|
context(fdo)->write_avail_sem()->up();
|
||||||
|
|
||||||
|
} while ((num_bytes_read < (ssize_t)count) &&
|
||||||
|
!context(fdo)->buffer()->empty());
|
||||||
|
|
||||||
|
return num_bytes_read;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* no support for execptfds right now */
|
/* no support for execptfds right now */
|
||||||
|
|
||||||
int Plugin::select(int nfds,
|
int Plugin::select(int nfds,
|
||||||
fd_set *readfds,
|
fd_set *readfds,
|
||||||
fd_set *writefds,
|
fd_set *writefds,
|
||||||
@ -303,6 +338,7 @@ namespace {
|
|||||||
FD_ZERO(exceptfds);
|
FD_ZERO(exceptfds);
|
||||||
|
|
||||||
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
|
for (int libc_fd = 0; libc_fd < nfds; libc_fd++) {
|
||||||
|
|
||||||
fdo = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
|
fdo = Libc::file_descriptor_allocator()->find_by_libc_fd(libc_fd);
|
||||||
|
|
||||||
/* handle only libc_fds that belong to this plugin */
|
/* handle only libc_fds that belong to this plugin */
|
||||||
@ -310,14 +346,15 @@ namespace {
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (FD_ISSET(libc_fd, &in_readfds) &&
|
if (FD_ISSET(libc_fd, &in_readfds) &&
|
||||||
(is_read_end(fdo)) &&
|
is_read_end(fdo) &&
|
||||||
(*context(fdo)->lock_state() == Genode::Lock::UNLOCKED)) {
|
!context(fdo)->buffer()->empty()) {
|
||||||
FD_SET(libc_fd, readfds);
|
FD_SET(libc_fd, readfds);
|
||||||
nready++;
|
nready++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* currently the write end is always ready for writing */
|
if (FD_ISSET(libc_fd, &in_writefds) &&
|
||||||
if (FD_ISSET(libc_fd, &in_writefds)) {
|
is_write_end(fdo) &&
|
||||||
|
(context(fdo)->buffer()->avail_capacity() > 0)) {
|
||||||
FD_SET(libc_fd, writefds);
|
FD_SET(libc_fd, writefds);
|
||||||
nready++;
|
nready++;
|
||||||
}
|
}
|
||||||
@ -331,33 +368,43 @@ namespace {
|
|||||||
{
|
{
|
||||||
if (!is_write_end(fdo)) {
|
if (!is_write_end(fdo)) {
|
||||||
PERR("Cannot write into read end of pipe.");
|
PERR("Cannot write into read end of pipe.");
|
||||||
|
errno = EBADF;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
if (context(fdo)->nonblock() &&
|
||||||
* Currently each 'write()' overwrites the previous
|
(context(fdo)->buffer()->avail_capacity() == 0)) {
|
||||||
* content of the pipe buffer.
|
errno = EAGAIN;
|
||||||
*/
|
return -1;
|
||||||
if ((count > 0) && buf)
|
}
|
||||||
Genode::memcpy(context(fdo)->buffer(), buf,
|
|
||||||
Genode::min(count, (::size_t)PIPE_BUF_SIZE));
|
|
||||||
|
|
||||||
context(fdo)->set_lock_state(Genode::Lock::UNLOCKED);
|
::size_t num_bytes_written = 0;
|
||||||
context(fdo)->lock()->unlock();
|
while (num_bytes_written < count) {
|
||||||
|
|
||||||
|
if (context(fdo)->buffer()->avail_capacity() == 0) {
|
||||||
|
|
||||||
|
if (context(fdo)->nonblock())
|
||||||
|
return num_bytes_written;
|
||||||
|
|
||||||
|
if (libc_select_notify)
|
||||||
|
libc_select_notify();
|
||||||
|
}
|
||||||
|
|
||||||
|
context(fdo)->write_avail_sem()->down();
|
||||||
|
|
||||||
|
context(fdo)->buffer()->add(((unsigned char*)buf)[num_bytes_written]);
|
||||||
|
num_bytes_written++;
|
||||||
|
}
|
||||||
|
|
||||||
if (libc_select_notify)
|
if (libc_select_notify)
|
||||||
libc_select_notify();
|
libc_select_notify();
|
||||||
|
|
||||||
return 0;
|
return num_bytes_written;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
} /* unnamed namespace */
|
void __attribute__((constructor)) init_libc_pipe()
|
||||||
|
|
||||||
|
|
||||||
void __attribute__((constructor)) init_libc_lock_pipe()
|
|
||||||
{
|
{
|
||||||
PDBG("init_libc_lock_pipe()\n");
|
static Libc_pipe::Plugin plugin;
|
||||||
static Plugin plugin;
|
|
||||||
}
|
}
|
||||||
|
|
89
repos/libports/src/test/libc_pipe/main.cc
Normal file
89
repos/libports/src/test/libc_pipe/main.cc
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
* \brief libc_pipe test
|
||||||
|
* \author Christian Prochaska
|
||||||
|
* \date 2016-04-24
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2016 Genode Labs GmbH
|
||||||
|
*
|
||||||
|
* This file is part of the Genode OS framework, which is distributed
|
||||||
|
* under the terms of the GNU General Public License version 2.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* libc includes */
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
|
||||||
|
enum { BUF_SIZE = 16*1024 };
|
||||||
|
static char buf[BUF_SIZE];
|
||||||
|
|
||||||
|
static int pipefd[2];
|
||||||
|
|
||||||
|
static volatile bool reader_finished = false;
|
||||||
|
|
||||||
|
void *read_pipe(void *arg)
|
||||||
|
{
|
||||||
|
static char read_buf[BUF_SIZE];
|
||||||
|
|
||||||
|
ssize_t num_bytes_read = 0;
|
||||||
|
|
||||||
|
while (num_bytes_read < BUF_SIZE) {
|
||||||
|
|
||||||
|
ssize_t res = read(pipefd[0],
|
||||||
|
&read_buf[num_bytes_read],
|
||||||
|
BUF_SIZE - num_bytes_read);
|
||||||
|
|
||||||
|
if (res < 0) {
|
||||||
|
fprintf(stderr, "Error reading from pipe\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
num_bytes_read += res;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((read_buf[0] != buf[0]) ||
|
||||||
|
(read_buf[BUF_SIZE - 1] != buf[BUF_SIZE - 1])) {
|
||||||
|
fprintf(stderr, "Error: data mismatch\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
reader_finished = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
/* test values */
|
||||||
|
buf[0] = 1;
|
||||||
|
buf[BUF_SIZE - 1] = 255;
|
||||||
|
|
||||||
|
int res = pipe(pipefd);
|
||||||
|
if (res != 0) {
|
||||||
|
fprintf(stderr, "Error creating pipe\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_t tid;
|
||||||
|
pthread_create(&tid, 0, read_pipe, 0);
|
||||||
|
|
||||||
|
ssize_t bytes_written = write(pipefd[1], buf, BUF_SIZE);
|
||||||
|
|
||||||
|
if (bytes_written != BUF_SIZE) {
|
||||||
|
fprintf(stderr, "Error writing to pipe");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* pthread_join() is not implemented at this time */
|
||||||
|
while (!reader_finished) { }
|
||||||
|
|
||||||
|
printf("--- test finished ---\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
3
repos/libports/src/test/libc_pipe/target.mk
Normal file
3
repos/libports/src/test/libc_pipe/target.mk
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
TARGET = test-libc_pipe
|
||||||
|
LIBS = libc libc_pipe pthread
|
||||||
|
SRC_CC = main.cc
|
@ -228,7 +228,7 @@ in the form of a separate shared library. Please make sure to integrate those
|
|||||||
shared libraries along with the dynamic linker (ld.lib.so) in your boot image.
|
shared libraries along with the dynamic linker (ld.lib.so) in your boot image.
|
||||||
They are 'libc.lib.so' (the libc), 'libc_log.lib.so' (for printing the LOG
|
They are 'libc.lib.so' (the libc), 'libc_log.lib.so' (for printing the LOG
|
||||||
output of GDB monitor to core's LOG service), 'libc_terminal.lib.so' (to
|
output of GDB monitor to core's LOG service), 'libc_terminal.lib.so' (to
|
||||||
connect with GDB), and 'libc_lock_pipe.lib.so' (used for synchronizing threads
|
connect with GDB), and 'libc_pipe.lib.so' (used for synchronizing threads
|
||||||
via 'select' and 'pipe'). For using the TCP terminal, 'lwip.lib.so' (TCP/IP
|
via 'select' and 'pipe'). For using the TCP terminal, 'lwip.lib.so' (TCP/IP
|
||||||
stack) is needed as well.
|
stack) is needed as well.
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ append boot_modules {
|
|||||||
libc.lib.so libm.lib.so lwip.lib.so
|
libc.lib.so libm.lib.so lwip.lib.so
|
||||||
zlib.lib.so libpng.lib.so jpeg.lib.so libssl.lib.so libcrypto.lib.so
|
zlib.lib.so libpng.lib.so jpeg.lib.so libssl.lib.so libcrypto.lib.so
|
||||||
freetype.lib.so
|
freetype.lib.so
|
||||||
libc_lock_pipe.lib.so
|
libc_pipe.lib.so
|
||||||
stdcxx.lib.so
|
stdcxx.lib.so
|
||||||
nitpicker_plugin.tar
|
nitpicker_plugin.tar
|
||||||
}
|
}
|
||||||
|
@ -115,7 +115,7 @@ install_config $config
|
|||||||
# generic modules
|
# generic modules
|
||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer
|
core init timer
|
||||||
ld.lib.so libc.lib.so libc_lock_pipe.lib.so libc_terminal.lib.so
|
ld.lib.so libc.lib.so libc_pipe.lib.so libc_terminal.lib.so
|
||||||
uart_drv
|
uart_drv
|
||||||
gdb_monitor
|
gdb_monitor
|
||||||
nitpicker pointer scout
|
nitpicker pointer scout
|
||||||
|
@ -88,7 +88,7 @@ install_config $config
|
|||||||
# generic modules
|
# generic modules
|
||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer
|
core init timer
|
||||||
ld.lib.so libc.lib.so libc_lock_pipe.lib.so libc_terminal.lib.so
|
ld.lib.so libc.lib.so libc_pipe.lib.so libc_terminal.lib.so
|
||||||
uart_drv
|
uart_drv
|
||||||
gdb_monitor test-gdb_monitor
|
gdb_monitor test-gdb_monitor
|
||||||
}
|
}
|
||||||
|
@ -77,7 +77,7 @@ install_config $config
|
|||||||
# generic modules
|
# generic modules
|
||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer
|
core init timer
|
||||||
ld.lib.so libc.lib.so libc_lock_pipe.lib.so libc_terminal.lib.so
|
ld.lib.so libc.lib.so libc_pipe.lib.so libc_terminal.lib.so
|
||||||
uart_drv
|
uart_drv
|
||||||
gdb_monitor test-gdb_monitor
|
gdb_monitor test-gdb_monitor
|
||||||
}
|
}
|
||||||
|
@ -71,7 +71,7 @@ install_config $config
|
|||||||
# generic modules
|
# generic modules
|
||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer
|
core init timer
|
||||||
ld.lib.so libc.lib.so libc_log.lib.so libc_lock_pipe.lib.so libc_terminal.lib.so
|
ld.lib.so libc.lib.so libc_log.lib.so libc_pipe.lib.so libc_terminal.lib.so
|
||||||
uart_drv
|
uart_drv
|
||||||
gdb_monitor test-gdb_monitor_target_config
|
gdb_monitor test-gdb_monitor_target_config
|
||||||
}
|
}
|
||||||
|
@ -206,7 +206,7 @@ install_config $config
|
|||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer ld.lib.so noux terminal terminal_crosslink
|
core init timer ld.lib.so noux terminal terminal_crosslink
|
||||||
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
|
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
|
||||||
libc_lock_pipe.lib.so libc_terminal.lib.so
|
libc_pipe.lib.so libc_terminal.lib.so
|
||||||
gdb_monitor test-gdb_monitor
|
gdb_monitor test-gdb_monitor
|
||||||
gdb.tar test-gdb_monitor.tar test-gdb_monitor-src.tar
|
gdb.tar test-gdb_monitor.tar test-gdb_monitor-src.tar
|
||||||
}
|
}
|
||||||
|
@ -140,7 +140,7 @@ exec cp ${genode_dir}/repos/os/src/app/cli_monitor/gdb_command_config bin
|
|||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer ld.lib.so noux terminal_mux terminal_crosslink
|
core init timer ld.lib.so noux terminal_mux terminal_crosslink
|
||||||
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
|
libc.lib.so libm.lib.so libc_noux.lib.so ncurses.lib.so expat.lib.so
|
||||||
libc_lock_pipe.lib.so libc_log.lib.so libc_terminal.lib.so
|
libc_pipe.lib.so libc_log.lib.so libc_terminal.lib.so
|
||||||
cli_monitor gdb_monitor terminal_log gdb.tar
|
cli_monitor gdb_monitor terminal_log gdb.tar
|
||||||
gdb_command_config
|
gdb_command_config
|
||||||
gdb_target.tar
|
gdb_target.tar
|
||||||
|
@ -159,7 +159,7 @@ install_config $config
|
|||||||
# generic modules
|
# generic modules
|
||||||
set boot_modules {
|
set boot_modules {
|
||||||
core init timer tcp_terminal nic_bridge
|
core init timer tcp_terminal nic_bridge
|
||||||
ld.lib.so noux_net libc.lib.so libm.lib.so libc_lock_pipe.lib.so
|
ld.lib.so noux_net libc.lib.so libm.lib.so libc_pipe.lib.so
|
||||||
libc_resolv.lib.so libc_noux.lib.so lwip.lib.so noux_netcat.tar
|
libc_resolv.lib.so libc_noux.lib.so lwip.lib.so noux_netcat.tar
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ lappend_if [have_spec linux] boot_modules fb_sdl
|
|||||||
lappend_if [have_spec x86] boot_modules rtc_drv
|
lappend_if [have_spec x86] boot_modules rtc_drv
|
||||||
|
|
||||||
append boot_modules {
|
append boot_modules {
|
||||||
ld.lib.so libc.lib.so libm.lib.so pthread.lib.so libc_lock_pipe.lib.so
|
ld.lib.so libc.lib.so libm.lib.so pthread.lib.so libc_pipe.lib.so
|
||||||
libc_terminal.lib.so libiconv.lib.so stdcxx.lib.so
|
libc_terminal.lib.so libiconv.lib.so stdcxx.lib.so
|
||||||
qemu-usb.lib.so
|
qemu-usb.lib.so
|
||||||
}
|
}
|
||||||
|
@ -229,7 +229,7 @@ append boot_modules {
|
|||||||
core init timer
|
core init timer
|
||||||
part_blk ahci_drv fs_rom
|
part_blk ahci_drv fs_rom
|
||||||
ld.lib.so libc.lib.so libm.lib.so pthread.lib.so
|
ld.lib.so libc.lib.so libm.lib.so pthread.lib.so
|
||||||
libc_lock_pipe.lib.so libc_terminal.lib.so
|
libc_pipe.lib.so libc_terminal.lib.so
|
||||||
libiconv.lib.so stdcxx.lib.so
|
libiconv.lib.so stdcxx.lib.so
|
||||||
rump.lib.so rump_fs.lib.so rump_fs
|
rump.lib.so rump_fs.lib.so rump_fs
|
||||||
virtualbox qemu-usb.lib.so
|
virtualbox qemu-usb.lib.so
|
||||||
|
@ -10,7 +10,7 @@ INC_DIR += $(GDB_CONTRIB_DIR)/include \
|
|||||||
$(PRG_DIR)/gdbserver \
|
$(PRG_DIR)/gdbserver \
|
||||||
$(PRG_DIR)
|
$(PRG_DIR)
|
||||||
|
|
||||||
LIBS = libc libc_terminal libc_lock_pipe \
|
LIBS = libc libc_terminal libc_pipe \
|
||||||
gdbserver_platform gdbserver_libc_support
|
gdbserver_platform gdbserver_libc_support
|
||||||
|
|
||||||
SRC_C = event-loop.c \
|
SRC_C = event-loop.c \
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
TARGET = openvpn
|
TARGET = openvpn
|
||||||
|
|
||||||
LIBS += libc libc_lock_pipe libc_lwip_nic_dhcp \
|
LIBS += libc libc_pipe libc_lwip_nic_dhcp \
|
||||||
libcrypto libssl config_args server
|
libcrypto libssl config_args server
|
||||||
|
|
||||||
OPENVPN_PORT_DIR := $(call select_from_ports,openvpn)
|
OPENVPN_PORT_DIR := $(call select_from_ports,openvpn)
|
||||||
|
@ -23,7 +23,7 @@ LIBS += virtualbox-bios virtualbox-recompiler virtualbox-runtime \
|
|||||||
virtualbox-storage virtualbox-zlib virtualbox-liblzf \
|
virtualbox-storage virtualbox-zlib virtualbox-liblzf \
|
||||||
virtualbox-hwaccl virtualbox-xml virtualbox-main
|
virtualbox-hwaccl virtualbox-xml virtualbox-main
|
||||||
|
|
||||||
LIBS += pthread libc_terminal libc_lock_pipe libiconv
|
LIBS += pthread libc_terminal libc_pipe libiconv
|
||||||
|
|
||||||
LIBS += qemu-usb
|
LIBS += qemu-usb
|
||||||
|
|
||||||
|
@ -8,6 +8,7 @@ tar_rom
|
|||||||
noux
|
noux
|
||||||
noux_net_netcat
|
noux_net_netcat
|
||||||
libc_ffat
|
libc_ffat
|
||||||
|
libc_pipe
|
||||||
libc_vfs
|
libc_vfs
|
||||||
libc_vfs_ram
|
libc_vfs_ram
|
||||||
libc_vfs_fs
|
libc_vfs_fs
|
||||||
|
Loading…
x
Reference in New Issue
Block a user