1 /* 2 * (c) 2008-2009 Adam Lackorzynski <adam@os.inf.tu-dresden.de>, 3 * Alexander Warg <warg@os.inf.tu-dresden.de> 4 * economic rights: Technische Universität Dresden (Germany) 5 * 6 * This file is part of TUD:OS and distributed under the terms of the 7 * GNU General Public License 2. 8 * Please see the COPYING-GPL-2 file for details. 9 */ 10 #pragma once 11 12 #include <l4/sys/task.h> 13 #include <l4/sys/factory.h> 14 #include <l4/sys/types.h> 15 #include <l4/sys/thread> 16 17 #include <l4/re/util/bitmap_cap_alloc> 18 #include <l4/re/error_helper> 19 #include <l4/re/env> 20 21 #include <l4/cxx/exceptions> 22 #include <l4/cxx/hlist> 23 24 #include "early.h" 25 #include "server_obj.h" 26 27 #include <cstring> 28 #include <cassert> 29 #include <cstdio> 30 31 #define DEBUG_CAP_ALLOC 0 32 33 enum 34 { 35 Rcv_cap = 0x100, 36 }; 37 38 class Cap_alloc; 39 40 class Object_pool 41 : public L4::Basic_registry, 42 public L4::Ipc_svr::Server_iface, 43 private L4::Irqep_t<Object_pool> 44 { 45 friend struct L4::Irqep_t<Object_pool>; 46 47 public: 48 explicit Object_pool(Cap_alloc *ca); 49 Cap_alloc *cap_alloc() const { return _cap_alloc; } 50 cxx::H_list_t<Moe::Server_object> life; 51 int alloc_buffer_demand(L4::Type_info::Demand const &demand) override 52 { 53 if (demand.caps > 1 54 || demand.ports != 0 55 || demand.mem != 0 56 || demand.flags != 0) 57 return -L4_EINVAL; 58 59 return 0; 60 } 61 62 L4::Cap<void> get_rcv_cap(int index) const override 63 { 64 if (index == 0) 65 return L4::Cap<void>(Rcv_cap << L4_CAP_SHIFT); 66 else 67 return L4::Cap<void>::Invalid; 68 } 69 70 int realloc_rcv_cap(int) override 71 { return -L4_ENOMEM; } 72 73 int add_timeout(L4::Ipc_svr::Timeout *, l4_kernel_clock_t) override 74 { return -L4_ENODEV; } 75 76 int remove_timeout(L4::Ipc_svr::Timeout *) override 77 { return -L4_ENODEV; } 78 79 private: 80 Cap_alloc *_cap_alloc; 81 82 void handle_irq() 83 { 84 l4_utcb_t *utcb = l4_utcb(); 85 for (auto i = life.begin(); i != life.end();) 86 { 87 if (i->obj_cap() && !i->obj_cap().validate(utcb).label()) 88 delete *i; 89 else 90 ++i; 91 } 92 } 93 }; 94 95 class Cap_alloc 96 { 97 public: 98 enum 99 { 100 Non_gc_caps = 8192, 101 Non_gc_cap_0 = Rcv_cap + 1, 102 }; 103 104 private: 105 // caps mainly used for things from outside (registered in name spaces) 106 // this are usually not a lot 107 L4Re::Util::Cap_alloc<Non_gc_caps> _non_gc; 108 109 public: 110 Cap_alloc() : _non_gc(Non_gc_cap_0) 111 {} 112 113 L4::Cap<L4::Kobject> alloc() 114 { 115 L4::Cap<L4::Kobject> cap = _non_gc.alloc<L4::Kobject>(); 116 #if DEBUG_CAP_ALLOC 117 L4::cerr << "AC->" << L4::n_hex(cap.cap()) << "\n"; 118 #endif 119 return cap; 120 } 121 122 template< typename T > 123 L4::Cap<T> alloc() { return L4::cap_cast<T>(alloc()); } 124 125 L4::Cap<L4::Kobject> alloc(Moe::Server_object *_o) 126 { 127 extern Object_pool object_pool; 128 // make sure we register an Epiface ptr 129 L4::Epiface *o = _o; 130 L4::Cap<L4::Kobject> cap = _non_gc.alloc<L4::Kobject>(); 131 #if DEBUG_CAP_ALLOC 132 L4::cerr << "ACO->" << L4::n_hex(cap.cap()) << "\n"; 133 #endif 134 if (!cap.is_valid()) 135 throw(L4::Out_of_memory()); 136 137 l4_umword_t id = l4_umword_t(o); 138 l4_factory_create_gate(L4_BASE_FACTORY_CAP, cap.cap(), 139 L4_BASE_THREAD_CAP, id); 140 141 _o->set_server(&object_pool, cap, true); 142 return cap; 143 } 144 145 bool free(L4::Cap<void> const &cap, l4_umword_t unmap_flags = L4_FP_ALL_SPACES) 146 { 147 if (!cap.is_valid()) 148 return false; 149 150 if ((cap.cap() >> L4_CAP_SHIFT) >= Non_gc_cap_0) 151 _non_gc.free(cap, L4_BASE_TASK_CAP, unmap_flags); 152 else 153 return false; 154 155 return true; 156 } 157 158 }; 159 160 inline Object_pool::Object_pool(Cap_alloc *ca) : _cap_alloc(ca) 161 { 162 // make sure we register an Epiface PTR 163 L4::Epiface *self = this; 164 auto c = early_chkcap(cap_alloc()->alloc<L4::Irq>(), 165 "Moe::Object_pool: Failed to allocate capability\n"); 166 early_chksys(L4Re::Env::env()->factory()->create(c), 167 "Moe::Object_pool: Failed to create IRQ\n"); 168 early_chksys(c->bind_thread(L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP), 169 l4_umword_t(self)), 170 "Moe::Object_pool: Failed to bind IRQ\n"); 171 set_server(this, c, true); 172 early_chksys(L4::Cap<L4::Thread>(L4_BASE_THREAD_CAP)->register_del_irq(c), 173 "Moe::Object_pool: Failed to register deletion IRQ\n"); 174 } 175