genode/ports/src/noux/io_channel.h

202 lines
5.3 KiB
C++

/*
* \brief I/O channel
* \author Norman Feske
* \date 2011-02-17
*
* An 'Io_channel' is the interface for the operations on an open file
* descriptor.
*/
/*
* Copyright (C) 2011-2013 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.
*/
#ifndef _NOUX__IO_CHANNEL_H_
#define _NOUX__IO_CHANNEL_H_
/* Genode includes */
#include <base/lock.h>
#include <vfs/file_system.h>
/* Noux includes */
#include <noux_session/sysio.h>
#include <shared_pointer.h>
#include <wake_up_notifier.h>
#include <io_channel_listener.h>
namespace Noux {
class Terminal_io_channel;
extern Genode::Lock &signal_lock();
/**
* Input/output channel backend that is used for calling
* different methos which does not belong to the original
* interface, e.g. network methods.
*/
class Io_channel_backend
{
public:
virtual ~Io_channel_backend() { }
virtual int type() const { return -1; }
};
/**
* Input/output channel interface
*/
class Io_channel : public Reference_counter
{
private:
/**
* List of notifiers (i.e., processes) used by threads that block
* for an I/O-channel event
*/
List<Wake_up_notifier> _notifiers;
Lock _notifiers_lock;
List<Io_channel_listener> _interrupt_handlers;
Lock _interrupt_handlers_lock;
public:
bool close_on_execve;
Io_channel() : close_on_execve(false) { }
virtual ~Io_channel() { }
virtual Io_channel_backend* backend() { return 0; }
virtual bool write(Sysio *sysio, size_t &offset) { return false; }
virtual bool read(Sysio *sysio) { return false; }
virtual bool fstat(Sysio *sysio) { return false; }
virtual bool ftruncate(Sysio *sysio) { return false; }
virtual bool fcntl(Sysio *sysio) { return false; }
virtual bool dirent(Sysio *sysio) { return false; }
virtual bool ioctl(Sysio *sysio) { return false; }
virtual bool lseek(Sysio *sysio) { return false; }
/**
* Return true if an unblocking condition of the channel is satisfied
*
* \param rd if true, check for data available for reading
* \param wr if true, check for readiness for writing
* \param ex if true, check for exceptions
*/
virtual bool check_unblock(bool rd, bool wr, bool ex) const {
return false; }
/**
* Return true if the channel is set to non-blocking mode
*/
virtual bool is_nonblocking() { return false; }
/**
* Register blocker for getting waked up on an I/O channel event
*
* This function is normally called by the to-be-blocked thread
* prior blocking itself, e.g., during a 'select' syscall.
*/
void register_wake_up_notifier(Wake_up_notifier *notifier)
{
Lock::Guard guard(_notifiers_lock);
_notifiers.insert(notifier);
}
/**
* Unregister wake-up notifier
*
* This function is normally called after a blocker has left the
* blocking condition, e.g., during the return from the 'select'
* syscall'.
*/
void unregister_wake_up_notifier(Wake_up_notifier *notifier)
{
Lock::Guard guard(_notifiers_lock);
_notifiers.remove(notifier);
}
/**
* Tell all registered notifiers about an occurred I/O event
*
* This function is called by I/O channel implementations that
* respond to external signals, e.g., the availability of new
* input from a terminal session.
*/
void invoke_all_notifiers()
{
Lock::Guard guard(_notifiers_lock);
for (Wake_up_notifier *n = _notifiers.first(); n; n = n->next())
n->wake_up();
}
/**
* Register interrupt handler
*
* This function is called by Child objects to get woken up if the
* terminal sends, for example, Ctrl-C.
*/
void register_interrupt_handler(Io_channel_listener *handler)
{
Lock::Guard guard(_interrupt_handlers_lock);
_interrupt_handlers.insert(handler);
}
/**
* Unregister interrupt handler
*/
void unregister_interrupt_handler(Io_channel_listener *handler)
{
Lock::Guard guard(_interrupt_handlers_lock);
_interrupt_handlers.remove(handler);
}
/**
* Find the 'Io_channel_listener' object which contains the given
* 'Interrupt_handler' pointer
*/
Io_channel_listener *lookup_io_channel_listener(Interrupt_handler *handler)
{
for (Io_channel_listener *l = _interrupt_handlers.first();
l; l = l->next())
if (l->object() == handler)
return l;
return 0;
}
/**
* Tell all registered handlers about an interrupt event
*/
void invoke_all_interrupt_handlers()
{
Lock::Guard signal_lock_guard(signal_lock());
Lock::Guard guard(_interrupt_handlers_lock);
for (Io_channel_listener *l = _interrupt_handlers.first();
l; l = l->next())
l->object()->handle_interrupt();
}
/**
* Get the path of the file associated with the I/O channel
*
* This function is used to simplify the implemenation of SYSCALL_FSTAT
* and is only implemented by Vfs_io_channel.
*/
virtual bool path(char *path, size_t len) { return false; }
};
}
#endif /* _NOUX__IO_CHANNEL_H_ */