mirror of
https://gitlab.com/sortix/sortix.git
synced 2023-02-13 20:55:38 -05:00
Add poll(2) and ppoll(2).
This commit is contained in:
parent
e76073cc4f
commit
b2b55bc34a
18 changed files with 601 additions and 1 deletions
|
@ -189,6 +189,8 @@ on_exit.o \
|
|||
openat.o \
|
||||
open.o \
|
||||
pipe.o \
|
||||
poll.o \
|
||||
ppoll.o \
|
||||
print.o \
|
||||
putc.o \
|
||||
raise.o \
|
||||
|
|
46
libc/include/poll.h
Normal file
46
libc/include/poll.h
Normal file
|
@ -0,0 +1,46 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
poll.h
|
||||
Input/output multiplexing.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef _POLL_H
|
||||
#define _POLL_H 1
|
||||
|
||||
#include <features.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
@include(time_t.h)
|
||||
|
||||
__END_DECLS
|
||||
#include <sortix/poll.h>
|
||||
#include <sortix/sigset.h>
|
||||
#include <sortix/timespec.h>
|
||||
__BEGIN_DECLS
|
||||
|
||||
int poll(struct pollfd* fds, nfds_t nfds, int timeout);
|
||||
int ppoll(struct pollfd* fds, nfds_t nfds, const struct timespec* timeout,
|
||||
const sigset_t* sigmask);
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
34
libc/poll.cpp
Normal file
34
libc/poll.cpp
Normal file
|
@ -0,0 +1,34 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
poll.cpp
|
||||
Input/output multiplexing.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <poll.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern "C" int poll(struct pollfd* fds, nfds_t nfds, int timeout)
|
||||
{
|
||||
struct timespec ts;
|
||||
ts.tv_sec = timeout;
|
||||
ts.tv_nsec = 0;
|
||||
return ppoll(fds, nfds, &ts, NULL);
|
||||
}
|
36
libc/ppoll.cpp
Normal file
36
libc/ppoll.cpp
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of the Sortix C Library.
|
||||
|
||||
The Sortix C Library is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU Lesser General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or (at your
|
||||
option) any later version.
|
||||
|
||||
The Sortix C Library is distributed in the hope that it will be useful, but
|
||||
WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
|
||||
License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public License
|
||||
along with the Sortix C Library. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
ppoll.cpp
|
||||
Input/output multiplexing.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/syscall.h>
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
DEFN_SYSCALL4(int, sys_ppoll, SYSCALL_PPOLL, struct pollfd*, nfds_t,
|
||||
const struct timespec*, const sigset_t*);
|
||||
|
||||
extern "C" int ppoll(struct pollfd* fds, nfds_t nfds,
|
||||
const struct timespec* timeout, const sigset_t* sigmask)
|
||||
{
|
||||
return sys_ppoll(fds, nfds, timeout, sigmask);
|
||||
}
|
|
@ -106,6 +106,7 @@ mtable.o \
|
|||
panic.o \
|
||||
pci.o \
|
||||
pipe.o \
|
||||
poll.o \
|
||||
process.o \
|
||||
refcount.o \
|
||||
scheduler.o \
|
||||
|
|
|
@ -416,4 +416,9 @@ int Descriptor::gettermmode(ioctx_t* ctx, unsigned* mode)
|
|||
return vnode->gettermmode(ctx, mode);
|
||||
}
|
||||
|
||||
int Descriptor::poll(ioctx_t* ctx, PollNode* node)
|
||||
{
|
||||
return vnode->poll(ctx, node);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -213,6 +213,7 @@ public:
|
|||
virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws);
|
||||
virtual int settermmode(ioctx_t* ctx, unsigned mode);
|
||||
virtual int gettermmode(ioctx_t* ctx, unsigned* mode);
|
||||
virtual int poll(ioctx_t* ctx, PollNode* node);
|
||||
|
||||
private:
|
||||
bool SendMessage(Channel* channel, size_t type, void* ptr, size_t size,
|
||||
|
@ -1115,6 +1116,11 @@ int Unode::gettermmode(ioctx_t* ctx, unsigned* mode)
|
|||
return ret;
|
||||
}
|
||||
|
||||
int Unode::poll(ioctx_t* /*ctx*/, PollNode* /*node*/)
|
||||
{
|
||||
return errno = ENOTSUP, -1;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialization.
|
||||
//
|
||||
|
|
|
@ -41,6 +41,7 @@ struct kernel_dirent;
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
class PollNode;
|
||||
class Inode;
|
||||
class Vnode;
|
||||
struct ioctx_struct;
|
||||
|
@ -77,6 +78,7 @@ public:
|
|||
int tcgetwinsize(ioctx_t* ctx, struct winsize* ws);
|
||||
int settermmode(ioctx_t* ctx, unsigned mode);
|
||||
int gettermmode(ioctx_t* ctx, unsigned* mode);
|
||||
int poll(ioctx_t* ctx, PollNode* node);
|
||||
|
||||
private:
|
||||
Ref<Descriptor> open_elem(ioctx_t* ctx, const char* filename, int flags,
|
||||
|
|
|
@ -41,6 +41,7 @@ struct kernel_dirent;
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
class PollNode;
|
||||
struct ioctx_struct;
|
||||
typedef struct ioctx_struct ioctx_t;
|
||||
|
||||
|
@ -87,6 +88,7 @@ public:
|
|||
virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws) = 0;
|
||||
virtual int settermmode(ioctx_t* ctx, unsigned mode) = 0;
|
||||
virtual int gettermmode(ioctx_t* ctx, unsigned* mode) = 0;
|
||||
virtual int poll(ioctx_t* ctx, PollNode* node) = 0;
|
||||
|
||||
};
|
||||
|
||||
|
@ -151,6 +153,7 @@ public:
|
|||
virtual int tcgetwinsize(ioctx_t* ctx, struct winsize* ws);
|
||||
virtual int settermmode(ioctx_t* ctx, unsigned mode);
|
||||
virtual int gettermmode(ioctx_t* ctx, unsigned* mode);
|
||||
virtual int poll(ioctx_t* ctx, PollNode* node);
|
||||
|
||||
};
|
||||
|
||||
|
|
83
sortix/include/sortix/kernel/poll.h
Normal file
83
sortix/include/sortix/kernel/poll.h
Normal file
|
@ -0,0 +1,83 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/kernel/poll.h
|
||||
Kernel declarations for event polling.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_SORTIX_KERNEL_POLL_H
|
||||
#define INCLUDE_SORTIX_KERNEL_POLL_H
|
||||
|
||||
#include <sortix/kernel/kthread.h>
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
class PollChannel;
|
||||
class PollNode;
|
||||
|
||||
class PollChannel
|
||||
{
|
||||
public:
|
||||
PollChannel();
|
||||
~PollChannel();
|
||||
void Signal(short events);
|
||||
void Register(PollNode* node);
|
||||
void Unregister(PollNode* node);
|
||||
|
||||
private:
|
||||
void SignalUnlocked(short events);
|
||||
|
||||
private:
|
||||
struct PollNode* first;
|
||||
struct PollNode* last;
|
||||
kthread_mutex_t channel_lock;
|
||||
kthread_cond_t no_pending_cond;
|
||||
|
||||
};
|
||||
|
||||
class PollNode
|
||||
{
|
||||
friend class PollChannel;
|
||||
|
||||
public:
|
||||
PollNode() { next = NULL; prev = NULL; channel = NULL; }
|
||||
|
||||
private:
|
||||
PollNode* next;
|
||||
PollNode* prev;
|
||||
|
||||
public:
|
||||
PollChannel* channel;
|
||||
|
||||
public:
|
||||
kthread_mutex_t* wake_mutex;
|
||||
kthread_cond_t* wake_cond;
|
||||
short events;
|
||||
short revents;
|
||||
bool* woken;
|
||||
|
||||
public:
|
||||
void Cancel();
|
||||
|
||||
};
|
||||
|
||||
} // namespace Sortix
|
||||
|
||||
#endif
|
|
@ -34,6 +34,7 @@ struct kernel_dirent;
|
|||
|
||||
namespace Sortix {
|
||||
|
||||
class PollNode;
|
||||
class Inode;
|
||||
struct ioctx_struct;
|
||||
typedef struct ioctx_struct ioctx_t;
|
||||
|
@ -74,6 +75,7 @@ public:
|
|||
int tcgetwinsize(ioctx_t* ctx, struct winsize* ws);
|
||||
int settermmode(ioctx_t* ctx, unsigned mode);
|
||||
int gettermmode(ioctx_t* ctx, unsigned* mode);
|
||||
int poll(ioctx_t* ctx, PollNode* node);
|
||||
|
||||
public /*TODO: private*/:
|
||||
Ref<Inode> inode;
|
||||
|
|
57
sortix/include/sortix/poll.h
Normal file
57
sortix/include/sortix/poll.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
sortix/poll.h
|
||||
Interface for waiting on file descriptor events.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef INCLUDE_SORTIX_POLL_H
|
||||
#define INCLUDE_SORTIX_POLL_H
|
||||
|
||||
#include <features.h>
|
||||
|
||||
__BEGIN_DECLS
|
||||
|
||||
typedef unsigned long int nfds_t;
|
||||
|
||||
struct pollfd
|
||||
{
|
||||
int fd;
|
||||
short events;
|
||||
short revents;
|
||||
};
|
||||
|
||||
#define POLLERR (1<<0)
|
||||
#define POLLHUP (1<<1)
|
||||
#define POLLNVAL (1<<2)
|
||||
|
||||
#define POLLIN (1<<3)
|
||||
#define POLLRDNORM (1<<4)
|
||||
#define POLLRDBAND (1<<5)
|
||||
#define POLLPRI (1<<6)
|
||||
#define POLLOUT (1<<7)
|
||||
#define POLLWRNORM (1<<8)
|
||||
#define POLLWRBAND (1<<9)
|
||||
|
||||
#define POLL__ONLY_REVENTS (POLLERR | POLLHUP | POLLNVAL)
|
||||
|
||||
__END_DECLS
|
||||
|
||||
#endif
|
|
@ -93,6 +93,7 @@
|
|||
#define SYSCALL_FCHMODAT 69
|
||||
#define SYSCALL_LINKAT 70
|
||||
#define SYSCALL_FSM_FSBIND 71
|
||||
#define SYSCALL_MAX_NUM 72 /* index of highest constant + 1 */
|
||||
#define SYSCALL_PPOLL 72
|
||||
#define SYSCALL_MAX_NUM 73 /* index of highest constant + 1 */
|
||||
|
||||
#endif
|
||||
|
|
|
@ -267,4 +267,18 @@ int AbstractInode::gettermmode(ioctx_t* /*ctx*/, unsigned* /*mode*/)
|
|||
return errno = ENOTTY, -1;
|
||||
}
|
||||
|
||||
int AbstractInode::poll(ioctx_t* /*ctx*/, PollNode* /*node*/)
|
||||
{
|
||||
#if 0 // TODO: Support poll on regular files as per POSIX.
|
||||
if ( inode_type == INODE_TYPE_FILE )
|
||||
{
|
||||
// TODO: Correct bits?
|
||||
node->revents |= (POLLIN | POLLOUT) & node->events;
|
||||
// TODO: What if not listening on events (POLLIN | POLLOUT)?
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return errno = ENOTSUP, -1;
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
|
@ -73,6 +73,7 @@
|
|||
#include "io.h"
|
||||
#include "pipe.h"
|
||||
#include "interrupt.h"
|
||||
#include "poll.h"
|
||||
#include "dispmsg.h"
|
||||
#include "fs/kram.h"
|
||||
#include "fs/user.h"
|
||||
|
@ -396,6 +397,9 @@ static void BootThread(void* /*user*/)
|
|||
// Initialize the pipe system.
|
||||
Pipe::Init();
|
||||
|
||||
// Initialize poll system call.
|
||||
Poll::Init();
|
||||
|
||||
// Initialize the kernel information query syscall.
|
||||
Info::Init();
|
||||
|
||||
|
|
263
sortix/poll.cpp
Normal file
263
sortix/poll.cpp
Normal file
|
@ -0,0 +1,263 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
poll.cpp
|
||||
Interface for waiting on file descriptor events.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include <sortix/poll.h>
|
||||
#include <sortix/sigset.h>
|
||||
#include <sortix/syscallnum.h>
|
||||
#include <sortix/timespec.h>
|
||||
|
||||
#include <sortix/kernel/platform.h>
|
||||
#include <sortix/kernel/kthread.h>
|
||||
#include <sortix/kernel/copy.h>
|
||||
#include <sortix/kernel/descriptor.h>
|
||||
#include <sortix/kernel/ioctx.h>
|
||||
#include <sortix/kernel/poll.h>
|
||||
|
||||
#include "syscall.h"
|
||||
#include "process.h"
|
||||
#include "poll.h"
|
||||
|
||||
namespace Sortix {
|
||||
|
||||
PollChannel::PollChannel()
|
||||
{
|
||||
first = NULL;
|
||||
last = NULL;
|
||||
channel_lock = KTHREAD_MUTEX_INITIALIZER;
|
||||
no_pending_cond = KTHREAD_COND_INITIALIZER;
|
||||
}
|
||||
|
||||
PollChannel::~PollChannel()
|
||||
{
|
||||
ScopedLock lock(&channel_lock);
|
||||
// TODO: Is this the correct error to signal with?
|
||||
SignalUnlocked(POLLHUP);
|
||||
// Note: We can't stop early in case of a signal, because that would mean
|
||||
// other threads are still using our data, and since this is the destructor,
|
||||
// leaving early _will_ cause data corruption. Luckily, this loop will
|
||||
// terminate because everyone is now woken up and will cancel, which is what
|
||||
// we wait for to finish. No new requests can come, since we are the
|
||||
// destructor - whoever owns this object is no longer using it.
|
||||
while ( first )
|
||||
kthread_cond_wait(&no_pending_cond, &channel_lock);
|
||||
}
|
||||
|
||||
void PollChannel::Signal(short events)
|
||||
{
|
||||
ScopedLock lock(&channel_lock);
|
||||
SignalUnlocked(events);
|
||||
}
|
||||
|
||||
void PollChannel::SignalUnlocked(short events)
|
||||
{
|
||||
for ( PollNode* node = first; node; node = node->next )
|
||||
if ( node->revents |= events & (node->events | POLL__ONLY_REVENTS) )
|
||||
{
|
||||
ScopedLock node_lock(node->wake_mutex);
|
||||
if ( !*node->woken )
|
||||
{
|
||||
*node->woken = true;
|
||||
kthread_cond_signal(node->wake_cond);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PollChannel::Register(PollNode* node)
|
||||
{
|
||||
ScopedLock lock(&channel_lock);
|
||||
node->channel = this;
|
||||
if ( !first )
|
||||
first = last = node,
|
||||
node->next = node->prev = NULL;
|
||||
else
|
||||
node->next = NULL,
|
||||
node->prev = last,
|
||||
last->next = node,
|
||||
last = node;
|
||||
}
|
||||
|
||||
void PollChannel::Unregister(PollNode* node)
|
||||
{
|
||||
ScopedLock lock(&channel_lock);
|
||||
node->channel = NULL;
|
||||
if ( node->prev )
|
||||
node->prev->next = node->next;
|
||||
else
|
||||
first = node->next;
|
||||
if ( node->next )
|
||||
node->next->prev = node->prev;
|
||||
else
|
||||
last = node->prev;
|
||||
if ( !first )
|
||||
kthread_cond_signal(&no_pending_cond);
|
||||
}
|
||||
|
||||
void PollNode::Cancel()
|
||||
{
|
||||
if ( channel )
|
||||
channel->Unregister(this);
|
||||
}
|
||||
|
||||
namespace Poll {
|
||||
|
||||
static struct pollfd* CopyFdsFromUser(struct pollfd* user_fds, nfds_t nfds)
|
||||
{
|
||||
size_t size = sizeof(struct pollfd) * nfds;
|
||||
struct pollfd* fds = new struct pollfd[nfds];
|
||||
if ( !fds )
|
||||
return NULL;
|
||||
if ( !CopyFromUser(fds, user_fds, size) )
|
||||
{
|
||||
delete[] fds;
|
||||
return NULL;
|
||||
}
|
||||
return fds;
|
||||
}
|
||||
|
||||
static bool CopyFdsToUser(struct pollfd* user_fds,
|
||||
const struct pollfd* kernel_fds, nfds_t nfds)
|
||||
{
|
||||
size_t size = sizeof(struct pollfd) * nfds;
|
||||
return CopyToUser(user_fds, kernel_fds, size);
|
||||
}
|
||||
|
||||
static bool FetchTimespec(struct timespec* dest, const struct timespec* user)
|
||||
{
|
||||
if ( !user )
|
||||
dest->tv_sec = -1,
|
||||
dest->tv_nsec = 0;
|
||||
else if ( !CopyFromUser(dest, user, sizeof(*dest)) )
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int sys_ppoll(struct pollfd* user_fds, nfds_t nfds,
|
||||
const struct timespec* user_timeout_ts,
|
||||
const sigset_t* user_sigmask)
|
||||
{
|
||||
ioctx_t ctx; SetupKernelIOCtx(&ctx);
|
||||
|
||||
struct timespec timeout_ts;
|
||||
if ( !FetchTimespec(&timeout_ts, user_timeout_ts) )
|
||||
return -1;
|
||||
|
||||
if ( 0 < timeout_ts.tv_sec || timeout_ts.tv_nsec || user_sigmask )
|
||||
return errno = ENOSYS, -1;
|
||||
|
||||
struct pollfd* fds = CopyFdsFromUser(user_fds, nfds);
|
||||
if ( !fds ) { return -1; }
|
||||
|
||||
PollNode* nodes = new PollNode[nfds];
|
||||
if ( !nodes ) { delete[] fds; return -1; }
|
||||
|
||||
Process* process = CurrentProcess();
|
||||
|
||||
kthread_mutex_t wakeup_mutex = KTHREAD_MUTEX_INITIALIZER;
|
||||
kthread_cond_t wakeup_cond = KTHREAD_COND_INITIALIZER;
|
||||
|
||||
kthread_mutex_lock(&wakeup_mutex);
|
||||
|
||||
int ret = -1;
|
||||
bool self_woken = false;
|
||||
volatile bool remote_woken = false;
|
||||
bool unexpected_error = false;
|
||||
|
||||
nfds_t reqs = nfds;
|
||||
for ( reqs = 0; !unexpected_error && reqs < nfds; reqs++ )
|
||||
{
|
||||
PollNode* node = nodes + reqs;
|
||||
if ( fds[reqs].fd < 0 )
|
||||
{
|
||||
fds[reqs].revents = POLLNVAL;
|
||||
// TODO: Should we set POLLNVAL in node->revents too? Should this
|
||||
// system call ignore this error and keep polling, or return to
|
||||
// user-space immediately? What if conditions are already true on
|
||||
// some of the file descriptors (those we have processed so far?)?
|
||||
node->revents = 0;
|
||||
continue;
|
||||
}
|
||||
Ref<Descriptor> desc = process->GetDescriptor(fds[reqs].fd);
|
||||
if ( !desc ) { unexpected_error = true; break; }
|
||||
node->events = fds[reqs].events;
|
||||
node->revents = 0;
|
||||
node->wake_mutex = &wakeup_mutex;
|
||||
node->wake_cond = &wakeup_cond;
|
||||
node->woken = (bool*) &remote_woken;
|
||||
// TODO: How should erors be handled?
|
||||
if ( desc->poll(&ctx, node) == 0 )
|
||||
self_woken = true;
|
||||
else if ( errno != EAGAIN )
|
||||
unexpected_error = self_woken = true;
|
||||
}
|
||||
|
||||
if ( timeout_ts.tv_sec < 0 )
|
||||
self_woken = true;
|
||||
|
||||
while ( !(self_woken || remote_woken) )
|
||||
{
|
||||
if ( !kthread_cond_wait_signal(&wakeup_cond, &wakeup_mutex) )
|
||||
errno = -EINTR,
|
||||
self_woken = true;
|
||||
}
|
||||
|
||||
kthread_mutex_unlock(&wakeup_mutex);
|
||||
|
||||
for ( nfds_t i = 0; i < reqs; i++ )
|
||||
nodes[i].Cancel();
|
||||
|
||||
if ( !unexpected_error )
|
||||
{
|
||||
int num_events = 0;
|
||||
for ( nfds_t i = 0; i < reqs; i++ )
|
||||
{
|
||||
if ( fds[i].fd < -1 )
|
||||
continue;
|
||||
if ( (fds[i].revents = nodes[i].revents) )
|
||||
num_events++;
|
||||
}
|
||||
|
||||
if ( CopyFdsToUser(user_fds, fds, nfds) )
|
||||
ret = num_events;
|
||||
}
|
||||
|
||||
delete[] nodes;
|
||||
delete[] fds;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Init()
|
||||
{
|
||||
Syscall::Register(SYSCALL_PPOLL, (void*) sys_ppoll);
|
||||
}
|
||||
|
||||
} // namespace Poll
|
||||
|
||||
} // namespace Sortix
|
36
sortix/poll.h
Normal file
36
sortix/poll.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/*******************************************************************************
|
||||
|
||||
Copyright(C) Jonas 'Sortie' Termansen 2012.
|
||||
|
||||
This file is part of Sortix.
|
||||
|
||||
Sortix is free software: you can redistribute it and/or modify it under the
|
||||
terms of the GNU General Public License as published by the Free Software
|
||||
Foundation, either version 3 of the License, or (at your option) any later
|
||||
version.
|
||||
|
||||
Sortix is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
||||
FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
|
||||
details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along with
|
||||
Sortix. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
poll.h
|
||||
Interface for waiting on file descriptor events.
|
||||
|
||||
*******************************************************************************/
|
||||
|
||||
#ifndef SORTIX_POLL_H
|
||||
#define SORTIX_POLL_H
|
||||
|
||||
namespace Sortix {
|
||||
namespace Poll {
|
||||
|
||||
void Init();
|
||||
|
||||
} // nanmespace Poll
|
||||
} // namespace Sortix
|
||||
|
||||
#endif
|
|
@ -213,4 +213,9 @@ int Vnode::gettermmode(ioctx_t* ctx, unsigned* mode)
|
|||
return inode->gettermmode(ctx, mode);
|
||||
}
|
||||
|
||||
int Vnode::poll(ioctx_t* ctx, PollNode* node)
|
||||
{
|
||||
return inode->poll(ctx, node);
|
||||
}
|
||||
|
||||
} // namespace Sortix
|
||||
|
|
Loading…
Reference in a new issue