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 #include "dataspace_anon.h"
11 #include "page_alloc.h"
12 #include "debug.h"
13
14 #include <l4/cxx/exceptions>
15 #include <l4/cxx/minmax>
16
17 #include <l4/sys/cache.h>
18
19 #include <cstring>
20 #include <climits>
21
Dataspace_anon(long size,Flags w,unsigned char page_shift)22 Moe::Dataspace_anon::Dataspace_anon(long size, Flags w,
23 unsigned char page_shift)
24 : Moe::Dataspace_cont(0, 0, w, page_shift)
25 {
26 Quota_guard g;
27 Single_page_unique_ptr m;
28
29 // test whether the client requested to max out his allocation and whether
30 // the allocator can fulfill this request in theory
31 if (L4_UNLIKELY(size < 0))
32 {
33 unsigned long l = qalloc()->quota()->limit();
34 unsigned long a = Single_page_alloc_base::_avail();
35
36 a = cxx::min(l - qalloc()->quota()->used(), a);
37
38 // not enough memory left
39 if (a <= (unsigned long)(-size))
40 L4Re::chksys(-L4_ENOMEM);
41
42 if (l == ~0UL)
43 l = LONG_MAX;
44
45 if (l <= (unsigned long)(-size))
46 L4Re::chksys(-L4_ENOMEM);
47
48 size = cxx::min(a + size, l + size);
49 size = l4_trunc_size(size, page_shift);
50
51 if (size == 0L)
52 L4Re::chksys(-L4_ENOMEM);
53
54 unsigned long r_size = size;
55 void *_m = Single_page_alloc_base::_alloc_max(page_size(), &r_size,
56 page_size(), page_size());
57
58 if (!_m)
59 L4Re::chksys(-L4_ENOMEM);
60
61 m = Single_page_unique_ptr(_m, r_size);
62 g = Quota_guard(qalloc()->quota(), r_size);
63 size = r_size;
64 }
65 else
66 {
67 unsigned long r_size = (size + page_size() - 1) & ~(page_size() -1);
68 g = Quota_guard(qalloc()->quota(), r_size);
69 void *_m = Single_page_alloc_base::_alloc(r_size, page_size());
70
71 m = Single_page_unique_ptr(_m, r_size);
72 }
73
74 memset(m.get(), 0, m.size());
75 // No need for I cache coherence, as we just zero fill and assume that
76 // this is no executable code
77 l4_cache_clean_data((l4_addr_t)m.get(), (l4_addr_t)m.get() + m.size());
78
79 start(m.release());
80 this->size(size);
81 g.release();
82 }
83
~Dataspace_anon()84 Moe::Dataspace_anon::~Dataspace_anon()
85 {
86 void *adr = start();
87 if (adr)
88 {
89 unsigned long r_size = (size() + page_size() - 1) & ~(page_size() -1);
90 Single_page_alloc_base::_free(adr, r_size);
91 qalloc()->quota()->free(r_size);
92 }
93 }
94