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