CHDK_DE Vorschauversion  Trunk Rev. 5163
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
suba.c-Dateireferenz
#include "stdlib.h"
#include "stddef.h"
+ Include-Abhängigkeitsdiagramm für suba.c:

gehe zum Quellcode dieser Datei

Datenstrukturen

struct  cell_hdr
 
struct  _cell
 
struct  allocator
 

Makrodefinitionen

#define SUBA_SEMAPHORE_TIMEOUT   1000
 
#define SANITY_CHECKS   1
 
#define SUBA_MAGIC   0x53554241
 
#define CELL_MAGIC   0x5342434C
 
#define ALIGNMASK   (sizeof(cell*)-1)
 
#define ALIGN(s)   (((s) + ALIGNMASK) & ~ALIGNMASK)
 
#define ACTUALSIZE(size)   (size + sizeof(cell_hdr))
 
#define ALLOCSIZE(size)   (size - sizeof(cell_hdr))
 
#define CELL2ALLOC(c)   (void*)((void*)c + sizeof(cell_hdr))
 
#define ALLOC2CELL(p)   (cell*)((void*)p - sizeof(cell_hdr))
 
#define CEND(c)   ((cell*)((char*)c + c->h.size))
 
#define ISADJ(c1, c2)   (CEND(c1) == (c2))
 

Typdefinitionen

typedef struct _cell cell
 

Funktionen

static cellcheck_cell (const allocator *suba, cell *c, char *fn, int ln)
 
void suba_getmeminfo (allocator *suba, int *allocated_size, int *allocated_peak, int *allocated_count, int *free_size, int *largest_block, int *free_block_count)
 
allocatorsuba_init (allocator *suba, size_t size, size_t mincell, char *name)
 
void * suba_alloc (allocator *suba, size_t size, int zero)
 
int suba_free (allocator *suba, void *ptr)
 

Makro-Dokumentation

#define ACTUALSIZE (   size)    (size + sizeof(cell_hdr))

Definiert in Zeile 57 der Datei suba.c.

#define ALIGN (   s)    (((s) + ALIGNMASK) & ~ALIGNMASK)

Definiert in Zeile 55 der Datei suba.c.

#define ALIGNMASK   (sizeof(cell*)-1)

Definiert in Zeile 54 der Datei suba.c.

#define ALLOC2CELL (   p)    (cell*)((void*)p - sizeof(cell_hdr))

Definiert in Zeile 60 der Datei suba.c.

#define ALLOCSIZE (   size)    (size - sizeof(cell_hdr))

Definiert in Zeile 58 der Datei suba.c.

#define CELL2ALLOC (   c)    (void*)((void*)c + sizeof(cell_hdr))

Definiert in Zeile 59 der Datei suba.c.

#define CELL_MAGIC   0x5342434C

Definiert in Zeile 21 der Datei suba.c.

#define CEND (   c)    ((cell*)((char*)c + c->h.size))

Definiert in Zeile 62 der Datei suba.c.

#define ISADJ (   c1,
  c2 
)    (CEND(c1) == (c2))

Definiert in Zeile 63 der Datei suba.c.

#define SANITY_CHECKS   1

Definiert in Zeile 18 der Datei suba.c.

#define SUBA_MAGIC   0x53554241

Definiert in Zeile 20 der Datei suba.c.

#define SUBA_SEMAPHORE_TIMEOUT   1000

Definiert in Zeile 17 der Datei suba.c.

Dokumentation der benutzerdefinierten Typen

typedef struct _cell cell

Dokumentation der Funktionen

static cell* check_cell ( const allocator suba,
cell c,
char *  fn,
int  ln 
)
static

Definiert in Zeile 67 der Datei suba.c.

68 {
69  if (suba && (c > (cell*)suba) && (c < (cell*)((char*)suba + suba->size))) {
70  if (c->h.magic != CELL_MAGIC)
71  DebugAssert("Corrupt cell header", ln);
72  return c;
73  }
74  char buf[200];
75  sprintf(buf, "%s bad cell - %x %x", fn, c, suba);
76  DebugAssert(buf, ln);
77  return NULL;
78 }
void* suba_alloc ( allocator suba,
size_t  size,
int  zero 
)

Definiert in Zeile 304 der Datei suba.c.

305 {
306  cell *this_cell = NULL;
307 
308  // sanitise size & calc real size needed
309  size = ALIGN(size);
310  int cellsize = ACTUALSIZE(size);
311  if (cellsize < suba->mincell) cellsize = suba->mincell;
312 
314  {
315  // Find first block big enough to satisfy request
316  cell *prev_cell = &suba->head;
317  this_cell = check_cell(suba, prev_cell->next, "suba_alloc", __LINE__);
318  while (this_cell->h.size > 0 && this_cell->h.size < cellsize) {
319  prev_cell = this_cell;
320  this_cell = check_cell(suba, this_cell->next, "suba_alloc", __LINE__);
321  }
322 
323  // Check if block large enough was found
324  if (this_cell->h.size > 0) {
325  if (this_cell == suba->largest_block)
326  suba->largest_block = NULL; // Force recalculation of largest block in suba_getmeminfo
327 
328  if (this_cell->h.size > (cellsize + suba->mincell)) {
329  // split new cell - return from end of larger block
330  this_cell->h.size = this_cell->h.size - cellsize;
331  this_cell = CEND(this_cell);
332  this_cell->h.size = cellsize;
333  this_cell->h.magic = CELL_MAGIC;
334  suba->free_size -= cellsize;
335  } else {
336  // use the entire cell - unlink from free list
337  prev_cell->next = this_cell->next;
338  cellsize = this_cell->h.size;
339  suba->free_block_count -= 1;
340  suba->free_size -= ALLOCSIZE(cellsize);
341  }
342 
343  // CHDK counters
344  suba->allocated_size += ALLOCSIZE(cellsize);
345  suba->allocated_count++;
346  if(suba->allocated_size > suba->allocated_peak) {
347  suba->allocated_peak = suba->allocated_size;
348  }
349  } else {
350  this_cell = NULL;
351  }
352 
353  GiveSemaphore(suba->sem_id);
354  }
355  else
356  {
357  DebugAssert("suba_alloc TakeSemaphore fail", __LINE__);
358  }
359 
360  void *p = NULL;
361 
362  if (this_cell != NULL)
363  {
364  p = CELL2ALLOC(this_cell);
365  if (zero) memset(p, 0, ALLOCSIZE(cellsize));
366  }
367 
368  return p;
369 }
int suba_free ( allocator suba,
void *  ptr 
)

Definiert in Zeile 372 der Datei suba.c.

373 {
374  cell* this_cell = ALLOC2CELL(ptr);
375 
376 #if SANITY_CHECKS
377  // Sanity checks
378  check_cell(suba, this_cell, "suba_free", __LINE__);
379  if (this_cell->h.size > suba->size) {
380  DebugAssert("Trying to free bad block", __LINE__);
381  return -1;
382  }
383 #endif
384 
386  {
387  // CHDK counters
388  suba->allocated_size -= ALLOCSIZE(this_cell->h.size);
389  suba->allocated_count--;
390 
391  // List header
392  cell* prev_cell = &suba->head;
393 
394  // find insertion point
395  while (prev_cell->next < this_cell) {
396  prev_cell = check_cell(suba, prev_cell->next, "suba_free", __LINE__);
397  }
398  cell* next_cell = check_cell(suba, prev_cell->next, "suba_free", __LINE__);
399 
400  // do prev cell and this cell need to be joined?
401  if (ISADJ(prev_cell,this_cell)) {
402  suba->free_size += this_cell->h.size;
403  prev_cell->h.size += this_cell->h.size;
404  this_cell = prev_cell;
405  } else {
406  this_cell->next = prev_cell->next;
407  prev_cell->next = this_cell;
408  suba->free_block_count += 1;
409  suba->free_size += ALLOCSIZE(this_cell->h.size);
410  }
411 
412  // do this cell and next cell need to be joined?
413  if (ISADJ(this_cell,next_cell)) {
414  this_cell->next = next_cell->next;
415  this_cell->h.size += next_cell->h.size;
416  suba->free_block_count -= 1;
417  suba->free_size += sizeof(cell_hdr);
418  }
419 
420  // Update largest_block if null or this one is now bigger
421  if ((suba->largest_block != NULL) && (this_cell->h.size > suba->largest_block->h.size))
422  suba->largest_block = this_cell;
423 
424  GiveSemaphore(suba->sem_id);
425  }
426  else
427  {
428  DebugAssert("suba_free TakeSemaphore fail", __LINE__);
429  return -1;
430  }
431 
432  return 0;
433 }
void suba_getmeminfo ( allocator suba,
int *  allocated_size,
int *  allocated_peak,
int *  allocated_count,
int *  free_size,
int *  largest_block,
int *  free_block_count 
)

Definiert in Zeile 202 der Datei suba.c.

203 {
205  {
206  if (suba->magic != SUBA_MAGIC || *suba->magic2 != SUBA_MAGIC)
207  DebugAssert("suba_getmeminfo BAD MAGIC", __LINE__);
208 
209  // Find largest block if not currently known
210  if (suba->largest_block == NULL)
211  {
212  cell* largest = &suba->head;
213  cell* c = check_cell(suba, &suba->head, "suba_getmeminfo", __LINE__);
214  while (c->h.size != 0)
215  {
216  if (c->h.size > largest->h.size) largest = c;
217  c = check_cell(suba, c->next, "suba_getmeminfo", __LINE__);
218  }
219  suba->largest_block = largest;
220  }
221 
222  *largest_block = ALLOCSIZE(suba->largest_block->h.size);
223  *free_size = suba->free_size;
224  *free_block_count = suba->free_block_count;
225 
226  *allocated_size = suba->allocated_size;
227  *allocated_peak = suba->allocated_peak;
228  *allocated_count = suba->allocated_count;
229 
230 #ifdef SUBA_DEBUG
231  check_stats(suba);
232 #endif
233 
234  GiveSemaphore(suba->sem_id);
235  }
236  else
237  {
238  DebugAssert("suba_getmeminfo TakeSemaphore fail", __LINE__);
239  }
240 }
allocator* suba_init ( allocator suba,
size_t  size,
size_t  mincell,
char *  name 
)

Definiert in Zeile 243 der Datei suba.c.

244 {
245  size_t hdrsiz;
246 
247 #if SANITY_CHECKS
248  if (suba == NULL || size == 0) {
249  DebugAssert("Invalid parameters to 'suba_init'", __LINE__);
250  return NULL;
251  }
252 #endif
253 
254  size = size & ~ALIGNMASK;
255  hdrsiz = ALIGN(sizeof(allocator));
256  mincell = ACTUALSIZE(ALIGN(mincell));
257 
258  // Initialise allocator header
259  memset(suba, 0, hdrsiz);
260  suba->magic = SUBA_MAGIC;
261  // cell data must be large enough for next pointer
262  suba->mincell = sizeof(cell);
263  if (mincell > suba->mincell)
264  suba->mincell = mincell;
265  suba->size = size;
266  suba->sem_id = CreateBinarySemaphore(name, 1);
267 
268  // Initialise free list
269  cell *c1, *c2;
270 
271  // First cell - allocation block (size - header - empty terminator cell)
272  c1 = (cell*)((void*)suba + hdrsiz);
273  c1->h.size = size - hdrsiz - sizeof(cell);
274  c1->h.magic = CELL_MAGIC;
275 
276  // Second cell - list terminator (size = 0, next = 0)
277  c2 = CEND(c1);
278  c2->h.size = 0;
279  c2->h.magic = CELL_MAGIC;
280  c2->next = 0;
281 
282  // Link first to second, reduce size of first so it will never merge with second terminator cell
283  c1->next = c2;
284  c1->h.size -= sizeof(cell*);
285 
286  // Guard value at the end of the memory block;
287  suba->magic2 = (unsigned int*)CEND(c1);
288  *suba->magic2 = SUBA_MAGIC;
289 
290  // Initial stats
291  suba->free_block_count = 1;
292  suba->free_size = ALLOCSIZE(c1->h.size);
293  suba->largest_block = c1;
294 
295  // List head - dummy cell, separate from main block so will never be merged, too small to ever be allocated
296  suba->head.h.size = sizeof(cell_hdr);
297  suba->head.h.magic = CELL_MAGIC;
298  suba->head.next = c1;
299 
300  return suba;
301 }