if (old_length = length + 12){uses an assignment (=) instead of (==), which is always true. The compiler warns. You ignore the warning, your code does not work. An avoidable mistake.
static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;or by calling pthread_mutex_init().
pthread_mutex_lock(&lock); return list_size(&used_list); pthread_mutex_unlock(&lock);You don't unlock the mutex, ever.
pthread_mutex_lock(&lock); if (*) return NULL; pthread_mutex_unlock(&lock);You don't unlock if (*) is true. In general, you need to unlock the mutex on all paths leaving the function.
size_t mem_sizeof_free_list(void) { pthread_mutex_lock(&my_mutex); // leave this function alone dangerous threads if(!list_empty(&free_list)) { pthread_mutex_unlock(&my_mutex); // release the function return list_size(&free_list); // take adantage of lists count } else { pthread_mutex_unlock(&my_mutex); // release the function return 0; } }The correct way to write this code is
size_t mem_sizeof_free_list(void) { pthread_mutex_lock(&my_mutex); size_t sz = list_size(&free_list); pthread_mutex_unlock(&my_mutex); return sz; }Note that 'sz' is declared as a local variable. Local variable are not shared among threads. Thus, we store the result of list_size() - which has to be inside lock/unlock - into a variable that is not shared and which can therefore be safely accessed after the unlock.
My advice is to heed the warning about nesting level (no more than 3), but because of today's larger screens, we will not grade you down if comments stretch past 80 columns. (It's still hard to print such code, though.)
list_insert(list_begin(&list), &blk->elem);Use list_push_front(&list, &blk->elem); instead. (Slightly slower, but a lot more readable.) Similarly, use list_push_back instead of list_insert(list_end(...), ...).