CHDK_DE Vorschauversion  Trunk Rev. 5830
 Alle Datenstrukturen Dateien Funktionen Variablen Typdefinitionen Aufzählungen Aufzählungswerte Makrodefinitionen
suba.c-Dateireferenz
#include "stdlib.h"
#include "stddef.h"
#include "string.h"
#include "semaphore.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 59 der Datei suba.c.

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

Definiert in Zeile 57 der Datei suba.c.

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

Definiert in Zeile 56 der Datei suba.c.

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

Definiert in Zeile 62 der Datei suba.c.

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

Definiert in Zeile 60 der Datei suba.c.

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

Definiert in Zeile 61 der Datei suba.c.

#define CELL_MAGIC   0x5342434C

Definiert in Zeile 23 der Datei suba.c.

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

Definiert in Zeile 64 der Datei suba.c.

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

Definiert in Zeile 65 der Datei suba.c.

#define SANITY_CHECKS   1

Definiert in Zeile 20 der Datei suba.c.

#define SUBA_MAGIC   0x53554241

Definiert in Zeile 22 der Datei suba.c.

#define SUBA_SEMAPHORE_TIMEOUT   1000

Definiert in Zeile 19 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 69 der Datei suba.c.

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

Definiert in Zeile 306 der Datei suba.c.

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

Definiert in Zeile 374 der Datei suba.c.

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

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

Definiert in Zeile 245 der Datei suba.c.

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