K_LIST *_k_free_list(K_LIST *list, KLIST_FFL_ARGS) { int i; CHKLIST(list); if (list->is_store) { quithere(1, "List %s can't %s() a store" 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); for (i = 0; i < list->data_mem_count; i++) free(list->data_memory[i]); free(list->data_memory); if (list->lock) { cklock_destroy(list->lock); free(list->lock); } // local_list lists are not stored in all_klists if (!list->local_list) { K_LISTS *klists, *klists_prev = NULL; // not locked :P if (!lock_check_init) { quitfrom(1, file, func, line, "in %s(), lock_check_lock has not been initialised!", __func__); } ck_wlock(&lock_check_lock); klists = all_klists; while (klists && klists->klist != list) { klists_prev = klists; klists = klists->next; } if (!klists) { quitfrom(1, file, func, line, "in %s(), list %s not in klists", __func__, list->name); } else { if (klists_prev) klists_prev->next = klists->next; else all_klists = klists->next; free(klists); } ck_wunlock(&lock_check_lock); } free(list); return NULL; }
void _cksem_wait(sem_t *sem, const char *file, const char *func, const int line) { if (unlikely(sem_wait(sem))) { if (errno == EINTR) return; quitfrom(1, file, func, line, "Failed to sem_wait errno=%d sem=0x%p", errno, sem); } }
/* Make every locking attempt warn if we're unable to get the lock for more * than 10 seconds and fail if we can't get it for longer than a minute. */ void _mutex_lock(mutex_t *lock, const char *file, const char *func, const int line) { int ret, retries = 0; retry: ret = _mutex_timedlock(lock, 10, file, func, line); if (unlikely(ret)) { if (likely(ret == ETIMEDOUT)) { LOGERR("WARNING: Prolonged mutex lock contention from %s %s:%d, held by %s %s:%d", file, func, line, lock->file, lock->func, lock->line); if (++retries < 6) goto retry; quitfrom(1, file, func, line, "FAILED TO GRAB MUTEX!"); } quitfrom(1, file, func, line, "WTF MUTEX ERROR ON LOCK!"); } }
void _rd_lock(rwlock_t *lock, const char *file, const char *func, const int line) { int ret, retries = 0; retry: ret = rd_timedlock(&lock->rwlock, 10); if (unlikely(ret)) { if (likely(ret == ETIMEDOUT)) { LOGERR("WARNING: Prolonged read lock contention from %s %s:%d, held by %s %s:%d", file, func, line, lock->file, lock->func, lock->line); if (++retries < 6) goto retry; quitfrom(1, file, func, line, "FAILED TO GRAB READ LOCK!"); } quitfrom(1, file, func, line, "WTF ERROR ON READ LOCK!"); } lock->file = file; lock->func = func; lock->line = line; }
int _cksem_mswait(sem_t *sem, int ms, const char *file, const char *func, const int line) { ts_t abs_timeout, ts_now; tv_t tv_now; int ret; tv_time(&tv_now); tv_to_ts(&ts_now, &tv_now); ms_to_ts(&abs_timeout, ms); timeraddspec(&abs_timeout, &ts_now); ret = sem_timedwait(sem, &abs_timeout); if (ret) { if (likely(errno == ETIMEDOUT)) return ETIMEDOUT; if (errno == EINTR) return EINTR; quitfrom(1, file, func, line, "Failed to sem_timedwait errno=%d sem=0x%p", errno, sem); } return 0; }
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; }
void _cksem_destroy(sem_t *sem, const char *file, const char *func, const int line) { if (unlikely(sem_destroy(sem))) quitfrom(1, file, func, line, "Failed to sem_destroy errno=%d sem=0x%p", errno, sem); }
void _cksem_init(sem_t *sem, const char *file, const char *func, const int line) { int ret; if ((ret = sem_init(sem, 0, 0))) quitfrom(1, file, func, line, "Failed to sem_init ret=%d errno=%d", ret, errno); }
void _cond_init(pthread_cond_t *cond, const char *file, const char *func, const int line) { if (unlikely(pthread_cond_init(cond, NULL))) quitfrom(1, file, func, line, "Failed to pthread_cond_init!"); }
void _rwlock_init(rwlock_t *lock, const char *file, const char *func, const int line) { if (unlikely(pthread_rwlock_init(&lock->rwlock, NULL))) quitfrom(1, file, func, line, "Failed to pthread_rwlock_init"); }
void _rw_unlock(rwlock_t *lock, const char *file, const char *func, const int line) { if (unlikely(pthread_rwlock_unlock(&lock->rwlock))) quitfrom(1, file, func, line, "WTF RWLOCK ERROR ON UNLOCK!"); }
/* Does not unset lock->file/func/line since they're only relevant when the lock is held */ void _mutex_unlock(mutex_t *lock, const char *file, const char *func, const int line) { if (unlikely(pthread_mutex_unlock(&lock->mutex))) quitfrom(1, file, func, line, "WTF MUTEX ERROR ON UNLOCK!"); }