IBNOS
handle.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2014, Michael Müller
3  * Copyright (c) 2014, Sebastian Lackner
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright notice, this
10  * list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright notice,
12  * this list of conditions and the following disclaimer in the documentation
13  * and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25  *
26  */
27 
28 #include <process/handle.h>
29 #include <memory/allocator.h>
30 #include <process/object.h>
31 #include <util/list.h>
32 #include <util/util.h>
33 
48 void handleTableInit(struct handleTable *table)
49 {
50  table->count = MIN_HANDLES;
51  table->free_begin = 0; /* first free element */
52  table->free_end = 0; /* last used element + 1 */
53  table->handles = heapAlloc(table->count * sizeof(struct object *));
54 
55  assert(table->handles);
56  memset(table->handles, 0, table->count * sizeof(struct object *));
57 }
58 
68 void handleForkTable(struct handleTable *destination, struct handleTable *source)
69 {
70  uint32_t i;
71  uint32_t count = MIN_HANDLES;
72  while (count < source->free_end) count *= 2;
73 
74  assert(source->handles);
75  assert(count >= source->free_end);
76 
77  destination->count = count;
78  destination->free_begin = source->free_begin;
79  destination->free_end = source->free_end;
80  destination->handles = heapAlloc(count * sizeof(struct object *));
81 
82  assert(destination->handles);
83  memset(destination->handles, 0, destination->count * sizeof(struct object *));
84 
85  for (i = 0; i < source->free_end; i++)
86  destination->handles[i] = source->handles[i] ? __objectAddRef(source->handles[i]) : NULL;
87 }
88 
94 void handleTableFree(struct handleTable *table)
95 {
96  uint32_t i;
97 
98  for (i = 0; i < table->free_end; i++)
99  {
100  if (table->handles[i]) __objectRelease(table->handles[i]);
101  }
102 
103  heapFree(table->handles);
104 }
105 
117 uint32_t handleAllocate(struct handleTable *table, struct object *object)
118 {
119  uint32_t i;
120  assert(object);
121 
122  /* start iteration with the lowest possible handle */
123  i = __objectGetMinHandle(object);
124  if (i < table->free_begin) i = table->free_begin;
125 
126  for (; i < table->free_end; i++)
127  {
128  if (!table->handles[i])
129  {
130  table->free_begin = i + 1;
131  table->handles[i] = __objectAddRef(object);
132  return i;
133  }
134  }
135 
136  if (i >= table->count)
137  {
138  uint32_t count = 2 * table->count;
139  while (count < i) count *= 2;
140  if (count > MAX_HANDLES) count = MAX_HANDLES;
141 
142  /* unable to allocate further handles */
143  if (table->count >= count) return -1;
144 
145  table->handles = heapReAlloc(table->handles, count * sizeof(struct object *));
146  memset(table->handles + table->count, 0, (count - table->count) * sizeof(struct object *));
147  table->count = count;
148 
149  assert(table->handles);
150  }
151 
152  table->free_begin = i + 1;
153  table->free_end = i + 1;
154  table->handles[i] = __objectAddRef(object);
155  return i;
156 }
157 
168 bool handleSet(struct handleTable *table, uint32_t handle, struct object *object)
169 {
170  struct object *old_object;
171  assert(object);
172 
173  if (handle >= MAX_HANDLES) return false;
174 
175  if (handle >= table->count)
176  {
177  uint32_t count = 2 * table->count;
178  while (count < handle) count *= 2;
179  if (count > MAX_HANDLES) count = MAX_HANDLES;
180  assert(count > table->count);
181 
182  table->handles = heapReAlloc(table->handles, count * sizeof(struct object *));
183  memset(table->handles + table->count, 0, (count - table->count) * sizeof(struct object *));
184  table->count = count;
185 
186  assert(table->handles);
187  }
188 
189  /* replace object */
190  old_object = table->handles[handle];
191  table->handles[handle] = __objectAddRef(object);
192 
193  /* update first free if necessary */
194  if (handle == table->free_begin)
195  table->free_begin = handle + 1;
196 
197  /* update (last used + 1) if necessary */
198  if (handle >= table->free_end)
199  table->free_end = handle + 1;
200 
201  if (old_object) __objectRelease(old_object);
202  return true;
203 }
204 
213 struct object *handleGet(struct handleTable *table, uint32_t handle)
214 {
215  if (handle >= table->free_end) return NULL;
216  return table->handles[handle];
217 }
218 
227 bool handleRelease(struct handleTable *table, uint32_t handle)
228 {
229  struct object *object;
230 
231  if (handle >= table->free_end) return false;
232  if (!(object = table->handles[handle])) return false;
233  table->handles[handle] = NULL;
234 
235  /* update first free if necessary */
236  if (handle < table->free_begin)
237  table->free_begin = handle;
238 
239  /* update (last used + 1) if necessary */
240  if (handle == table->free_end - 1)
241  {
242  /* decrease table->free_last till we hit the last used handle */
243  while (table->free_end > 0 && !table->handles[table->free_end - 1])
244  table->free_end--;
245 
246  if (table->free_end > MIN_HANDLES && table->free_end < table->count / 4)
247  {
248  uint32_t count = table->count / 4;
249  if (count < MIN_HANDLES) count = MIN_HANDLES;
250 
251  table->handles = heapReAlloc(table->handles, count * sizeof(struct object *));
252  table->count = count;
253 
254  assert(table->handles);
255  }
256  }
257 
258  __objectRelease(object);
259  return true;
260 }
261 
268 uint32_t handleCount(struct handleTable *table)
269 {
270  uint32_t i, count = 0;
271  for (i = 0; i < table->free_end; i++)
272  {
273  if (table->handles[i]) count++;
274  }
275  return count;
276 }
void handleForkTable(struct handleTable *destination, struct handleTable *source)
Forks a handle table.
Definition: handle.c:68
void * heapReAlloc(void *addr, uint32_t length)
Resizes a block of kernel memory.
Definition: allocator.c:439
void * heapAlloc(uint32_t length)
Allocates a block of kernel memory.
Definition: allocator.c:363
#define assert(ex)
Definition: util.h:61
void handleTableFree(struct handleTable *table)
Releases the memory of the handle table and all associated objects.
Definition: handle.c:94
#define MAX_HANDLES
Definition: handle.h:43
void * memset(void *ptr, int value, size_t num)
Fills a memory region with some specific byte value.
Definition: util.c:123
void heapFree(void *addr)
Deallocates a block of kernel memory.
Definition: allocator.c:385
Definition: object.h:69
uint32_t free_end
Definition: handle.h:49
uint32_t handleAllocate(struct handleTable *table, struct object *object)
Allocates a handle (index) for a specific kernel object.
Definition: handle.c:117
uint32_t free_begin
Definition: handle.h:48
struct object ** handles
Definition: handle.h:50
bool handleRelease(struct handleTable *table, uint32_t handle)
Releases the object associated with a handle.
Definition: handle.c:227
uint32_t handleCount(struct handleTable *table)
Returns the number of handles in a handletable.
Definition: handle.c:268
void handleTableInit(struct handleTable *table)
Initializes the handle table structure which is part of each process.
Definition: handle.c:48
struct object * handleGet(struct handleTable *table, uint32_t handle)
Returns the kernel object associated to a handle.
Definition: handle.c:213
bool handleSet(struct handleTable *table, uint32_t handle, struct object *object)
Associates a handle (index) with a kernel object.
Definition: handle.c:168
#define MIN_HANDLES
Definition: handle.h:42
uint32_t count
Definition: handle.h:47