• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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 
17 #include "common/vsoc/lib/vsoc_memory.h"
18 
19 #include <string.h>
20 #include <unistd.h>
21 
22 #include <map>
23 #include <string>
24 #include <type_traits>
25 
26 #include "common/libs/glog/logging.h"
27 #include "common/vsoc/shm/audio_data_layout.h"
28 #include "common/vsoc/shm/base.h"
29 #include "common/vsoc/shm/e2e_test_region_layout.h"
30 #include "common/vsoc/shm/gralloc_layout.h"
31 #include "common/vsoc/shm/input_events_layout.h"
32 #include "common/vsoc/shm/managed_e2e_test_region_layout.h"
33 #include "common/vsoc/shm/screen_layout.h"
34 #include "common/vsoc/shm/socket_forward_layout.h"
35 
36 #include "uapi/vsoc_shm.h"
37 
38 namespace {
39 
40 // Takes a vector of objects and returns a vector of pointers to those objects.
41 template <typename T, typename R>
GetConstPointers(const std::vector<T> & v)42 std::vector<R*> GetConstPointers(const std::vector<T>& v) {
43   std::vector<R*> result;
44   result.reserve(v.size());
45   for (auto& element : v) {
46     result.push_back(&element);
47   }
48   return result;
49 }
50 }  // namespace
51 
52 namespace vsoc {
53 
54 namespace {
55 
56 class VSoCRegionLayoutImpl : public VSoCRegionLayout {
57  public:
VSoCRegionLayoutImpl(const char * region_name,size_t layout_size,int guest_to_host_signal_table_log_size,int host_to_guest_signal_table_log_size,const char * managed_by)58   VSoCRegionLayoutImpl(const char* region_name, size_t layout_size,
59                        int guest_to_host_signal_table_log_size,
60                        int host_to_guest_signal_table_log_size,
61                        const char* managed_by)
62       : region_name_(region_name),
63         layout_size_(layout_size),
64         guest_to_host_signal_table_log_size_(
65             guest_to_host_signal_table_log_size),
66         host_to_guest_signal_table_log_size_(
67             host_to_guest_signal_table_log_size),
68         managed_by_(managed_by) {
69   }
70   VSoCRegionLayoutImpl(const VSoCRegionLayoutImpl&) = default;
71 
region_name() const72   const char* region_name() const override { return region_name_; }
managed_by() const73   const char* managed_by() const override { return managed_by_; }
74 
layout_size() const75   size_t layout_size() const override { return layout_size_; }
guest_to_host_signal_table_log_size() const76   int guest_to_host_signal_table_log_size() const override {
77     return guest_to_host_signal_table_log_size_;
78   }
host_to_guest_signal_table_log_size() const79   int host_to_guest_signal_table_log_size() const override {
80     return host_to_guest_signal_table_log_size_;
81   }
82 
83  private:
84   const char* region_name_{};
85   const size_t layout_size_{};
86   const int guest_to_host_signal_table_log_size_{};
87   const int host_to_guest_signal_table_log_size_{};
88   const char* managed_by_{};
89 };
90 
91 class VSoCMemoryLayoutImpl : public VSoCMemoryLayout {
92  public:
VSoCMemoryLayoutImpl(std::vector<VSoCRegionLayoutImpl> && regions)93   explicit VSoCMemoryLayoutImpl(std::vector<VSoCRegionLayoutImpl>&& regions)
94       : regions_(regions), region_idx_by_name_(GetNameToIndexMap(regions)) {
95     for (size_t i = 0; i < regions_.size(); ++i) {
96       // This link could be resolved later, but doing it here disables
97       // managed_by cycles among the regions.
98       if (regions[i].managed_by() &&
99           !region_idx_by_name_.count(regions[i].managed_by())) {
100         LOG(FATAL) << regions[i].region_name()
101                    << " managed by unknown region: " << regions[i].managed_by()
102                    << ". Manager Regions must be declared before the regions "
103                       "they manage";
104       }
105     }
106   }
107 
108   ~VSoCMemoryLayoutImpl() = default;
109 
GetRegions() const110   std::vector<const VSoCRegionLayout*> GetRegions() const {
111     static std::vector<const VSoCRegionLayout*> ret =
112         GetConstPointers<VSoCRegionLayoutImpl, const VSoCRegionLayout>(
113             regions_);
114     return ret;
115   }
116 
GetRegionByName(const char * region_name) const117   const VSoCRegionLayout* GetRegionByName(
118       const char* region_name) const override {
119     if (!region_idx_by_name_.count(region_name)) {
120       return nullptr;
121     }
122     return &regions_[region_idx_by_name_.at(region_name)];
123   }
124 
125  protected:
126   VSoCMemoryLayoutImpl() = delete;
127   VSoCMemoryLayoutImpl(const VSoCMemoryLayoutImpl&) = delete;
128 
129   // Helper function to allow the creation of the name to index map in the
130   // constructor and allow the field to be const
GetNameToIndexMap(const std::vector<VSoCRegionLayoutImpl> & regions)131   static std::map<const char*, size_t> GetNameToIndexMap(
132       const std::vector<VSoCRegionLayoutImpl>& regions) {
133     std::map<const char*, size_t> result;
134     for (size_t index = 0; index < regions.size(); ++index) {
135       auto region_name = regions[index].region_name();
136       if (result.count(region_name)) {
137         LOG(FATAL) << region_name << " used for more than one region";
138       }
139       result[region_name] = index;
140     }
141     return result;
142   }
143 
144   std::vector<VSoCRegionLayoutImpl> regions_;
145   const std::map<const char*, size_t> region_idx_by_name_;
146 };
147 
148 template <class R>
ValidateAndBuildLayout(int g_to_h_signal_table_log_size,int h_to_g_signal_table_log_size,const char * managed_by=nullptr)149 VSoCRegionLayoutImpl ValidateAndBuildLayout(int g_to_h_signal_table_log_size,
150                                             int h_to_g_signal_table_log_size,
151                                             const char* managed_by = nullptr) {
152   // Double check that the Layout is a valid shm type.
153   ASSERT_SHM_COMPATIBLE(R);
154   return VSoCRegionLayoutImpl(R::region_name, sizeof(R),
155                               g_to_h_signal_table_log_size,
156                               h_to_g_signal_table_log_size, managed_by);
157 }
158 
159 }  // namespace
160 
Get()161 VSoCMemoryLayout* VSoCMemoryLayout::Get() {
162   /*******************************************************************
163    * Make sure the first region is not the manager of other regions. *
164    *       This error will only be caught on runtime!!!!!            *
165    *******************************************************************/
166   static VSoCMemoryLayoutImpl layout(
167       {ValidateAndBuildLayout<layout::input_events::InputEventsLayout>(2, 2),
168        ValidateAndBuildLayout<layout::screen::ScreenLayout>(2, 2),
169        ValidateAndBuildLayout<layout::gralloc::GrallocManagerLayout>(2, 2),
170        ValidateAndBuildLayout<layout::gralloc::GrallocBufferLayout>(
171            0, 0,
172            /* managed_by */ layout::gralloc::GrallocManagerLayout::region_name),
173        ValidateAndBuildLayout<layout::socket_forward::SocketForwardLayout>(7,
174                                                                            7),
175        ValidateAndBuildLayout<layout::e2e_test::E2EPrimaryTestRegionLayout>(1,
176                                                                             1),
177        ValidateAndBuildLayout<layout::e2e_test::E2ESecondaryTestRegionLayout>(
178            1, 1),
179        ValidateAndBuildLayout<layout::e2e_test::E2EManagerTestRegionLayout>(1,
180                                                                             1),
181        ValidateAndBuildLayout<layout::e2e_test::E2EManagedTestRegionLayout>(1,
182                                                                             1),
183        ValidateAndBuildLayout<layout::audio_data::AudioDataLayout>(2, 2)});
184 
185   // We need this code to compile on both sides to enforce the static checks,
186   // but should only be used host side.
187 #if !defined(CUTTLEFISH_HOST)
188   LOG(FATAL) << "Memory layout should not be used guest side, use region "
189                 "classes or the vsoc driver directly instead.";
190 #endif
191   return &layout;
192 }
193 
194 }  // namespace vsoc
195