| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 | |
| 5 package system | |
| 6 | |
| 7 import ( | |
| 8 "runtime" | |
| 9 "sync" | |
| 10 ) | |
| 11 | |
| 12 // core is an instance of the Mojo system APIs implementation. | |
| 13 var core coreImpl | |
| 14 | |
| 15 // Core is an interface giving access to the base operations. | |
| 16 // See |mojo/public/c/include/mojo/system/*.h| for the underlying API. | |
| 17 type Core interface { | |
| 18 // AcquireNativeHandle acquires a handle from the native side. The handl
e | |
| 19 // will be owned by the returned object and must not be closed outside o
f | |
| 20 // it. | |
| 21 AcquireNativeHandle(handle MojoHandle) UntypedHandle | |
| 22 | |
| 23 // GetTimeTicksNow returns a monotonically increasing platform dependent | |
| 24 // tick count representing "right now". Resolution depends on the system | |
| 25 // configuration. | |
| 26 GetTimeTicksNow() MojoTimeTicks | |
| 27 | |
| 28 // WaitMany behaves as if Wait were called on each handle/signal pair | |
| 29 // simultaneously and completing when the first Wait would complete. | |
| 30 // Notes about return values: | |
| 31 // |index| can be -1 if the error returned was not caused by a | |
| 32 // particular handle. For example, the error MOJO_RESULT_DEADLINE_
EXCEEDED | |
| 33 // is not related to a particular handle. | |
| 34 // |states| can be nil if the signal array could not be returned. This
can | |
| 35 // happen with errors such as MOJO_RESULT_INVALID_ARGUMENT. | |
| 36 WaitMany(handles []Handle, signals []MojoHandleSignals, deadline MojoDea
dline) (result MojoResult, index int, states []MojoHandleSignalsState) | |
| 37 | |
| 38 // CreateDataPipe creates a data pipe which is a unidirectional | |
| 39 // communication channel for unframed data. On success, returns a | |
| 40 // handle to the producer and consumer of the data pipe. | |
| 41 CreateDataPipe(opts *DataPipeOptions) (MojoResult, ProducerHandle, Consu
merHandle) | |
| 42 | |
| 43 // CreateMessagePipe creates a message pipe which is a bidirectional | |
| 44 // communication channel for framed data (i.e., messages). Messages | |
| 45 // can contain plain data and/or Mojo handles. On success, it returns | |
| 46 // handles to the two endpoints of the message pipe. | |
| 47 CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, MessagePipeHand
le, MessagePipeHandle) | |
| 48 | |
| 49 // CreateSharedBuffer creates a buffer of size numBytes that can be | |
| 50 // shared between applications. One must call MapBuffer to access | |
| 51 // the buffer. | |
| 52 CreateSharedBuffer(opts *SharedBufferOptions, numBytes uint64) (MojoResu
lt, SharedBufferHandle) | |
| 53 } | |
| 54 | |
| 55 // coreImpl is an implementation of the Mojo system APIs. | |
| 56 type coreImpl struct { | |
| 57 // The Go runtime spawns more OS threads (or recycles one from a thread
pool) | |
| 58 // to serve its goroutines if a call blocks for more than some small fra
ction | |
| 59 // of time. To prevent creating spurrious OS threads, we try to have no
more | |
| 60 // than one parallel non-blocking mojo system call; blocking calls shoul
dn't | |
| 61 // use this mutex. | |
| 62 mu sync.Mutex | |
| 63 } | |
| 64 | |
| 65 // GetCore returns singleton instance of the Mojo system APIs implementation. | |
| 66 // | |
| 67 // The implementation uses cgo to call native mojo APIs implementation. Each cgo | |
| 68 // call uses a separate thread for execution. To limit the number of used | |
| 69 // threads all non-blocking system calls (i.e. all system calls except |Wait| | |
| 70 // and |WaitMany|) on this implementation and on handles returned by this | |
| 71 // implementation are protected by a mutex so that if you make two parallel | |
| 72 // system calls one will wait for another to finish before executing. | |
| 73 // However, |Wait| and |WaitMany| are not protected by a mutex and each parallel | |
| 74 // call will use a separate thread. To reduce number of threads used for |Wait| | |
| 75 // calls prefer to use |WaitMany|. | |
| 76 func GetCore() Core { | |
| 77 return &core | |
| 78 } | |
| 79 | |
| 80 func (impl *coreImpl) AcquireNativeHandle(mojoHandle MojoHandle) UntypedHandle { | |
| 81 handle := &untypedHandleImpl{baseHandle{impl, mojoHandle}} | |
| 82 runtime.SetFinalizer(handle, finalizeHandle) | |
| 83 return handle | |
| 84 } | |
| 85 | |
| 86 func (impl *coreImpl) GetTimeTicksNow() MojoTimeTicks { | |
| 87 impl.mu.Lock() | |
| 88 r := sysImpl.GetTimeTicksNow() | |
| 89 impl.mu.Unlock() | |
| 90 return MojoTimeTicks(r) | |
| 91 } | |
| 92 | |
| 93 func (impl *coreImpl) WaitMany(handles []Handle, signals []MojoHandleSignals, de
adline MojoDeadline) (MojoResult, int, []MojoHandleSignalsState) { | |
| 94 if len(handles) == 0 { | |
| 95 r, _, _, _ := sysImpl.WaitMany(nil, nil, uint64(deadline)) | |
| 96 return MojoResult(r), -1, nil | |
| 97 } | |
| 98 rawHandles := make([]uint32, len(handles)) | |
| 99 rawSignals := make([]uint32, len(signals)) | |
| 100 for i := 0; i < len(handles); i++ { | |
| 101 rawHandles[i] = uint32(handles[i].NativeHandle()) | |
| 102 rawSignals[i] = uint32(signals[i]) | |
| 103 } | |
| 104 r, index, rawSatisfiedSignals, rawSatisfiableSignals := sysImpl.WaitMany
(rawHandles, rawSignals, uint64(deadline)) | |
| 105 if MojoResult(r) == MOJO_RESULT_INVALID_ARGUMENT || MojoResult(r) == MOJ
O_RESULT_RESOURCE_EXHAUSTED { | |
| 106 return MojoResult(r), index, nil | |
| 107 } | |
| 108 signalsStates := make([]MojoHandleSignalsState, len(handles)) | |
| 109 for i := 0; i < len(handles); i++ { | |
| 110 signalsStates[i].SatisfiedSignals = MojoHandleSignals(rawSatisfi
edSignals[i]) | |
| 111 signalsStates[i].SatisfiableSignals = MojoHandleSignals(rawSatis
fiableSignals[i]) | |
| 112 } | |
| 113 return MojoResult(r), index, signalsStates | |
| 114 } | |
| 115 | |
| 116 func (impl *coreImpl) CreateDataPipe(opts *DataPipeOptions) (MojoResult, Produce
rHandle, ConsumerHandle) { | |
| 117 | |
| 118 var r uint32 | |
| 119 var p, c uint32 | |
| 120 impl.mu.Lock() | |
| 121 if opts == nil { | |
| 122 r, p, c = sysImpl.CreateDataPipeWithDefaultOptions() | |
| 123 } else { | |
| 124 r, p, c = sysImpl.CreateDataPipe(uint32(opts.Flags), uint32(opts
.ElemSize), uint32(opts.Capacity)) | |
| 125 } | |
| 126 impl.mu.Unlock() | |
| 127 return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(p)).ToProducer
Handle(), impl.AcquireNativeHandle(MojoHandle(c)).ToConsumerHandle() | |
| 128 } | |
| 129 | |
| 130 func (impl *coreImpl) CreateMessagePipe(opts *MessagePipeOptions) (MojoResult, M
essagePipeHandle, MessagePipeHandle) { | |
| 131 | |
| 132 var flags uint32 | |
| 133 if opts != nil { | |
| 134 flags = uint32(opts.Flags) | |
| 135 } | |
| 136 impl.mu.Lock() | |
| 137 r, handle0, handle1 := sysImpl.CreateMessagePipe(flags) | |
| 138 impl.mu.Unlock() | |
| 139 return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(handle0)).ToMe
ssagePipeHandle(), impl.AcquireNativeHandle(MojoHandle(handle1)).ToMessagePipeHa
ndle() | |
| 140 } | |
| 141 | |
| 142 func (impl *coreImpl) CreateSharedBuffer(opts *SharedBufferOptions, numBytes uin
t64) (MojoResult, SharedBufferHandle) { | |
| 143 var flags uint32 | |
| 144 if opts != nil { | |
| 145 flags = uint32(opts.Flags) | |
| 146 } | |
| 147 impl.mu.Lock() | |
| 148 r, handle := sysImpl.CreateSharedBuffer(flags, numBytes) | |
| 149 impl.mu.Unlock() | |
| 150 return MojoResult(r), impl.AcquireNativeHandle(MojoHandle(handle)).ToSha
redBufferHandle() | |
| 151 } | |
| OLD | NEW |