sel_ldr: Remove support for rodata segment at start of executable
[nativeclient.git] / service_runtime / dyn_array.c
blob9f14418a9bd5c44c949cd4bed79f5c17687a3e26
1 /*
2 * Copyright 2008, Google Inc.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
8 *
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
15 * * Neither the name of Google Inc. nor the names of its
16 * contributors may be used to endorse or promote products derived from
17 * this software without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 * Implementation of dynamic arrays.
36 #include "native_client/include/portability.h"
38 #define DYN_ARRAY_DEBUG 1
40 #include <stdlib.h>
41 #include <string.h>
43 #include "native_client/service_runtime/dyn_array.h"
45 #if DYN_ARRAY_DEBUG
46 # include "native_client/service_runtime/nacl_log.h"
47 #endif
49 static INLINE int BitsToAllocWords(int nbits)
51 return (nbits + kBitsPerWord - 1) >> kWordIndexShift;
54 static INLINE int BitsToIndex(int nbits)
56 return nbits >> kWordIndexShift;
59 static INLINE int BitsToOffset(int nbits)
61 return nbits & (kBitsPerWord - 1);
64 int DynArrayCtor(struct DynArray *dap,
65 int initial_size)
67 if (initial_size <= 0) {
68 initial_size = 32;
70 dap->num_entries = 0u;
71 dap->ptr_array = calloc(initial_size, sizeof *dap->ptr_array);
72 if (NULL == dap->ptr_array) {
73 return 0;
75 dap->available = calloc(BitsToAllocWords(initial_size),
76 sizeof *dap->available);
77 if (NULL == dap->available) {
78 free(dap->ptr_array);
79 dap->ptr_array = NULL;
80 return 0;
82 dap->avail_ix = 0; /* hint */
84 dap->ptr_array_space = initial_size;
85 return 1;
88 void DynArrayDtor(struct DynArray *dap)
90 dap->num_entries = 0; /* assume user has freed entries */
91 free(dap->ptr_array);
92 dap->ptr_array = NULL;
93 dap->ptr_array_space = 0;
94 free(dap->available);
95 dap->available = NULL;
98 void *DynArrayGet(struct DynArray *dap,
99 int idx)
101 if ((unsigned) idx < (unsigned) dap->num_entries) {
102 return dap->ptr_array[idx];
104 return NULL;
107 int DynArraySet(struct DynArray *dap,
108 int idx,
109 void *ptr)
111 int desired_space;
112 int tmp;
113 int ix;
115 for (desired_space = dap->ptr_array_space;
116 idx >= desired_space;
117 desired_space = tmp) {
118 tmp = 2 * desired_space;
119 if (tmp < desired_space) {
120 return 0;
123 if (desired_space != dap->ptr_array_space) {
124 /* need to grow */
126 void **new_space;
127 uint32_t *new_avail;
128 size_t new_avail_nwords;
129 size_t old_avail_nwords;
131 new_space = realloc(dap->ptr_array, desired_space * sizeof *new_space);
132 if (NULL == new_space) {
133 return 0;
135 memset((void *) (new_space + dap->ptr_array_space),
137 (desired_space - dap->ptr_array_space) * sizeof *new_space);
138 dap->ptr_array = new_space;
140 old_avail_nwords = BitsToAllocWords(dap->ptr_array_space);
141 new_avail_nwords = BitsToAllocWords(desired_space);
143 new_avail = realloc(dap->available,
144 new_avail_nwords * sizeof *new_avail);
145 if (NULL == new_avail) {
146 return 0;
148 memset((void *) &new_avail[old_avail_nwords],
150 (new_avail_nwords - old_avail_nwords) * sizeof *new_avail);
151 dap->available = new_avail;
153 dap->ptr_array_space = desired_space;
155 dap->ptr_array[idx] = ptr;
156 ix = BitsToIndex(idx);
157 #if DYN_ARRAY_DEBUG
158 NaClLog(4, "Set(%d,%p) @ix %d: 0x%08x\n", idx, ptr, ix, dap->available[ix]);
159 #endif
160 if (NULL != ptr) {
161 dap->available[ix] |= (1 << BitsToOffset(idx));
162 } else {
163 dap->available[ix] &= ~(1 << BitsToOffset(idx));
164 if (ix < dap->avail_ix) {
165 dap->avail_ix = ix;
168 #if DYN_ARRAY_DEBUG
169 NaClLog(4, "After @ix %d: 0x%08x, avail_ix %d\n",
170 ix, dap->available[ix], dap->avail_ix);
171 #endif
172 if (dap->num_entries <= idx) {
173 dap->num_entries = idx + 1;
175 return 1;
178 int DynArrayFirstAvail(struct DynArray *dap)
180 int ix;
181 int last_ix;
182 int avail_pos;
184 last_ix = BitsToAllocWords(dap->ptr_array_space);
186 #if DYN_ARRAY_DEBUG
187 for (ix = 0; ix < last_ix; ++ix) {
188 NaClLog(4, "ix %d: 0x%08x\n", ix, dap->available[ix]);
190 #endif
191 for (ix = dap->avail_ix; ix < last_ix; ++ix) {
192 if (0U != ~dap->available[ix]) {
193 #if DYN_ARRAY_DEBUG
194 NaClLog(4, "found first not-all-ones ix %d\n", ix);
195 #endif
196 dap->avail_ix = ix;
197 break;
200 if (ix < last_ix) {
201 avail_pos = ffs(~dap->available[ix]) - 1;
202 avail_pos += ix << kWordIndexShift;
203 } else {
204 avail_pos = dap->ptr_array_space;
206 return avail_pos;