OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [nio/] [EpollSelectorImpl.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* EpollSelectorImpl.java -- selector implementation using epoll
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.nio;
40
 
41
import gnu.classpath.Configuration;
42
 
43
import java.io.IOException;
44
import java.nio.ByteBuffer;
45
import java.nio.channels.SelectableChannel;
46
import java.nio.channels.SelectionKey;
47
import java.nio.channels.Selector;
48
import java.nio.channels.spi.AbstractSelectableChannel;
49
import java.nio.channels.spi.AbstractSelector;
50
import java.nio.channels.spi.SelectorProvider;
51
import java.util.Collections;
52
import java.util.HashMap;
53
import java.util.HashSet;
54
import java.util.Iterator;
55
import java.util.Set;
56
 
57
/**
58
 * An implementation of {@link Selector} that uses the epoll event
59
 * notification mechanism on GNU/Linux.
60
 *
61
 * @author Casey Marshall (csm@gnu.org)
62
 */
63
public class EpollSelectorImpl extends AbstractSelector
64
{
65
  // XXX is this reasonable? Does it matter?
66
  private static final int DEFAULT_EPOLL_SIZE = 128;
67
  private static final int sizeof_struct_epoll_event;
68
 
69
  private static final int OP_ACCEPT  = SelectionKey.OP_ACCEPT;
70
  private static final int OP_CONNECT = SelectionKey.OP_CONNECT;
71
  private static final int OP_READ    = SelectionKey.OP_READ;
72
  private static final int OP_WRITE   = SelectionKey.OP_WRITE;
73
 
74
  /** our epoll file descriptor. */
75
  private int epoll_fd;
76
 
77
  private final HashMap keys;
78
  private Set selectedKeys;
79
  private Thread waitingThread;
80
  private ByteBuffer events;
81
 
82
  private static final int INITIAL_CAPACITY;
83
  private static final int MAX_DOUBLING_CAPACITY;
84
  private static final int CAPACITY_INCREMENT;
85
 
86
  static
87
  {
88
    if (Configuration.INIT_LOAD_LIBRARY)
89
      System.loadLibrary("javanio");
90
 
91
    if (epoll_supported())
92
      sizeof_struct_epoll_event = sizeof_struct();
93
    else
94
      sizeof_struct_epoll_event = -1;
95
 
96
    INITIAL_CAPACITY = 64 * sizeof_struct_epoll_event;
97
    MAX_DOUBLING_CAPACITY = 1024 * sizeof_struct_epoll_event;
98
    CAPACITY_INCREMENT = 128 * sizeof_struct_epoll_event;
99
  }
100
 
101
  public EpollSelectorImpl(SelectorProvider provider)
102
    throws IOException
103
  {
104
    super(provider);
105
    epoll_fd = epoll_create(DEFAULT_EPOLL_SIZE);
106
    keys = new HashMap();
107
    selectedKeys = null;
108
    events = ByteBuffer.allocateDirect(INITIAL_CAPACITY);
109
  }
110
 
111
  /* (non-Javadoc)
112
   * @see java.nio.channels.Selector#keys()
113
   */
114
  public Set keys()
115
  {
116
    return new HashSet(keys.values());
117
  }
118
 
119
  /* (non-Javadoc)
120
   * @see java.nio.channels.Selector#select()
121
   */
122
  public int select() throws IOException
123
  {
124
    return doSelect(-1);
125
  }
126
 
127
  /* (non-Javadoc)
128
   * @see java.nio.channels.Selector#select(long)
129
   */
130
  public int select(long timeout) throws IOException
131
  {
132
    if (timeout > Integer.MAX_VALUE)
133
      throw new IllegalArgumentException("timeout is too large");
134
    if (timeout < 0)
135
      throw new IllegalArgumentException("invalid timeout");
136
    return doSelect((int) timeout);
137
  }
138
 
139
  private int doSelect(int timeout) throws IOException
140
  {
141
    synchronized (keys)
142
    {
143
      Set cancelledKeys = cancelledKeys();
144
      synchronized (cancelledKeys)
145
      {
146
        for (Iterator it = cancelledKeys.iterator(); it.hasNext(); )
147
          {
148
            EpollSelectionKeyImpl key = (EpollSelectionKeyImpl) it.next();
149
            epoll_delete(epoll_fd, key.fd);
150
            key.valid = false;
151
            keys.remove(Integer.valueOf(key.fd));
152
            it.remove();
153
            deregister(key);
154
          }
155
 
156
        // Clear out closed channels. The fds are removed from the epoll
157
        // fd when closed, so there is no need to remove them manually.
158
        for (Iterator it = keys.values().iterator(); it.hasNext(); )
159
          {
160
            EpollSelectionKeyImpl key = (EpollSelectionKeyImpl) it.next();
161
            SelectableChannel ch = key.channel();
162
            if (ch instanceof VMChannelOwner)
163
              {
164
                if (!((VMChannelOwner) ch).getVMChannel().getState().isValid())
165
                  it.remove();
166
              }
167
          }
168
 
169
        // Don't bother if we have nothing to select.
170
        if (keys.isEmpty())
171
          return 0;
172
 
173
        int ret;
174
        try
175
          {
176
            begin();
177
            waitingThread = Thread.currentThread();
178
            ret = epoll_wait(epoll_fd, events, keys.size(), timeout);
179
          }
180
        finally
181
          {
182
            Thread.interrupted();
183
            waitingThread = null;
184
            end();
185
          }
186
 
187
        HashSet s = new HashSet(ret);
188
        for (int i = 0; i < ret; i++)
189
          {
190
            events.position(i * sizeof_struct_epoll_event);
191
            ByteBuffer b = events.slice();
192
            int fd = selected_fd(b);
193
            EpollSelectionKeyImpl key
194
              = (EpollSelectionKeyImpl) keys.get(Integer.valueOf(fd));
195
            if (key == null)
196
              throw new IOException("fd was selected, but no key found");
197
            key.selectedOps = selected_ops(b) & key.interestOps;
198
            s.add(key);
199
          }
200
 
201
        reallocateBuffer();
202
 
203
        selectedKeys = s;
204
        return ret;
205
      }
206
    }
207
  }
208
 
209
  /* (non-Javadoc)
210
   * @see java.nio.channels.Selector#selectedKeys()
211
   */
212
  public Set selectedKeys()
213
  {
214
    if (selectedKeys == null)
215
      return Collections.EMPTY_SET;
216
    return selectedKeys;
217
  }
218
 
219
  /* (non-Javadoc)
220
   * @see java.nio.channels.Selector#selectNow()
221
   */
222
  public int selectNow() throws IOException
223
  {
224
    return doSelect(0);
225
  }
226
 
227
  /* (non-Javadoc)
228
   * @see java.nio.channels.Selector#wakeup()
229
   */
230
  public Selector wakeup()
231
  {
232
    try
233
      {
234
        waitingThread.interrupt();
235
      }
236
    catch (NullPointerException npe)
237
      {
238
        // Ignored, thrown if we are not in a blocking op.
239
      }
240
    return this;
241
  }
242
 
243
  /* (non-Javadoc)
244
   * @see java.nio.channels.spi.AbstractSelector#implCloseSelector()
245
   */
246
  protected void implCloseSelector() throws IOException
247
  {
248
    VMChannel.close(epoll_fd);
249
  }
250
 
251
  /* (non-Javadoc)
252
   * @see java.nio.channels.spi.AbstractSelector#register(java.nio.channels.spi.AbstractSelectableChannel, int, java.lang.Object)
253
   */
254
  protected SelectionKey register(AbstractSelectableChannel ch, int ops, Object att)
255
  {
256
    if (!(ch instanceof VMChannelOwner))
257
      throw new IllegalArgumentException("unsupported channel type");
258
 
259
    VMChannel channel = ((VMChannelOwner) ch).getVMChannel();
260
    try
261
      {
262
        int native_fd = channel.getState().getNativeFD();
263
        synchronized (keys)
264
        {
265
          if (keys.containsKey(Integer.valueOf(native_fd)))
266
            throw new IllegalArgumentException("channel already registered");
267
          EpollSelectionKeyImpl result =
268
            new EpollSelectionKeyImpl(this, ch, native_fd);
269
          if ((ops & ~(ch.validOps())) != 0)
270
            throw new IllegalArgumentException("invalid ops for channel");
271
          result.interestOps = ops;
272
          result.selectedOps = 0;
273
          result.valid = true;
274
          result.attach(att);
275
          result.key = System.identityHashCode(result);
276
          epoll_add(epoll_fd, result.fd, ops);
277
          keys.put(Integer.valueOf(native_fd), result);
278
          reallocateBuffer();
279
          return result;
280
        }
281
      }
282
    catch (IOException ioe)
283
      {
284
        throw new IllegalArgumentException(ioe);
285
      }
286
  }
287
 
288
  private void reallocateBuffer()
289
  {
290
    // Ensure we have enough space for all potential events that may be
291
    // returned.
292
    if (events.capacity() < keys.size() * sizeof_struct_epoll_event)
293
      {
294
        int cap = events.capacity();
295
        if (cap < MAX_DOUBLING_CAPACITY)
296
          cap <<= 1;
297
        else
298
          cap += CAPACITY_INCREMENT;
299
        events = ByteBuffer.allocateDirect(cap);
300
      }
301
    // Ensure that the events buffer is not too large, given the number of
302
    // events registered.
303
    else if (events.capacity() > keys.size() * sizeof_struct_epoll_event * 2 + 1
304
             && events.capacity() > INITIAL_CAPACITY)
305
      {
306
        int cap = events.capacity() >>> 1;
307
        events = ByteBuffer.allocateDirect(cap);
308
      }
309
  }
310
 
311
  void epoll_modify(EpollSelectionKeyImpl key, int ops) throws IOException
312
  {
313
    epoll_modify(epoll_fd, key.fd, ops);
314
  }
315
 
316
  /**
317
   * Tell if epoll is supported by this system, and support was compiled in.
318
   *
319
   * @return True if this system supports event notification with epoll.
320
   */
321
  public static native boolean epoll_supported();
322
 
323
 
324
  /**
325
   * Returns the size of `struct epoll_event'.
326
   *
327
   * @return The size of `struct epoll_event'.
328
   */
329
  private static native int sizeof_struct();
330
 
331
 
332
  /**
333
   * Open a new epoll file descriptor.
334
   *
335
   * @param size The size hint for the new epoll descriptor.
336
   * @return The new file descriptor integer.
337
   * @throws IOException If allocating a new epoll descriptor fails.
338
   */
339
  private static native int epoll_create(int size) throws IOException;
340
 
341
  /**
342
   * Add a file descriptor to this selector.
343
   *
344
   * @param efd The epoll file descriptor.
345
   * @param fd  The file descriptor to add (or modify).
346
   * @param ops The interest opts.
347
   */
348
  private static native void epoll_add(int efd, int fd, int ops)
349
    throws IOException;
350
 
351
  /**
352
   * Modify the interest ops of the key selecting for the given FD.
353
   *
354
   * @param efd The epoll file descriptor.
355
   * @param fd  The file descriptor to modify.
356
   * @param ops The ops.
357
   * @throws IOException
358
   */
359
  private static native void epoll_modify(int efd, int fd, int ops)
360
    throws IOException;
361
 
362
  /**
363
   * Remove a file descriptor from this selector.
364
   *
365
   * @param efd The epoll file descriptor.
366
   * @param fd  The file descriptor.
367
   * @throws IOException
368
   */
369
  private static native void epoll_delete(int efd, int fd) throws IOException;
370
 
371
  /**
372
   * Select events.
373
   *
374
   * @param efd     The epoll file descriptor.
375
   * @param state   The buffer to hold selected events.
376
   * @param n       The number of events that may be put in `state'.
377
   * @param timeout The timeout.
378
   * @return The number of events selected.
379
   * @throws IOException
380
   */
381
  private static native int epoll_wait(int efd, ByteBuffer state, int n, int timeout)
382
    throws IOException;
383
 
384
  /**
385
   * Fetch the fd value from a selected struct epoll_event.
386
   *
387
   * @param struct The direct buffer holding the struct.
388
   * @return The fd value.
389
   */
390
  private static native int selected_fd(ByteBuffer struct);
391
 
392
  /**
393
   * Fetch the enabled operations from a selected struct epoll_event.
394
   *
395
   * @param struct The direct buffer holding the struct.
396
   * @return The selected operations.
397
   */
398
  private static native int selected_ops(ByteBuffer struct);
399
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.