Вы можете использовать глобальную переменную для всей программы.
int _fCloseThreads;
Установите значение 1, когда хотите, чтобы потоки прекратили выполнение. Пусть потоки проверят эту переменную в своем «цикле» и красиво выйдут, когда она установлена в 1. Нет необходимости защищать ее мьютексом.
Вам нужно дождаться завершения потоков. Вы можете использовать соединение. Другой способ заключается в увеличении счетчика, когда поток входит в свой поток, и затем декрицификации счетчика при выходе. Счетчик должен быть своего рода глобальным. Используйте gcc Atomic Ops на счетчике. Основной поток после установки fCloseThreads может ожидать на счетчике обнуления, зацикливаясь, спя и проверяя счетчик.
Наконец, вы можете проверить pthread_cleanup_push и pop. Они представляют собой модель, позволяющую потоку отменять любое место в своем коде (использует longjump) и затем вызывать функцию окончательной очистки перед выходом из threadproc. По сути, вы помещаете cleanup_push вверху вашего threadproc и cleanup_pop внизу, создаете функцию размотки, а затем в определенных точках отмены поток, отмененный вызовом pthread_cancel (), будет долго возвращаться к threadproc и вызывать функцию unwind.