С потоком обычно связана небольшая структура, контекст потока. Эта структура может быть заполнена всеми частями данных, которые необходимы для работы потока.
Например, корень структуры данных, необходимый для доступа к специфичным для потока ключам этого потока и для их итерации по ним, чтобы очистить их при завершении работы.
В этой структуре обычно есть мьютекс-подобная блокировка, и, возможно, более одной для разных секций.
Контекст потока может иметь небольшое поле, в котором завершающий поток может поместить свой статус выхода. (void *
возвращается pthread_exit
или возвращением из функции потока.)
Контекст потока также может указывать состояние потока (еще не создано, работает, остановлено).
Может существовать примитив синхронизации, такой как условная переменная или семафор, который поток может kick
после подготовки состояния завершения и указания, что он завершается.
Функция pthread_join
может ожидать этого примитива синхронизации. По завершении ожидания функция может инициировать очистку ресурса для этого потока в дополнение к извлечению статуса.
Поток продолжает выполняться после сообщения о соединении. Для этого он должен продолжать иметь контекст со стеком. После этого система должна решить проблему чистой остановки потока в фоновом режиме.
Реализация потоков в пользовательском пространстве может отложить это до ядра. Например. какой-то сигнал может сработать или что-то еще, что указывает на завершение потока. В этот момент пользовательское пространство знает, что поток больше не может использовать свой стек, и может его переработать.
В ядре планировщик может «съесть» поток. Поток может вызвать некоторую функцию в планировщике, которая никогда не возвращается после очистки большинства своих ресурсов. Он помечает поток как мертвый и переключает контекст на другой поток. Стек потока никогда не будет использоваться снова (так как эта функция никогда не вернется) и может быть восстановлен, а также его структура задачи и все оставшиеся элементы, связанные с ним.