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 |