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

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libgo/] [go/] [net/] [fd.go] - Blame information for rev 848

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 747 jeremybenn
// Copyright 2009 The Go Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style
3
// license that can be found in the LICENSE file.
4
 
5
// +build darwin freebsd linux netbsd openbsd
6
 
7
package net
8
 
9
import (
10
        "io"
11
        "os"
12
        "sync"
13
        "syscall"
14
        "time"
15
)
16
 
17
// Network file descriptor.
18
type netFD struct {
19
        // locking/lifetime of sysfd
20
        sysmu   sync.Mutex
21
        sysref  int
22
        closing bool
23
 
24
        // immutable until Close
25
        sysfd       int
26
        family      int
27
        sotype      int
28
        isConnected bool
29
        sysfile     *os.File
30
        cr          chan bool
31
        cw          chan bool
32
        net         string
33
        laddr       Addr
34
        raddr       Addr
35
 
36
        // owned by client
37
        rdeadline int64
38
        rio       sync.Mutex
39
        wdeadline int64
40
        wio       sync.Mutex
41
 
42
        // owned by fd wait server
43
        ncr, ncw int
44
}
45
 
46
// A pollServer helps FDs determine when to retry a non-blocking
47
// read or write after they get EAGAIN.  When an FD needs to wait,
48
// send the fd on s.cr (for a read) or s.cw (for a write) to pass the
49
// request to the poll server.  Then receive on fd.cr/fd.cw.
50
// When the pollServer finds that i/o on FD should be possible
51
// again, it will send fd on fd.cr/fd.cw to wake any waiting processes.
52
// This protocol is implemented as s.WaitRead() and s.WaitWrite().
53
//
54
// There is one subtlety: when sending on s.cr/s.cw, the
55
// poll server is probably in a system call, waiting for an fd
56
// to become ready.  It's not looking at the request channels.
57
// To resolve this, the poll server waits not just on the FDs it has
58
// been given but also its own pipe.  After sending on the
59
// buffered channel s.cr/s.cw, WaitRead/WaitWrite writes a
60
// byte to the pipe, causing the pollServer's poll system call to
61
// return.  In response to the pipe being readable, the pollServer
62
// re-polls its request channels.
63
//
64
// Note that the ordering is "send request" and then "wake up server".
65
// If the operations were reversed, there would be a race: the poll
66
// server might wake up and look at the request channel, see that it
67
// was empty, and go back to sleep, all before the requester managed
68
// to send the request.  Because the send must complete before the wakeup,
69
// the request channel must be buffered.  A buffer of size 1 is sufficient
70
// for any request load.  If many processes are trying to submit requests,
71
// one will succeed, the pollServer will read the request, and then the
72
// channel will be empty for the next process's request.  A larger buffer
73
// might help batch requests.
74
//
75
// To avoid races in closing, all fd operations are locked and
76
// refcounted. when netFD.Close() is called, it calls syscall.Shutdown
77
// and sets a closing flag. Only when the last reference is removed
78
// will the fd be closed.
79
 
80
type pollServer struct {
81
        cr, cw     chan *netFD // buffered >= 1
82
        pr, pw     *os.File
83
        poll       *pollster // low-level OS hooks
84
        sync.Mutex           // controls pending and deadline
85
        pending    map[int]*netFD
86
        deadline   int64 // next deadline (nsec since 1970)
87
}
88
 
89
func (s *pollServer) AddFD(fd *netFD, mode int) {
90
        intfd := fd.sysfd
91
        if intfd < 0 {
92
                // fd closed underfoot
93
                if mode == 'r' {
94
                        fd.cr <- true
95
                } else {
96
                        fd.cw <- true
97
                }
98
                return
99
        }
100
 
101
        s.Lock()
102
 
103
        var t int64
104
        key := intfd << 1
105
        if mode == 'r' {
106
                fd.ncr++
107
                t = fd.rdeadline
108
        } else {
109
                fd.ncw++
110
                key++
111
                t = fd.wdeadline
112
        }
113
        s.pending[key] = fd
114
        doWakeup := false
115
        if t > 0 && (s.deadline == 0 || t < s.deadline) {
116
                s.deadline = t
117
                doWakeup = true
118
        }
119
 
120
        wake, err := s.poll.AddFD(intfd, mode, false)
121
        if err != nil {
122
                panic("pollServer AddFD " + err.Error())
123
        }
124
        if wake {
125
                doWakeup = true
126
        }
127
 
128
        s.Unlock()
129
 
130
        if doWakeup {
131
                s.Wakeup()
132
        }
133
}
134
 
135
var wakeupbuf [1]byte
136
 
137
func (s *pollServer) Wakeup() { s.pw.Write(wakeupbuf[0:]) }
138
 
139
func (s *pollServer) LookupFD(fd int, mode int) *netFD {
140
        key := fd << 1
141
        if mode == 'w' {
142
                key++
143
        }
144
        netfd, ok := s.pending[key]
145
        if !ok {
146
                return nil
147
        }
148
        delete(s.pending, key)
149
        return netfd
150
}
151
 
152
func (s *pollServer) WakeFD(fd *netFD, mode int) {
153
        if mode == 'r' {
154
                for fd.ncr > 0 {
155
                        fd.ncr--
156
                        fd.cr <- true
157
                }
158
        } else {
159
                for fd.ncw > 0 {
160
                        fd.ncw--
161
                        fd.cw <- true
162
                }
163
        }
164
}
165
 
166
func (s *pollServer) Now() int64 {
167
        return time.Now().UnixNano()
168
}
169
 
170
func (s *pollServer) CheckDeadlines() {
171
        now := s.Now()
172
        // TODO(rsc): This will need to be handled more efficiently,
173
        // probably with a heap indexed by wakeup time.
174
 
175
        var next_deadline int64
176
        for key, fd := range s.pending {
177
                var t int64
178
                var mode int
179
                if key&1 == 0 {
180
                        mode = 'r'
181
                } else {
182
                        mode = 'w'
183
                }
184
                if mode == 'r' {
185
                        t = fd.rdeadline
186
                } else {
187
                        t = fd.wdeadline
188
                }
189
                if t > 0 {
190
                        if t <= now {
191
                                delete(s.pending, key)
192
                                if mode == 'r' {
193
                                        s.poll.DelFD(fd.sysfd, mode)
194
                                        fd.rdeadline = -1
195
                                } else {
196
                                        s.poll.DelFD(fd.sysfd, mode)
197
                                        fd.wdeadline = -1
198
                                }
199
                                s.WakeFD(fd, mode)
200
                        } else if next_deadline == 0 || t < next_deadline {
201
                                next_deadline = t
202
                        }
203
                }
204
        }
205
        s.deadline = next_deadline
206
}
207
 
208
func (s *pollServer) Run() {
209
        var scratch [100]byte
210
        s.Lock()
211
        defer s.Unlock()
212
        for {
213
                var t = s.deadline
214
                if t > 0 {
215
                        t = t - s.Now()
216
                        if t <= 0 {
217
                                s.CheckDeadlines()
218
                                continue
219
                        }
220
                }
221
                fd, mode, err := s.poll.WaitFD(s, t)
222
                if err != nil {
223
                        print("pollServer WaitFD: ", err.Error(), "\n")
224
                        return
225
                }
226
                if fd < 0 {
227
                        // Timeout happened.
228
                        s.CheckDeadlines()
229
                        continue
230
                }
231
                if fd == s.pr.Fd() {
232
                        // Drain our wakeup pipe (we could loop here,
233
                        // but it's unlikely that there are more than
234
                        // len(scratch) wakeup calls).
235
                        s.pr.Read(scratch[0:])
236
                        s.CheckDeadlines()
237
                } else {
238
                        netfd := s.LookupFD(fd, mode)
239
                        if netfd == nil {
240
                                print("pollServer: unexpected wakeup for fd=", fd, " mode=", string(mode), "\n")
241
                                continue
242
                        }
243
                        s.WakeFD(netfd, mode)
244
                }
245
        }
246
}
247
 
248
func (s *pollServer) WaitRead(fd *netFD) {
249
        s.AddFD(fd, 'r')
250
        <-fd.cr
251
}
252
 
253
func (s *pollServer) WaitWrite(fd *netFD) {
254
        s.AddFD(fd, 'w')
255
        <-fd.cw
256
}
257
 
258
// Network FD methods.
259
// All the network FDs use a single pollServer.
260
 
261
var pollserver *pollServer
262
var onceStartServer sync.Once
263
 
264
func startServer() {
265
        p, err := newPollServer()
266
        if err != nil {
267
                print("Start pollServer: ", err.Error(), "\n")
268
        }
269
        pollserver = p
270
}
271
 
272
func newFD(fd, family, sotype int, net string) (*netFD, error) {
273
        onceStartServer.Do(startServer)
274
        if err := syscall.SetNonblock(fd, true); err != nil {
275
                return nil, err
276
        }
277
        netfd := &netFD{
278
                sysfd:  fd,
279
                family: family,
280
                sotype: sotype,
281
                net:    net,
282
        }
283
        netfd.cr = make(chan bool, 1)
284
        netfd.cw = make(chan bool, 1)
285
        return netfd, nil
286
}
287
 
288
func (fd *netFD) setAddr(laddr, raddr Addr) {
289
        fd.laddr = laddr
290
        fd.raddr = raddr
291
        var ls, rs string
292
        if laddr != nil {
293
                ls = laddr.String()
294
        }
295
        if raddr != nil {
296
                rs = raddr.String()
297
        }
298
        fd.sysfile = os.NewFile(fd.sysfd, fd.net+":"+ls+"->"+rs)
299
}
300
 
301
func (fd *netFD) connect(ra syscall.Sockaddr) error {
302
        err := syscall.Connect(fd.sysfd, ra)
303
        if err == syscall.EINPROGRESS {
304
                pollserver.WaitWrite(fd)
305
                var e int
306
                e, err = syscall.GetsockoptInt(fd.sysfd, syscall.SOL_SOCKET, syscall.SO_ERROR)
307
                if err != nil {
308
                        return os.NewSyscallError("getsockopt", err)
309
                }
310
                if e != 0 {
311
                        err = syscall.Errno(e)
312
                }
313
        }
314
        return err
315
}
316
 
317
// Add a reference to this fd.
318
func (fd *netFD) incref() {
319
        fd.sysmu.Lock()
320
        fd.sysref++
321
        fd.sysmu.Unlock()
322
}
323
 
324
// Remove a reference to this FD and close if we've been asked to do so (and
325
// there are no references left.
326
func (fd *netFD) decref() {
327
        fd.sysmu.Lock()
328
        fd.sysref--
329
        if fd.closing && fd.sysref == 0 && fd.sysfd >= 0 {
330
                // In case the user has set linger, switch to blocking mode so
331
                // the close blocks.  As long as this doesn't happen often, we
332
                // can handle the extra OS processes.  Otherwise we'll need to
333
                // use the pollserver for Close too.  Sigh.
334
                syscall.SetNonblock(fd.sysfd, false)
335
                fd.sysfile.Close()
336
                fd.sysfile = nil
337
                fd.sysfd = -1
338
        }
339
        fd.sysmu.Unlock()
340
}
341
 
342
func (fd *netFD) Close() error {
343
        if fd == nil || fd.sysfile == nil {
344
                return os.EINVAL
345
        }
346
 
347
        fd.incref()
348
        syscall.Shutdown(fd.sysfd, syscall.SHUT_RDWR)
349
        fd.closing = true
350
        fd.decref()
351
        return nil
352
}
353
 
354
func (fd *netFD) shutdown(how int) error {
355
        if fd == nil || fd.sysfile == nil {
356
                return os.EINVAL
357
        }
358
        err := syscall.Shutdown(fd.sysfd, how)
359
        if err != nil {
360
                return &OpError{"shutdown", fd.net, fd.laddr, err}
361
        }
362
        return nil
363
}
364
 
365
func (fd *netFD) CloseRead() error {
366
        return fd.shutdown(syscall.SHUT_RD)
367
}
368
 
369
func (fd *netFD) CloseWrite() error {
370
        return fd.shutdown(syscall.SHUT_WR)
371
}
372
 
373
func (fd *netFD) Read(p []byte) (n int, err error) {
374
        if fd == nil {
375
                return 0, os.EINVAL
376
        }
377
        fd.rio.Lock()
378
        defer fd.rio.Unlock()
379
        fd.incref()
380
        defer fd.decref()
381
        if fd.sysfile == nil {
382
                return 0, os.EINVAL
383
        }
384
        for {
385
                n, err = syscall.Read(fd.sysfile.Fd(), p)
386
                if err == syscall.EAGAIN {
387
                        if fd.rdeadline >= 0 {
388
                                pollserver.WaitRead(fd)
389
                                continue
390
                        }
391
                        err = errTimeout
392
                }
393
                if err != nil {
394
                        n = 0
395
                } else if n == 0 && err == nil && fd.sotype != syscall.SOCK_DGRAM {
396
                        err = io.EOF
397
                }
398
                break
399
        }
400
        if err != nil && err != io.EOF {
401
                err = &OpError{"read", fd.net, fd.raddr, err}
402
        }
403
        return
404
}
405
 
406
func (fd *netFD) ReadFrom(p []byte) (n int, sa syscall.Sockaddr, err error) {
407
        if fd == nil || fd.sysfile == nil {
408
                return 0, nil, os.EINVAL
409
        }
410
        fd.rio.Lock()
411
        defer fd.rio.Unlock()
412
        fd.incref()
413
        defer fd.decref()
414
        for {
415
                n, sa, err = syscall.Recvfrom(fd.sysfd, p, 0)
416
                if err == syscall.EAGAIN {
417
                        if fd.rdeadline >= 0 {
418
                                pollserver.WaitRead(fd)
419
                                continue
420
                        }
421
                        err = errTimeout
422
                }
423
                if err != nil {
424
                        n = 0
425
                }
426
                break
427
        }
428
        if err != nil {
429
                err = &OpError{"read", fd.net, fd.laddr, err}
430
        }
431
        return
432
}
433
 
434
func (fd *netFD) ReadMsg(p []byte, oob []byte) (n, oobn, flags int, sa syscall.Sockaddr, err error) {
435
        if fd == nil || fd.sysfile == nil {
436
                return 0, 0, 0, nil, os.EINVAL
437
        }
438
        fd.rio.Lock()
439
        defer fd.rio.Unlock()
440
        fd.incref()
441
        defer fd.decref()
442
        for {
443
                n, oobn, flags, sa, err = syscall.Recvmsg(fd.sysfd, p, oob, 0)
444
                if err == syscall.EAGAIN {
445
                        if fd.rdeadline >= 0 {
446
                                pollserver.WaitRead(fd)
447
                                continue
448
                        }
449
                        err = errTimeout
450
                }
451
                if err == nil && n == 0 {
452
                        err = io.EOF
453
                }
454
                break
455
        }
456
        if err != nil && err != io.EOF {
457
                err = &OpError{"read", fd.net, fd.laddr, err}
458
                return
459
        }
460
        return
461
}
462
 
463
func (fd *netFD) Write(p []byte) (int, error) {
464
        if fd == nil {
465
                return 0, os.EINVAL
466
        }
467
        fd.wio.Lock()
468
        defer fd.wio.Unlock()
469
        fd.incref()
470
        defer fd.decref()
471
        if fd.sysfile == nil {
472
                return 0, os.EINVAL
473
        }
474
 
475
        var err error
476
        nn := 0
477
        for {
478
                var n int
479
                n, err = syscall.Write(fd.sysfile.Fd(), p[nn:])
480
                if n > 0 {
481
                        nn += n
482
                }
483
                if nn == len(p) {
484
                        break
485
                }
486
                if err == syscall.EAGAIN {
487
                        if fd.wdeadline >= 0 {
488
                                pollserver.WaitWrite(fd)
489
                                continue
490
                        }
491
                        err = errTimeout
492
                }
493
                if err != nil {
494
                        n = 0
495
                        break
496
                }
497
                if n == 0 {
498
                        err = io.ErrUnexpectedEOF
499
                        break
500
                }
501
        }
502
        if err != nil {
503
                err = &OpError{"write", fd.net, fd.raddr, err}
504
        }
505
        return nn, err
506
}
507
 
508
func (fd *netFD) WriteTo(p []byte, sa syscall.Sockaddr) (n int, err error) {
509
        if fd == nil || fd.sysfile == nil {
510
                return 0, os.EINVAL
511
        }
512
        fd.wio.Lock()
513
        defer fd.wio.Unlock()
514
        fd.incref()
515
        defer fd.decref()
516
        for {
517
                err = syscall.Sendto(fd.sysfd, p, 0, sa)
518
                if err == syscall.EAGAIN {
519
                        if fd.wdeadline >= 0 {
520
                                pollserver.WaitWrite(fd)
521
                                continue
522
                        }
523
                        err = errTimeout
524
                }
525
                break
526
        }
527
        if err == nil {
528
                n = len(p)
529
        } else {
530
                err = &OpError{"write", fd.net, fd.raddr, err}
531
        }
532
        return
533
}
534
 
535
func (fd *netFD) WriteMsg(p []byte, oob []byte, sa syscall.Sockaddr) (n int, oobn int, err error) {
536
        if fd == nil || fd.sysfile == nil {
537
                return 0, 0, os.EINVAL
538
        }
539
        fd.wio.Lock()
540
        defer fd.wio.Unlock()
541
        fd.incref()
542
        defer fd.decref()
543
        for {
544
                err = syscall.Sendmsg(fd.sysfd, p, oob, sa, 0)
545
                if err == syscall.EAGAIN {
546
                        if fd.wdeadline >= 0 {
547
                                pollserver.WaitWrite(fd)
548
                                continue
549
                        }
550
                        err = errTimeout
551
                }
552
                break
553
        }
554
        if err == nil {
555
                n = len(p)
556
                oobn = len(oob)
557
        } else {
558
                err = &OpError{"write", fd.net, fd.raddr, err}
559
        }
560
        return
561
}
562
 
563
func (fd *netFD) accept(toAddr func(syscall.Sockaddr) Addr) (netfd *netFD, err error) {
564
        if fd == nil || fd.sysfile == nil {
565
                return nil, os.EINVAL
566
        }
567
 
568
        fd.incref()
569
        defer fd.decref()
570
 
571
        // See ../syscall/exec.go for description of ForkLock.
572
        // It is okay to hold the lock across syscall.Accept
573
        // because we have put fd.sysfd into non-blocking mode.
574
        var s int
575
        var rsa syscall.Sockaddr
576
        for {
577
                if fd.closing {
578
                        return nil, os.EINVAL
579
                }
580
                syscall.ForkLock.RLock()
581
                s, rsa, err = syscall.Accept(fd.sysfd)
582
                if err != nil {
583
                        syscall.ForkLock.RUnlock()
584
                        if err == syscall.EAGAIN {
585
                                if fd.rdeadline >= 0 {
586
                                        pollserver.WaitRead(fd)
587
                                        continue
588
                                }
589
                                err = errTimeout
590
                        }
591
                        return nil, &OpError{"accept", fd.net, fd.laddr, err}
592
                }
593
                break
594
        }
595
        syscall.CloseOnExec(s)
596
        syscall.ForkLock.RUnlock()
597
 
598
        if netfd, err = newFD(s, fd.family, fd.sotype, fd.net); err != nil {
599
                syscall.Close(s)
600
                return nil, err
601
        }
602
        lsa, _ := syscall.Getsockname(netfd.sysfd)
603
        netfd.setAddr(toAddr(lsa), toAddr(rsa))
604
        return netfd, nil
605
}
606
 
607
func (fd *netFD) dup() (f *os.File, err error) {
608
        ns, err := syscall.Dup(fd.sysfd)
609
        if err != nil {
610
                return nil, &OpError{"dup", fd.net, fd.laddr, err}
611
        }
612
 
613
        // We want blocking mode for the new fd, hence the double negative.
614
        if err = syscall.SetNonblock(ns, false); err != nil {
615
                return nil, &OpError{"setnonblock", fd.net, fd.laddr, err}
616
        }
617
 
618
        return os.NewFile(ns, fd.sysfile.Name()), nil
619
}
620
 
621
func closesocket(s int) error {
622
        return syscall.Close(s)
623
}

powered by: WebSVN 2.1.0

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