/* * Unlink and return the head of the list * If the list is empty: * 1) If it's a store - return NULL * 2) alloc a new list and return the head - * which is NULL if the list limit has been reached */ K_ITEM *_k_unlink_head(K_LIST *list, LOCK_MAYBE bool chklock, KLIST_FFL_ARGS) { K_ITEM *item; CHKLS(list); _LIST_WRITE(list, chklock, file, func, line); if (!(list->head) && !(list->is_store)) k_alloc_items(list, KLIST_FFL_PASS); if (!(list->head)) return NULL; item = list->head; list->head = item->next; if (list->head) list->head->prev = NULL; else { if (list->do_tail) list->tail = NULL; } item->prev = item->next = NULL; list->count--; return item; }
K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit, bool do_tail, KLIST_FFL_ARGS) { K_LIST *list; if (allocate < 1) quithere(1, "Invalid new list %s with allocate %d must be > 0", name, allocate); if (limit < 0) quithere(1, "Invalid new list %s with limit %d must be >= 0", name, limit); list = calloc(1, sizeof(*list)); if (!list) quithere(1, "Failed to calloc list %s", name); list->is_store = false; list->lock = calloc(1, sizeof(*(list->lock))); if (!(list->lock)) quithere(1, "Failed to calloc lock for list %s", name); cglock_init(list->lock); list->name = name; list->siz = siz; list->allocate = allocate; list->limit = limit; list->do_tail = do_tail; k_alloc_items(list, KLIST_FFL_PASS); return list; }
/* * Unlink and return the head of the list * If the list is empty: * 1) If it's a store - return NULL * 2) alloc a new list and return the head - * which is NULL if the list limit has been reached */ K_ITEM *_k_unlink_head(K_LIST *list, KLIST_FFL_ARGS) { K_ITEM *item; if (!(list->head) && !(list->is_store)) k_alloc_items(list, KLIST_FFL_PASS); if (!(list->head)) return NULL; item = list->head; list->head = item->next; if (list->head) list->head->prev = NULL; else { if (list->do_tail) list->tail = NULL; } item->prev = item->next = NULL; list->count--; return item; }
static void k_cull_list(K_LIST *list, KLIST_FFL_ARGS) { int i; CHKLIST(list); _LIST_WRITE(list, true, file, func, line); if (list->is_store) { quithere(1, "List %s can't %s() a store" KLIST_FFL, list->name, __func__, KLIST_FFL_PASS); } if (list->is_lock_only) { quithere(1, "List %s can't %s() a lock_only" KLIST_FFL, list->name, __func__, KLIST_FFL_PASS); } if (list->count != list->total) { quithere(1, "List %s can't %s() a list in use" KLIST_FFL, list->name, __func__, KLIST_FFL_PASS); } for (i = 0; i < list->item_mem_count; i++) free(list->item_memory[i]); free(list->item_memory); list->item_memory = NULL; list->item_mem_count = 0; for (i = 0; i < list->data_mem_count; i++) free(list->data_memory[i]); free(list->data_memory); list->data_memory = NULL; list->data_mem_count = 0; list->total = list->count = list->count_up = 0; list->head = list->tail = NULL; list->cull_count++; k_alloc_items(list, KLIST_FFL_PASS); }
K_LIST *_k_new_list(const char *name, size_t siz, int allocate, int limit, bool do_tail, bool lock_only, bool without_lock, bool local_list, const char *name2, int cull_limit, KLIST_FFL_ARGS) { K_LIST *list; if (allocate < 1) quithere(1, "Invalid new list %s with allocate %d must be > 0", name, allocate); if (limit < 0) quithere(1, "Invalid new list %s with limit %d must be >= 0", name, limit); /* after culling, the first block of items are again allocated, * so there's no point culling a single block of items */ if (cull_limit > 0 && cull_limit <= allocate) quithere(1, "Invalid new list %s with cull_limit %d must be > allocate (%d)", name, cull_limit, allocate); list = calloc(1, sizeof(*list)); if (!list) quithere(1, "Failed to calloc list %s", name); list->master = list; list->is_store = false; list->is_lock_only = lock_only; list->local_list = local_list; if (without_lock) list->lock = NULL; else { list->lock = calloc(1, sizeof(*(list->lock))); if (!(list->lock)) quithere(1, "Failed to calloc lock for list %s", name); cklock_init(list->lock); } list->name = name; list->name2 = name2; list->siz = siz; list->allocate = allocate; list->limit = limit; list->do_tail = do_tail; list->cull_limit = cull_limit; list->next_store = list->prev_store = NULL; if (!(list->is_lock_only)) k_alloc_items(list, KLIST_FFL_PASS); /* Don't want to keep track of short lived (tree) lists * since they wont use locking anyway */ if (!list->local_list) { K_LISTS *klists; // not locked :P if (!lock_check_init) { quitfrom(1, file, func, line, "in %s(), lock_check_lock has not been initialised!", __func__); } klists = calloc(1, sizeof(*klists)); if (!klists) quithere(1, "Failed to calloc klists %s", name); klists->klist = list; ck_wlock(&lock_check_lock); klists->next = all_klists; all_klists = klists; ck_wunlock(&lock_check_lock); } return list; }