• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "host/commands/ivserver/vsocsharedmem.h"
17 
18 #include <errno.h>
19 #include <fcntl.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <sys/eventfd.h>
24 #include <sys/mman.h>
25 #include <sys/stat.h>
26 #include <unistd.h>
27 #include <algorithm>
28 #include <tuple>
29 
30 #include <glog/logging.h>
31 
32 #include "common/vsoc/lib/vsoc_memory.h"
33 #include "uapi/vsoc_shm.h"
34 
35 namespace ivserver {
36 namespace {
37 
38 class VSoCSharedMemoryImpl : public VSoCSharedMemory {
39  public:
40   VSoCSharedMemoryImpl(const std::map<std::string, size_t> &name_to_region_idx,
41                        const std::vector<Region> &regions,
42                        const std::string &path);
43 
44   bool GetEventFdPairForRegion(const std::string &region_name,
45                                cvd::SharedFD *guest_to_host,
46                                cvd::SharedFD *host_to_guest) const override;
47 
48   const cvd::SharedFD &SharedMemFD() const override;
49 
50   const std::vector<Region> &Regions() const override;
51 
52  private:
53   void CreateLayout();
54 
55   cvd::SharedFD shared_mem_fd_;
56   const std::map<std::string, size_t> region_name_to_index_;
57   const std::vector<Region> region_data_;
58 
59   VSoCSharedMemoryImpl(const VSoCSharedMemoryImpl &) = delete;
60   VSoCSharedMemoryImpl &operator=(const VSoCSharedMemoryImpl &other) = delete;
61 };
62 
VSoCSharedMemoryImpl(const std::map<std::string,size_t> & name_to_region_idx,const std::vector<Region> & regions,const std::string & path)63 VSoCSharedMemoryImpl::VSoCSharedMemoryImpl(
64     const std::map<std::string, size_t> &name_to_region_idx,
65     const std::vector<Region> &regions, const std::string &path)
66     : shared_mem_fd_(cvd::SharedFD::Open(path.c_str(), O_RDWR)),
67       region_name_to_index_{name_to_region_idx},
68       region_data_{regions} {
69   LOG_IF(FATAL, !shared_mem_fd_->IsOpen())
70       << "Error in creating shared_memory file: " << shared_mem_fd_->StrError();
71 }
72 
SharedMemFD() const73 const cvd::SharedFD &VSoCSharedMemoryImpl::SharedMemFD() const {
74   return shared_mem_fd_;
75 }
76 
Regions() const77 const std::vector<VSoCSharedMemory::Region> &VSoCSharedMemoryImpl::Regions()
78     const {
79   return region_data_;
80 }
81 
GetEventFdPairForRegion(const std::string & region_name,cvd::SharedFD * guest_to_host,cvd::SharedFD * host_to_guest) const82 bool VSoCSharedMemoryImpl::GetEventFdPairForRegion(
83     const std::string &region_name, cvd::SharedFD *guest_to_host,
84     cvd::SharedFD *host_to_guest) const {
85   auto it = region_name_to_index_.find(region_name);
86   if (it == region_name_to_index_.end()) return false;
87 
88   *guest_to_host = region_data_[it->second].host_fd;
89   *host_to_guest = region_data_[it->second].guest_fd;
90   return true;
91 }
92 
93 }  // anonymous namespace
94 
New(const std::string & path)95 std::unique_ptr<VSoCSharedMemory> VSoCSharedMemory::New(
96     const std::string &path) {
97   auto device_layout = vsoc::VSoCMemoryLayout::Get();
98 
99   std::map<std::string, size_t> name_to_region_idx;
100   std::vector<Region> regions;
101   regions.reserve(device_layout->GetRegions().size());
102 
103   for (auto region_spec : device_layout->GetRegions()) {
104     auto device_name = region_spec->region_name();
105 
106     // Create one pair of eventfds for this region. Note that the guest to host
107     // eventfd is non-blocking, whereas the host to guest eventfd is blocking.
108     // This is in anticipation of blocking semantics for the host side locks.
109     auto host_fd = cvd::SharedFD::Event(0, EFD_NONBLOCK);
110     if (!host_fd->IsOpen()) {
111       LOG(ERROR) << "Failed to create host eventfd for " << device_name << ": "
112                  << host_fd->StrError();
113       return nullptr;
114     }
115     auto guest_fd = cvd::SharedFD::Event(0, EFD_NONBLOCK);
116     if (!guest_fd->IsOpen()) {
117       LOG(ERROR) << "Failed to create guest eventfd for " << device_name << ": "
118                  << guest_fd->StrError();
119       return nullptr;
120     }
121 
122     auto region_idx = regions.size();
123     name_to_region_idx[device_name] = region_idx;
124     regions.emplace_back(device_name, host_fd, guest_fd);
125   }
126 
127   return std::unique_ptr<VSoCSharedMemory>(
128       new VSoCSharedMemoryImpl(name_to_region_idx, regions, path));
129 }
130 
131 }  // namespace ivserver
132