OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2012 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 #include "media/audio/shared_mem_synchronizer.h" | |
6 | |
7 #include <errno.h> | |
8 #include <sys/poll.h> | |
9 | |
10 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | |
12 #include "base/file_descriptor_posix.h" | |
13 | |
14 SharedMemSynchronizer::~SharedMemSynchronizer() {} | |
15 | |
16 SharedMemSynchronizer::SharedMemSynchronizer(IPCHandle handle_1, | |
17 IPCHandle handle_2) | |
18 : socket_(handle_1.fd) { | |
19 DCHECK_NE(handle_1.fd, -1); | |
20 DCHECK_EQ(handle_2.fd, -1); | |
21 DCHECK(IsValid()); | |
22 } | |
23 | |
24 void SharedMemSynchronizer::Signal() { | |
25 DCHECK(IsValid()); | |
26 char signal = 1; | |
27 size_t bytes = socket_.Send(&signal, sizeof(signal)); | |
28 DCHECK_EQ(bytes, 1U) << "errno: " << errno; | |
29 } | |
30 | |
31 void SharedMemSynchronizer::Wait() { | |
32 DCHECK(IsValid()); | |
33 char signal = 0; | |
34 size_t bytes = socket_.Receive(&signal, sizeof(signal)); | |
35 DCHECK_EQ(bytes, 1U) << "errno: " << errno; | |
36 DCHECK_EQ(signal, 1); | |
37 } | |
38 | |
39 bool SharedMemSynchronizer::IsValid() const { | |
40 return socket_.handle() != SocketClass::kInvalidHandle; | |
41 } | |
42 | |
43 bool SharedMemSynchronizer::ShareToProcess(base::ProcessHandle process, | |
44 IPCHandle* handle_1, | |
45 IPCHandle* handle_2) { | |
46 DCHECK(IsValid()); | |
47 handle_1->fd = socket_.handle(); | |
48 handle_1->auto_close = false; | |
49 handle_2->fd = -1; | |
50 return true; | |
51 } | |
52 | |
53 // static | |
54 bool SharedMemSynchronizer::InitializePair(SharedMemSynchronizer* a, | |
55 SharedMemSynchronizer* b) { | |
56 DCHECK(!a->IsValid()); | |
57 DCHECK(!b->IsValid()); | |
58 | |
59 bool ok = SocketClass::CreatePair(&a->socket_, &b->socket_); | |
60 | |
61 DLOG_IF(WARNING, !ok) << "failed to create socket: " << errno; | |
62 DCHECK(!ok || a->IsValid()); | |
63 DCHECK(!ok || b->IsValid()); | |
64 return ok; | |
65 } | |
66 | |
67 // static | |
68 int SharedMemSynchronizer::WaitMultiple(const SynchronizerVector& synchronizers, | |
69 size_t last_signaled) { | |
70 DCHECK_LT(last_signaled, synchronizers.size()); | |
71 | |
72 for (size_t i = 0; i < synchronizers.size(); ++i) { | |
73 DCHECK(synchronizers[i]->IsValid()); | |
74 } | |
75 | |
76 // Below, we always check the |revents| of the first socket in the array | |
77 // and return the index of that socket if set. This can cause sockets | |
78 // that come later in the array to starve when the first sockets are | |
79 // very busy. So to avoid the starving problem, we use the |last_signaled| | |
80 // variable to split up the array so that the last socket to be signaled | |
81 // becomes the last socket in the array and all the other sockets will have | |
82 // priority the next time WaitMultiple is called. | |
83 scoped_array<struct pollfd> sockets(new struct pollfd[synchronizers.size()]); | |
84 memset(&sockets[0], 0, synchronizers.size() * sizeof(sockets[0])); | |
85 size_t index = 0; | |
86 for (size_t i = last_signaled + 1; i < synchronizers.size(); ++i) { | |
87 struct pollfd& fd = sockets[index++]; | |
88 fd.events = POLLIN; | |
89 fd.fd = synchronizers[i]->socket_.handle(); | |
90 } | |
91 | |
92 for (size_t i = 0; i <= last_signaled; ++i) { | |
93 struct pollfd& fd = sockets[index++]; | |
94 fd.events = POLLIN; | |
95 fd.fd = synchronizers[i]->socket_.handle(); | |
96 } | |
97 DCHECK_EQ(index, synchronizers.size()); | |
98 | |
99 int err = poll(&sockets[0], synchronizers.size(), -1); | |
100 if (err != -1) { | |
101 for (size_t i = 0; i < synchronizers.size(); ++i) { | |
102 if (sockets[i].revents) { | |
103 int ret = (i + last_signaled + 1) % synchronizers.size(); | |
Ami GONE FROM CHROMIUM
2012/03/13 20:08:02
It is asymmetric that ret is an "int" but last_sig
tommi (sloooow) - chröme
2012/03/14 13:32:43
Done.
| |
104 DCHECK_EQ(sockets[i].fd, synchronizers[ret]->socket_.handle()); | |
105 synchronizers[ret]->Wait(); | |
106 return ret; | |
107 } | |
108 } | |
109 } else { | |
110 LOG(ERROR) << "poll() failed: " << errno; | |
Ami GONE FROM CHROMIUM
2012/03/13 20:08:02
The case of poll returning 0 but none of the reven
tommi (sloooow) - chröme
2012/03/14 13:32:43
Done.
| |
111 } | |
112 // Either poll() failed or we failed to find a single socket that was | |
113 // signaled. Either way continuing will result in undefined behavior. | |
114 CHECK(false); | |
115 return -1; | |
116 } | |
OLD | NEW |