Simple pool of threads which calculate the sum of a given number from the main process
It's hard to tell without seeing the code for InsertHead and PopTail, but I would not be surprised if you've got a race condition between the main thread's InsertHead and the worker thread's PopTail. The workers take mutex in order to prevent data races among themselves; but the main thread blithely pushes new data onto the list without taking mutex, which seems like it would cause a race in the case that the list had only one element.



Stylistically, I'd replace

int threads = 4;
int number, i;

pthread_t *threads_tab;
int *thread_args;

threads_tab = malloc(threads * sizeof(pthread_t));
thread_args = malloc(threads * sizeof(int));


with

pthread_t threads_tab[4];
int thread_args[4];


to save those heap allocations (which, by the way, you never free).

The variable i should be declared within the for loop:

for (int i = 0; i &lt; threads; i++) {


and the variable number should be declared where it's used:

int number = rand() % 100;




thread_args[i] = i;
pthread_create(&amp;threads_tab[i], NULL, sum, (void*) &amp;thread_args[i]);
[...]
printf(..., *(int *)ptr);


This is fine (and 100% correct, because it avoids implementation-defined casts!), but you should know that in practice most codebases will do simply

pthread_create(&amp;threads_tab[i], NULL, sum, (void*) i);
[...]
printf(..., (int)ptr);


The latter is technically implementation-defined, but on common platforms it works, and it works without any memory loads or stores, which is nice, so that's why people end up doing it.



You fail to check the return value of pthread_create, which is a pretty big deal in real code; it's easy for a process to run out of threads. See man pthread_create.



In English, accumulator has two cs.