static void *allocate_block(int order) { struct block *buddy; struct block *p; if (order > MAX_ORDER) abort(); p = blocks_orders[order]; if (p) { assert(p->pprev == blocks_orders + order); dequeue_free(p); assert(((struct free_block *)p)->order == order); goto out; } if (order == MAX_ORDER) return allocate_max_order_block(); /* * struct block *blocks_orders_snapshot[MAX_ORDER+1]; * memcpy(blocks_orders_snapshot, blocks_orders, sizeof(blocks_orders)); */ p = (struct block *)allocate_block(order+1) - 1; buddy = (struct block *)((char *)p + (1 << order)); buddy->next = USED_MARKER; buddy->pprev = 0; enqueue_free(buddy, order); out: return p + 1; }
static void _free_job_queues(void) { dequeue_t * queue = NULL; for(int i = 0; i < NUM_JOB_QUEUES; i++) { queue = _job_queues[i]; if(queue != NULL) { dequeue_free(queue); } } }
static void free_block(void *ptr, int order) { struct block *p = (struct block *)ptr - 1; assert(p->next == USED_MARKER); if (order < MAX_ORDER) { struct block *buddy = (struct block *)((intptr_t)p ^ (1 << order)); if (buddy->next != USED_MARKER && (((struct free_block *)buddy)->order == order)) { /* if buddy is free as well with same order, we should combine * with it, by first unlinking it from * free-list */ dequeue_free(buddy); if (buddy > p) buddy = p; free_block(buddy+1, order+1); return; } } enqueue_free(p, order); }