Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
dynarray.cpp
Go to the documentation of this file.
1 /* Copyright (c) 2010 Wildfire Games
2  *
3  * Permission is hereby granted, free of charge, to any person obtaining
4  * a copy of this software and associated documentation files (the
5  * "Software"), to deal in the Software without restriction, including
6  * without limitation the rights to use, copy, modify, merge, publish,
7  * distribute, sublicense, and/or sell copies of the Software, and to
8  * permit persons to whom the Software is furnished to do so, subject to
9  * the following conditions:
10  *
11  * The above copyright notice and this permission notice shall be included
12  * in all copies or substantial portions of the Software.
13  *
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18  * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21  */
22 
23 /*
24  * dynamic (expandable) array
25  */
26 
27 #include "precompiled.h"
29 
30 #include "lib/alignment.h"
31 #include "lib/sysdep/vm.h"
32 
33 
35 {
36  if(!da)
38 // u8* const base = da->base;
39  const size_t max_size_pa = da->max_size_pa;
40  const size_t cur_size = da->cur_size;
41  const size_t pos = da->pos;
42 
43  // note: this happens if max_size == 0
44 // if(debug_IsPointerBogus(base))
45 // WARN_RETURN(ERR::_1);
46  // note: don't check if base is page-aligned -
47  // might not be true for 'wrapped' mem regions.
48  if(!IsAligned(max_size_pa, pageSize))
50  if(cur_size > max_size_pa)
52  if(pos > cur_size || pos > max_size_pa)
54 
55  return INFO::OK;
56 }
57 
58 #define CHECK_DA(da) RETURN_STATUS_IF_ERR(validate_da(da))
59 
60 
61 Status da_alloc(DynArray* da, size_t max_size)
62 {
63  ENSURE(max_size != 0);
64  const size_t max_size_pa = Align<pageSize>(max_size);
65 
66  u8* p = (u8*)vm::ReserveAddressSpace(max_size_pa);
67  if(!p)
68  return ERR::NO_MEM; // NOWARN (already done in vm)
69 
70  da->base = p;
71  da->max_size_pa = max_size_pa;
72  da->cur_size = 0;
73  da->cur_size_pa = 0;
74  da->pos = 0;
75  CHECK_DA(da);
76  return INFO::OK;
77 }
78 
79 
81 {
82  CHECK_DA(da);
83 
85 
86  // wipe out the DynArray for safety
87  memset(da, 0, sizeof(*da));
88 
89  return INFO::OK;
90 }
91 
92 
93 Status da_set_size(DynArray* da, size_t new_size)
94 {
95  CHECK_DA(da);
96 
97  // determine how much to add/remove
98  const size_t cur_size_pa = Align<pageSize>(da->cur_size);
99  const size_t new_size_pa = Align<pageSize>(new_size);
100  const ssize_t size_delta_pa = (ssize_t)new_size_pa - (ssize_t)cur_size_pa;
101 
102  // not enough memory to satisfy this expand request: abort.
103  // note: do not complain - some allocators (e.g. file_cache)
104  // legitimately use up all available space.
105  if(new_size_pa > da->max_size_pa)
106  return ERR::LIMIT; // NOWARN
107 
108  u8* end = da->base + cur_size_pa;
109  bool ok = true;
110  // expanding
111  if(size_delta_pa > 0)
112  {
113  ok = vm::Commit(uintptr_t(end), size_delta_pa);
114  if(!ok)
115  debug_printf(L"Commit failed (%p %lld)\n", end, (long long)size_delta_pa);
116  }
117  // shrinking
118  else if(size_delta_pa < 0)
119  ok = vm::Decommit(uintptr_t(end+size_delta_pa), -size_delta_pa);
120  // else: no change in page count, e.g. if going from size=1 to 2
121  // (we don't want mem_* to have to handle size=0)
122 
123  da->cur_size = new_size;
124  da->cur_size_pa = new_size_pa;
125  CHECK_DA(da);
126  return ok? INFO::OK : ERR::FAIL;
127 }
128 
129 
130 Status da_reserve(DynArray* da, size_t size)
131 {
132  if(da->pos+size > da->cur_size_pa)
134  da->cur_size = std::max(da->cur_size, da->pos+size);
135  return INFO::OK;
136 }
137 
138 
139 Status da_append(DynArray* da, const void* data, size_t size)
140 {
141  RETURN_STATUS_IF_ERR(da_reserve(da, size));
142  memcpy(da->base+da->pos, data, size);
143  da->pos += size;
144  return INFO::OK;
145 }
#define u8
Definition: types.h:39
const Status _4
Definition: status.h:444
static const size_t pageSize
Definition: alignment.h:61
const Status OK
Definition: status.h:386
static Status validate_da(DynArray *da)
Definition: dynarray.cpp:34
provides a memory range that can be expanded but doesn&#39;t waste physical memory or relocate itself...
Definition: dynarray.h:39
const Status _3
Definition: status.h:443
bool Commit(uintptr_t address, size_t size, PageType pageType, int prot)
map physical memory to previously reserved address space.
Definition: uvm.cpp:59
bool IsAligned(T t, uintptr_t multiple)
Definition: alignment.h:8
#define ENSURE(expr)
ensure the expression &lt;expr&gt; evaluates to non-zero.
Definition: debug.h:282
u8 * base
Definition: dynarray.h:41
const Status LIMIT
Definition: status.h:428
const Status INVALID_POINTER
Definition: status.h:420
#define CHECK_DA(da)
Definition: dynarray.cpp:58
const Status _5
Definition: status.h:445
Status da_set_size(DynArray *da, size_t new_size)
expand or shrink the array: changes the amount of currently committed (i.e.
Definition: dynarray.cpp:93
bool Decommit(uintptr_t address, size_t size)
unmap physical memory.
Definition: uvm.cpp:77
Status da_append(DynArray *da, const void *data, size_t size)
&quot;write&quot; to array, i.e.
Definition: dynarray.cpp:139
i64 Status
Error handling system.
Definition: status.h:171
size_t pos
Definition: dynarray.h:46
intptr_t ssize_t
Definition: wposix_types.h:82
void ReleaseAddressSpace(void *p, size_t size)
release address space and decommit any memory.
Definition: uvm.cpp:49
size_t cur_size_pa
committed
Definition: dynarray.h:44
#define WARN_RETURN(status)
Definition: status.h:255
Status da_free(DynArray *da)
free all memory (address space + physical) that constitutes the given array.
Definition: dynarray.cpp:80
const Status FAIL
Definition: status.h:406
size_t max_size_pa
Definition: dynarray.h:42
void * ReserveAddressSpace(size_t size, size_t commitSize, PageType pageType, int prot)
reserve address space and set the parameters for any later on-demand commits.
Definition: uvm.cpp:40
const Status NO_MEM
Definition: status.h:430
Status da_reserve(DynArray *da, size_t size)
Make sure at least &lt;size&gt; bytes starting at da-&gt;pos are committed and ready for use.
Definition: dynarray.cpp:130
Status da_alloc(DynArray *da, size_t max_size)
ready the DynArray object for use.
Definition: dynarray.cpp:61
size_t cur_size
reserved
Definition: dynarray.h:43
void debug_printf(const wchar_t *fmt,...)
write a formatted string to the debug channel, subject to filtering (see below).
Definition: debug.cpp:142
#define RETURN_STATUS_IF_ERR(expression)
Definition: status.h:276