title: pthread_cleanup_push(3)

summary: помещает и выталкивает очищающие

text:
# pthread_cleanup_push(3)

## ИМЯ
pthread_cleanup_push, pthread_cleanup_pop - помещает и выталкивает очищающие обработчики при отмене нити

## ОБЗОР

```
#include <pthread.h>
```

```
void pthread_cleanup_push(void (*routine)(void *),
                          void *arg);
void pthread_cleanup_pop(int execute);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Данные функции управляют стеком нити, вызывающим очищающие обработчики при отмене нити. Очищающий обработчик — это функция, которая автоматически вызывается при отмене нити (или в при других обстоятельствах, описанных ниже); это может быть, например, отмена блокировки мьютекса, при которой он становится доступным другим нитям процесса.

Функция pthread_cleanup_push() помещает обработчик routine наверх стека очищающих обработчиков. Позднее, при вызове routine, ему будет передан arg в качестве аргумента.

Функция pthread_cleanup_pop() удаляет обработчик с вершины стека очищающих обработчиков, и, возможно, выполняет его, если execute не равно нулю.

Очищающий обработчик при отмене выталкивается из стека и выполняется при следующих условиях:

1.

Когда нить отменяется, все очищающие обработчики из стека выталкиваются и вызываются в обратном порядке их помещения в стек.

2.

Когда нить завершается вызовом pthread_exit(3), все очищающие обработчики выполняются как описано в предыдущем пункте (очищающие обработчики не вызываются, если нить завершается возвратом из начальной функции нити).

3.

Когда нить вызывает pthread_cleanup_pop() с ненулевым значением аргумента execute, самый верхний очищающий обработчик выталкивается и выполняется.

В POSIX.1 допускается реализация pthread_cleanup_push() и pthread_cleanup_pop() в виде макросов, которые раскрывают текст, содержащий '{' и '}', соответственно. По этой причине, вызывающий должен убедиться, что вызовы этих функций используются парно в одной функции и на одном лексическом уровне вложенности (другими словами, очищающий обработчик устанавливается только во время выполнения определённой секции кода).

Вызов longjmp(3) (siglongjmp(3)) приводит к непредсказуемым результатам, если был сделан любой вызов в pthread_cleanup_push() или pthread_cleanup_pop() без соответствующего вызову пары, так как буфер перехода (jump buffer) был заполнен setjmp(3) (sigsetjmp(3)). Подобным образом, вызов longjmp(3) (siglongjmp(3)) изнутри очищающего обработчика приводит к непредсказуемым результатам, если буфер перехода также не был заполнен setjmp(3) (sigsetjmp(3)) внутри обработчика.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Данные функции не возвращают никаких значений.

## ОШИБКИ
Эти функции не вызывают ошибок.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_cleanup_push(), pthread_cleanup_pop()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
В Linux, функции pthread_cleanup_push() и pthread_cleanup_pop() реализованы в виде макросов, которые расширяются до текста, содержащего '{' и '}', соответственно. Это означает, что переменные, объявленные внутри области парных вызовов этих функций, будут видимы внутри только этой области.

В POSIX.1 сказано, что результат использования return, break, continue или goto для преждевременного оставления блока, окружающего pthread_cleanup_push() и pthread_cleanup_pop(), не определён. В переносимых приложениях не нужно так делать.

## ПРИМЕР
Далее показан простой пример использования функций, описанных на этой странице. Программа создаёт нить, которая выполняет цикл обрамлённый pthread_cleanup_push() и pthread_cleanup_pop(). В этом цикле каждую секунду увеличивается глобальная переменная cnt. В зависимости от аргументов командной строки главная нить посылает другой нити запрос на отмену или изменяет глобальную переменную, что заставляет другую нить выйти из цикла и завершить работу (с помощью return).

В этом сеансе главная нить посылает запрос отмены другой нити:

```
$ ./a.out
Запущена новая нить
cnt = 0
cnt = 1
Отменяем нить
Вызван очищающий обработчик
Нить отменена; cnt = 0
```

Здесь мы видим, что нить была отменена и что был вызван очищающий обработчик и он сбросил значение глобальной переменной cnt в 0.

В следующем сеансе главная программа изменяет глобальную переменную, что вызывает штатное завершение другой нити:

```
$ ./a.out x
Запущена новая нить
cnt = 0
cnt = 1
Нить завершилась штатным образом; cnt = 2
```

Здесь мы видим, что очищающий обработчик не вызывался (так как cleanup_pop_arg равно 0), и поэтому значение cnt не сброшено.

В следующем сеансе главная программа изменяет глобальную переменную, что вызывает штатное завершение другой нити, передаёт ненулевое значение в cleanup_pop_arg:

```
$ ./a.out x 1
Запущена новая нить
cnt = 0
cnt = 1
Вызван очищающий обработчик
Нить завершилась штатным образом; cnt = 0
```

Здесь мы видим, что хотя нить не отменена, всё же вызван очищающий обработчик, так как в pthread_cleanup_pop() передан ненулевой аргумент.

### Исходный код программы

```
#include <pthread.h>
#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static int done = 0;
static int cleanup_pop_arg = 0;
static int cnt = 0;
static void
cleanup_handler(void *arg)
{

    printf("Вызван очищающий обработчик\n");

    cnt = 0;
}
static void *
thread_start(void *arg)
{

    time_t start, curr;

    printf("Запущена новая нить\n");

    pthread_cleanup_push(cleanup_handler, NULL);

    curr = start = time(NULL);

    while (!done) {

        pthread_testcancel();           /* точка отмены */

        if (curr < time(NULL)) {

            curr = time(NULL);

            printf("cnt = %d\n", cnt);  /* точка отмены */

            cnt++;

        }

    }

    pthread_cleanup_pop(cleanup_pop_arg);

    return NULL;
}
int
main(int argc, char *argv[])
{

    pthread_t thr;

    int s;

    void *res;

    s = pthread_create(&thr, NULL, thread_start, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_create");

    sleep(2);           /* даём время нити запуститься */

    if (argc > 1) {

        if (argc > 2)

            cleanup_pop_arg = atoi(argv[2]);

        done = 1;

    } else {

        printf("Отменяем нить\n");

        s = pthread_cancel(thr);

        if (s != 0)

            handle_error_en(s, "pthread_cancel");

    }

    s = pthread_join(thr, &res);

    if (s != 0)

        handle_error_en(s, "pthread_join");

    if (res == PTHREAD_CANCELED)

        printf("Нить была отменена; cnt = %d\n", cnt);

    else

        printf("Нить завершилась штатным образом; cnt = %d\n", cnt);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
pthread_cancel(3), pthread_cleanup_push_defer_np(3), pthread_setcancelstate(3), pthread_testcancel(3), pthreads(7)


package: man-pages-ru

title: pthread_cleanup_push_defer_np(3)

summary: добавляет и

text:
# pthread_cleanup_push_defer_np(3)

## ИМЯ
pthread_cleanup_push_defer_np, pthread_cleanup_pop_restore_np - добавляет и удаляет очищающие обработчики отмены нити при сохранении типа отмены

## ОБЗОР

```
#include <pthread.h>
```

```
void pthread_cleanup_push_defer_np(void (*routine)(void *),
                                   void *arg);
void pthread_cleanup_pop_restore_np(int execute);
```

Компилируется и компонуется вместе с -pthread.

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

pthread_cleanup_push_defer_np(), pthread_cleanup_pop_defer_np():

_GNU_SOURCE

## ОПИСАНИЕ
Эти функции работают также как pthread_cleanup_push(3) и pthread_cleanup_pop(3), за исключением различий, описанных в данной справочной странице.

Подобно pthread_cleanup_push(3), pthread_cleanup_push_defer_np() добавляет routine в стек нити к очищающим обработчикам отмены. Кроме этого, она также сохраняет текущий тип отмены нити, и изменяет тип отмены на «отложенный» (смотрите pthread_setcanceltype(3)); это гарантирует, что очистка при отмене произойдёт даже, если тип отмены нити перед вызовом был «асинхронный».

Подобно pthread_cleanup_pop(3), pthread_cleanup_pop_restore_np() удаляет самый верхний очищающий обработчик из стека нити очищающих обработчиков отмены. Кроме этого, она восстанавливает тип отмены нити в значение на момент, когда была вызвана pthread_cleanup_push_defer_np().

Вызывающий должен гарантировать, что вызовы этих функций будут попарными внутри одной функции, и на одном лексическом уровне вложенности. Остальные ограничения описаны в pthread_cleanup_push(3).

Последовательность вызовов:

```
pthread_cleanup_push_defer_np(routine, arg);
pthread_cleanup_pop_restore_np(execute);
```

эквивалентна (но короче и эффективнее):

```
int oldtype;
pthread_cleanup_push(routine, arg);
pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, &oldtype);
...
pthread_setcanceltype(oldtype, NULL);
pthread_cleanup_pop(execute);
```

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные функции являются не стандартизированными расширениями GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## СМОТРИТЕ ТАКЖЕ
pthread_cancel(3), pthread_cleanup_push(3), pthread_setcancelstate(3), pthread_testcancel(3), pthreads(7)


title: pthread_create(3)

summary: создаёт новую нить

text:
# pthread_create(3)

## ИМЯ
pthread_create - создаёт новую нить

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
                   void *(*start_routine) (void *), void *arg);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
Функция pthread_create() запускает новую нить в вызвавшем процессе. Новая нить начинает выполнение вызовом start_routine(); значение arg является единственным аргументом start_routine().

Новая нить завершает работу в одном из следующих случаев:

- Она вызывает pthread_exit(3), указывая код выхода, доступное другой нити в том же процессе, вызвавшей pthread_join(3).

- При возврате из start_routine(). Это эквивалентно вызову pthread_exit(3) со значением, переданным в операторе return.

- При её отмене (смотрите pthread_cancel(3)).

- При вызове из любой нити процесса функции exit(3), или если главная нить выполняет возврат из main(). Это вызывает завершение всех нитей процесса.

Аргумент attr указывает на структуру pthread_attr_t, чьё содержимое используется при создании нити для определения атрибутов новой нити; эта структура инициализируется с помощью pthread_attr_init(3) и подобными функциями. Если значение attr равно NULL, то нити создаётся с атрибутами по умолчанию.

Перед возвратом успешный вызов pthread_create() сохраняет ID новой нити в буфер, на который указывает thread; этот идентификатор используется для ссылки на нить в последующих вызовах других функций pthreads.

Новая нить наследует копию сигнальной маски создавшей нити (pthread_sigmask(3)). Набор ожидающих сигналов новой нити пуст (sigpending(2)). Новая нить не наследует альтернативный стек сигналов создавшей нити (sigaltstack(2)).

Новая нить наследует окружение плавающей запятой вызвавшей нити (fenv(3)).

Начальное значение часов ЦП новой нити равно 0 (смотрите pthread_getcpuclockid(3)).

### Информация, касающаяся только Linux
Новая нить наследует копию набора мандатов вызвавшей нити (смотрите capabilities(7)) и маску увязывания ЦП (смотрите sched_setaffinity(2)).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_create() возвращается 0; при ошибке возвращается номер ошибки, а содержимое *thread не определено.

## ОШИБКИ
EAGAIN

Недостаточно ресурсов для создания другой нити.

EAGAIN

Возникло системного ограничение на количество нитей. Есть несколько ограничений, которые могут вызвать эту ошибку: был достигнут мягкий ограничитель RLIMIT_NPROC (задаётся с помощью setrlimit(2)), который ограничивает количество процессов и ните для реального ID пользователя; был достигнут ядерный системный ограничитель на количество процессов и нитей, /proc/sys/kernel/threads-max (смотрите proc(5)); был достигнуто максимальное количество PID, /proc/sys/kernel/pid_max (смотрите proc(5)).

EINVAL

Некорректные значения в attr.

EPERM

Нет прав на изменение алгоритма планирования и параметров, указанных в attr.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_create()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Дополнительную информацию об идентификаторе нити, возвращаемом pthread_create() в *thread смотрите в pthread_self(3). Если не используются алгоритмы планирования реального времени после вызова pthread_create() невозможно сказать какая нить — создавшая или новая — будет выполняться далее первой.

Нить может быть присоединяема (joinable) или отключённой (detached). Если нить присоединяема, то другая нить может вызвать pthread_join(3) для ожидания завершения нити и получения её кода выхода. Освобождение ресурсов обратно в систему у завершённой присоединяемой нити происходит только после её присоединения. При завершении отключённой нити, её ресурсы автоматически освобождаются обратно в систему: к ней невозможно присоединиться для получения её кода выхода. Создание отключённых нитей полезно в некоторых типах служебных нитей, чей код выхода не нужен приложению. По умолчанию новая нить создаётся в присоединяемом состоянии, если в attr не указано создание нити в отключённом состоянии (с помощью pthread_attr_setdetachstate(3)).

В реализации нитей NPTL, если мягкое ограничение ресурса RLIMIT_STACK в момент запуска программы не равно «unlimited», то им задаётся размер стека по умолчанию для новых нитей. Чтобы получить размер стека, отличный от умолчательного при создании новой нити, можно изменить атрибут размера стека в аргументе attr с помощью pthread_attr_setstacksize(3). Если ресурс RLIMIT_STACK равен «unlimited», то для размера используется значение, определённое для архитектуры. Вот значения для некоторых архитектур:

Архитектура

Размер стека умолчанию

i386

2 МБ

IA-64

32 МБ

PowerPC

4 МБ

S/390

2 МБ

Sparc-32

2 МБ

Sparc-64

4 МБ

x86_64

2 МБ

## ДЕФЕКТЫ
В устаревшей реализации LinuxThreads каждая нить процесса имеет свой неодинаковый ID процесса. Это нарушает спецификацию нитей POSIX и является источником многих других несоответствий стандарту; смотрите pthreads(7).

## ПРИМЕР
Представленная ниже программа показывает использование pthread_create(), а также других функций программного интерфейса pthreads.

В этом сеансе в системе с реализацией нитей NPTL размер стека по умолчанию берётся из значения ограничения ресурса на «размер стека»:

```
$ ulimit -s
8192            # ограничение на размер стека 8 МБ (0x800000 байт)
$ ./a.out hola salut servus
Нить 1: вершина стека около 0xb7dd03b8; argv_string=hola
Нить 2: вершина стека около 0xb75cf3b8; argv_string=salut
Нить 3: вершина стека около 0xb6dce3b8; argv_string=servus
Присоединение нити 1; получено значение возврата HOLA
Присоединение нити 2; получено значение возврата SALUT
Присоединение нити 3; получено значение возврата SERVUS
```

В этом сеансе программа явно устанавливает размер стека в 1 МБ (с помощью pthread_attr_setstacksize(3)) для создаваемых нитей:

```
$ ./a.out -s 0x100000 hola salut servus
Нить 1: вершина стека около 0xb7d723b8; argv_string=hola
Нить 2: вершина стека около 0xb7c713b8; argv_string=salut
Нить 3: вершина стека около 0xb7b703b8; argv_string=servus
Присоединение нити 1; получено значение возврата HOLA
Присоединение нити 2; получено значение возврата SALUT
Присоединение нити 3; получено значение возврата SERVUS
```

### Исходный код программы

```
#include <pthread.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error(msg) \

        do { perror(msg); exit(EXIT_FAILURE); } while (0)
struct thread_info {    /* используется как аргумент thread_start() */

    pthread_t thread_id;        /* ID, полученный от pthread_create() */

    int       thread_num;       /* номер нити, определяемый

                                   приложением */

    char     *argv_string;      /* аргумент из командой строки */
};
/* Начальная функция нити: показывает адрес около вершины нашего стека,

   и возвращает копию argv_string заглавными буквами */
static void *
thread_start(void *arg)
{

    struct thread_info *tinfo = arg;

    char *uargv, *p;

    printf("Нить %d: вершина стека около %p; argv_string=%s\n",

            tinfo->thread_num, &p, tinfo->argv_string);

    uargv = strdup(tinfo->argv_string);

    if (uargv == NULL)

        handle_error("strdup");

    for (p = uargv; *p != '\0'; p++)

        *p = toupper(*p);

    return uargv;
}
int
main(int argc, char *argv[])
{

    int s, tnum, opt, num_threads;

    struct thread_info *tinfo;

    pthread_attr_t attr;

    int stack_size;

    void *res;

    /* Параметром «-s» определяется размер стека в наших нитях */

    stack_size = -1;

    while ((opt = getopt(argc, argv, "s:")) != -1) {

        switch (opt) {

        case 's':

            stack_size = strtoul(optarg, NULL, 0);

            break;

        default:

            fprintf(stderr, "Исп.: %s [-s размер стека] арг...\n",

                    argv[0]);

            exit(EXIT_FAILURE);

        }

    }

    num_threads = argc - optind;

    /* инициализация атрибутов создания нити */

    s = pthread_attr_init(&attr);

    if (s != 0)

        handle_error_en(s, "pthread_attr_init");

    if (stack_size > 0) {

        s = pthread_attr_setstacksize(&attr, stack_size);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setstacksize");

    }

    /* выделение памяти для аргументов pthread_create() */

    tinfo = calloc(num_threads, sizeof(struct thread_info));

    if (tinfo == NULL)

        handle_error("calloc");

    /* создание по одной нити на каждый аргумент командной строки */

    for (tnum = 0; tnum < num_threads; tnum++) {

        tinfo[tnum].thread_num = tnum + 1;

        tinfo[tnum].argv_string = argv[optind + tnum];

        /* вызов pthread_create() сохраняет ID нити в

           соответствующий элемент tinfo[] */

        s = pthread_create(&tinfo[tnum].thread_id, &attr,

                           &thread_start, &tinfo[tnum]);

        if (s != 0)

            handle_error_en(s, "pthread_create");

    }

    /* уничтожение объекта атрибутов нити, так как он

       больше не нужен */

    s = pthread_attr_destroy(&attr);

    if (s != 0)

        handle_error_en(s, "pthread_attr_destroy");

    /* теперь присоединяем каждую нить и показываем значение,

       возвращённое ею */

    for (tnum = 0; tnum < num_threads; tnum++) {

        s = pthread_join(tinfo[tnum].thread_id, &res);

        if (s != 0)

            handle_error_en(s, "pthread_join");

        printf("Присоединение нити %d; получено значение возврата %s\n",

                tinfo[tnum].thread_num, (char *) res);

        free(res);      /* освобождаем память, выделенную нитью */

    }

    free(tinfo);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
getrlimit(2), pthread_attr_init(3), pthread_cancel(3), pthread_detach(3), pthread_equal(3), pthread_exit(3), pthread_getattr_np(3), pthread_join(3), pthread_self(3), pthread_setattr_default_np(3), pthreads(7)


title: pthread_detach(3)

summary: отсоединяет нить

text:
# pthread_detach(3)

## ИМЯ
pthread_detach - отсоединяет нить

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_detach(pthread_t thread);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
Функция pthread_detach() помечает нить, указанную thread, как отсоединённую. Когда отсоединённая нить завершается, её ресурсы автоматически отдаются обратно системе и не нужно объединять другую нить с завершившей работу.

Попытка отсоединить уже отсоединённую нить приводит к непредсказуемым последствиям.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_detach() возвращается 0; при ошибке возвращается номер ошибки.

## ОШИБКИ
EINVAL

Нить thread не является присоединяемой.

ESRCH

Нить с идентификатором thread не найдена.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_detach()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
После отсоединения нить её нельзя обратно присоединить с помощью pthread_join(3) или снова сделать присоединяемой.

Новую нить можно создать в отсоединённом состоянии с помощью pthread_attr_setdetachstate(3), установив атрибут отсоединения у аргумента attr при pthread_create(3).

Атрибут отсоединения просто определяет поведение системы при завершении нити; он не препятствует завершению нити при завершении работы процесс с помощью exit(3) (или эквивалента, если завершается основная нить).

Функция pthread_join(3) или pthread_detach() должна вызываться для каждой нити, созданной приложением, для того, чтобы можно было освободить системные ресурсы нити (но, заметим, что ресурсы всех нитей, для которых выполняется одно из этих действий, освобождаются при завершении процесса).

## ПРИМЕР
Следующее выражение отсоединяет вызвавшую нить:

pthread_detach(pthread_self());

## СМОТРИТЕ ТАКЖЕ
pthread_attr_setdetachstate(3), pthread_cancel(3), pthread_create(3), pthread_exit(3), pthread_join(3), pthreads(7)


title: pthread_equal(3)

summary: сравнивает идентификаторы нитей

text:
# pthread_equal(3)

## ИМЯ
pthread_equal - сравнивает идентификаторы нитей

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_equal(pthread_t t1, pthread_t t2);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_equal() два идентификатора нитей.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Если два идентификатора нитей одинаковы, то pthread_equal() возвращает ненулевое значение; в противном случае возвращается 0.

## ОШИБКИ
Данная функция всегда завершается успешно.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_equal()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Функция pthread_equal() необходима, так как формат идентификаторов нитей следует считать «чёрным ящиком»: не существует переносимого способа сравнения двух непосредственно значений pthread_t из приложения.

## СМОТРИТЕ ТАКЖЕ
pthread_create(3), pthread_self(3), pthreads(7)


title: pthread_exit(3)

summary: завершает работу вызвавшей нити

text:
# pthread_exit(3)

## ИМЯ
pthread_exit - завершает работу вызвавшей нити

## ОБЗОР

```
#include <pthread.h>
```

```
void pthread_exit(void *retval);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_exit() завершает работу вызвавшей нити и возвращает значение через retval, доступное (если к нити можно присоединиться) другой нити в том же процессе, вызвавшей pthread_join(3).

Если есть какие-либо невызванные очищающие обработчики, установленные pthread_cleanup_push(3), то они выполняются (в обратном регистрации порядке). Если у нити есть какие-либо свои данные, то после выполнения очищающих обработчиков вызываются соответствующие функции удаления, в неопределённом порядке.

Когда нить завершает выполнение связанные с процессом ресурсы (например, мьютексы, условные переменные, семафоры и файловые дескрипторы) не освобождаются и функции, зарегистрированные через atexit(3), не вызываются.

После завершения последней нити процесса, процесс завершает работу как при вызове exit(3) с нулевых кодом выхода; то есть ресурсы процесса освобождаются и вызываются функции, зарезервированные с помощью atexit(3).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Данная функция не возвращает выполнение вызвавшему.

## ОШИБКИ
Данная функция всегда завершается успешно.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_exit()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Выполнение возврата из начальной функции любой не главной нити приводит к неявному вызову pthread_exit(), возвращаемое значение которой является кодом выхода нити.

Чтобы продолжить выполнение других нитей, главная нить должна завершаться вызовом pthread_exit(), а не exit(3).

Значение, на которое указывает retval, не должно располагаться в стеки вызывающей нити, так как содержимое этого стека не определено после завершения работы нити.

## ДЕФЕКТЫ
В настоящее время в реализуемой ядром логики есть ограничения для остановленных групп нитей с помощью wait(2) с мёртвым лидером группы нитей. Из-за этого могут возникнуть такие проблемы как заблокированный терминал, если сигнал останова посылается фоновому процессу, у которого лидер группы нитей уже вызвал pthread_exit().

## СМОТРИТЕ ТАКЖЕ
pthread_create(3), pthread_join(3), pthreads(7)


title: pthread_getattr_default_np(3)

summary: возврат или

text:
# pthread_getattr_default_np(3)

## ИМЯ
pthread_getattr_default_np, pthread_setattr_default_np - возврат или изменение атрибутов создания нити по умолчанию

## ОБЗОР

```
#define _GNU_SOURCE             /* Смотрите feature_test_macros(7) */
#include <pthread.h>
```

```
int pthread_getattr_default_np(pthread_attr_t *attr);
int pthread_setattr_default_np(pthread_attr_t *attr);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setattr_default_np() изменяет атрибуты по умолчанию, используемые при создании новой нити — то есть атрибуты, которые используются при вызове pthread_create(3) со вторым аргументом, равным NULL. Атрибуты по умолчанию изменяются в соответствии с атрибутами, переданными в *attr — объекте атрибутов нити, инициализированном ранее. Вот, что нужно знать об объекте атрибутов:

- Значения атрибутов в объекте должны быть корректными.

- Атрибут stack address не должен быть указан в объекте.

- Значение нуля в stack size означает, что размер стека по умолчанию остаётся без изменения.

Функция pthread_getattr_default_np() инициализирует объект атрибутов нити, на который указывает attr, так, что он содержит значения атрибутов по умолчанию, использованные при создании нити.

## ОШИБКИ
EINVAL

(pthread_setattr_default_np()) Одно из значений атрибутов в attr неверно или в attr изменён атрибут адреса стека.

ENOMEM

(pthread_setattr_default_np()) Недостаточно памяти.

## ВЕРСИИ
Эти функции доступны в glibc начиная с версии 2.18.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_getattr_default_np(), pthread_setattr_default_np()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные функции являются не стандартизированными расширениями GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## ПРИМЕР
В программе, показанной далее, используется pthread_getattr_default_np() для получения атрибутов создания нити по умолчанию, а затем выводятся различные параметры полученного объекта. Вывод работы программы:

```
$ ./a.out
Размер стека:          8388608
Размер защиты:          4096
Алгоритм планирования:   SCHED_OTHER
Приоритет планирования: 0
Состояние отсоединения:        JOINABLE
Наследование планировщика:   INHERIT
```

### Исходный код программы

```
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define errExitEN(en, msg) \

                        do { errno = en; perror(msg); \

                             exit(EXIT_FAILURE); } while (0)
static void
display_pthread_attr(pthread_attr_t *attr)
{

    int s;

    size_t stacksize;

    size_t guardsize;

    int policy;

    struct sched_param schedparam;

    int detachstate;

    int inheritsched;

    s = pthread_attr_getstacksize(attr, &stacksize);

    if (s != 0)

        errExitEN(s, "pthread_attr_getstacksize");

    printf("Размер стека:          %zd\n", stacksize);

    s = pthread_attr_getguardsize(attr, &guardsize);

    if (s != 0)

        errExitEN(s, "pthread_attr_getguardsize");

    printf("Размер защиты:          %zd\n", guardsize);

    s = pthread_attr_getschedpolicy(attr, &policy);

    if (s != 0)

        errExitEN(s, "pthread_attr_getschedpolicy");

    printf("Алгоритм планирования:   %s\n",

            (policy == SCHED_FIFO) ? "SCHED_FIFO" :

            (policy == SCHED_RR) ? "SCHED_RR" :

            (policy == SCHED_OTHER) ? "SCHED_OTHER" : "[неизвестно]");

    s = pthread_attr_getschedparam(attr, &schedparam);

    if (s != 0)

        errExitEN(s, "pthread_attr_getschedparam");

    printf("Приоритет планирования: %d\n", schedparam.sched_priority);

    s = pthread_attr_getdetachstate(attr, &detachstate);

    if (s != 0)

        errExitEN(s, "pthread_attr_getdetachstate");

    printf("Состояние отсоединения:        %s\n",

            (detachstate == PTHREAD_CREATE_DETACHED) ? "DETACHED" :

            (detachstate == PTHREAD_CREATE_JOINABLE) ? "JOINABLE" :

            "???");

    s = pthread_attr_getinheritsched(attr, &inheritsched);

    if (s != 0)

        errExitEN(s, "pthread_attr_getinheritsched");

    printf("Наследование планировщика:   %s\n",

            (inheritsched == PTHREAD_INHERIT_SCHED) ? "INHERIT" :

            (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "EXPLICIT" :

            "???");
}
int
main(int argc, char *argv[])
{

    int s;

    pthread_attr_t attr;

    s = pthread_getattr_default_np(&attr);

    if (s != 0)

        errExitEN(s, "pthread_getattr_default_np");

    display_pthread_attr(&attr);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
pthread_attr_getaffinity_np(3), pthread_attr_getdetachstate(3), pthread_attr_getguardsize(3), pthread_attr_getinheritsched(3), pthread_attr_getschedparam(3), pthread_attr_getschedpolicy(3), pthread_attr_getscope(3), pthread_attr_getstack(3), pthread_attr_getstackaddr(3), pthread_attr_getstacksize(3), pthread_attr_init(3), pthread_create(3), pthreads(7)


title: pthread_getattr_np(3)

summary: возвращает атрибуты созданной нити

text:
# pthread_getattr_np(3)

## ИМЯ
pthread_getattr_np - возвращает атрибуты созданной нити

## ОБЗОР

```
#define _GNU_SOURCE             /* Смотрите feature_test_macros(7) */
#include <pthread.h>
```

```
int pthread_getattr_np(pthread_t thread, pthread_attr_t *attr);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_getattr_np() инициализирует объект атрибутов нити, на который указывает attr, так, чтобы он содержал актуальные значения атрибутов выполняющейся нити thread.

Возвращаемые значения атрибутов могут отличаться от соответствующих значений атрибутов переданных в объекте attr, который использовался при создании нити с помощью pthread_create(3). В частности, могут отличаться следующие атрибуты:

- состояние отсоединения, так как присоединяемая нить могла сама отсоединиться после создания;

- размер стека, так как реализация нитей могла выронить значение по уместной границе.

- размер защиты, так как реализация нитей могла округлить значение в большую сторону до кратного размера страницы, или проигнорировать (т. е., посчитать за 0), если приложение само выделяет себе стек.

Кроме этого, если атрибут адреса стека не был указан в объекте атрибутов нити при создании нити, то возвращаемый объект атрибутов нити будет содержать актуальный адрес стека, который был выбран реализацией для нити.

Когда объект атрибутов нити, возвращаемый pthread_getattr_np(), больше не требуется, то он должен быть удалён с помощью pthread_attr_destroy(3).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функция возвращает 0; при ошибке возвращается ненулевой номер ошибки.

## ОШИБКИ
ENOMEM

Недостаточно памяти.

Также, если thread указывает на главную нить, то pthread_getattr_np() может завершиться с ошибкой из-за ошибок различных используемых вызовов: fopen(3), если невозможно открыть /proc/self/maps; getrlimit(2), если не поддерживается ограничение ресурса RLIMIT_STACK.

## ВЕРСИИ
Эта функция доступна в glibc начиная с версии 2.2.3.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_getattr_np()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартным расширением GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## ПРИМЕР
В программе, показанной далее, демонстрируется использование pthread_getattr_np(). Программа создаёт нить, которая, затем, использует pthread_getattr_np() для получения и показа своих атрибутов размера защиты, адреса стека и размера стека. Аргументами командной строки можно изменить эти атрибуты. Работа программы показана далее.

В этом запуске на системе x86-32 нить создаётся со значениями атрибутов по умолчанию:

```
$ ulimit -s      # Без ограничения стека ==>

                 # размер стека по умолчанию 2 МБ
unlimited
$ ./a.out
Атрибуты созданной нити:

        Размер защиты      = 4096 байт

        Адрес стека        = 0x40196000 (EOS = 0x40397000)

        Размер стека       = 0x201000 (2101248) байт
```

В этом запуске мы видим, что при задании размера защиты его значение округляется до значение следующего кратного размера системной страницы (4096 байт на x86-32):

```
$ ./a.out -g 4097
Объект атрибутов нити после инициализации:

        Размер защиты      = 4097 байт

        Адрес стека        = (nil)

        Размер стека       = 0x0 (0) байт
Атрибуты созданной нити:

        Размер защиты      = 8192 байт

        Адрес стека        = 0x40196000 (EOS = 0x40397000)

        Размер стека       = 0x201000 (2101248) байт
```

В этом запуске программа вручную выделяет стек для нити. В этом случае атрибут размера защиты игнорируется.

```
$ ./a.out -g 4096 -s 0x8000 -a
Выделен стек нити по адресу 0x804d000
Объект атрибутов нити после инициализации:

        Размер защиты      = 4096 байт

        Адрес стека        = 0x804d000 (EOS = 0x8055000)

        Размер стека       = 0x8000 (32768) байт
Атрибуты созданной нити:

        Размер защиты      = 0 байт

        Адрес стека        = 0x804d000 (EOS = 0x8055000)

        Размер стека       = 0x8000 (32768) байт
```

### Исходный код программы

```
#define _GNU_SOURCE     /* для объявления pthread_getattr_np() */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void
display_stack_related_attributes(pthread_attr_t *attr, char *prefix)
{

    int s;

    size_t stack_size, guard_size;

    void *stack_addr;

    s = pthread_attr_getguardsize(attr, &guard_size);

    if (s != 0)

        handle_error_en(s, "pthread_attr_getguardsize");

    printf("%sРазмер защиты            = %d байт\n", prefix, guard_size);

    s = pthread_attr_getstack(attr, &stack_addr, &stack_size);

    if (s != 0)

        handle_error_en(s, "pthread_attr_getstack");

    printf("%sАдрес стека       = %p", prefix, stack_addr);

    if (stack_size > 0)

        printf(" (EOS = %p)", (char *) stack_addr + stack_size);

    printf("\n");

    printf("%sРазмер стека          = 0x%x (%d) байт\n",

            prefix, stack_size, stack_size);
}
static void
display_thread_attributes(pthread_t thread, char *prefix)
{

    int s;

    pthread_attr_t attr;

    s = pthread_getattr_np(thread, &attr);

    if (s != 0)

        handle_error_en(s, "pthread_getattr_np");

    display_stack_related_attributes(&attr, prefix);

    s = pthread_attr_destroy(&attr);

    if (s != 0)

        handle_error_en(s, "pthread_attr_destroy");
}
static void *           /* Начальная функция создаваемой нити */
thread_start(void *arg)
{

    printf("Атрибуты созданной нити:\n");

    display_thread_attributes(pthread_self(), "\t");

    exit(EXIT_SUCCESS);         /* Завершить все нити */
}
static void
usage(char *pname, char *msg)
{

    if (msg != NULL)

        fputs(msg, stderr);

    fprintf(stderr, "Использование: %s [-s stack-size [-a]]"

            " [-g guard-size]\n", pname);

    fprintf(stderr, "\t\t-a означает, что программа выделяет стек\n");

    exit(EXIT_FAILURE);
}
static pthread_attr_t *   /* получить атрибуты нити из ком. строки */
get_thread_attributes_from_cl(int argc, char *argv[],

                              pthread_attr_t *attrp)
{

    int s, opt, allocate_stack;

    long stack_size, guard_size;

            void *stack_addr;

    pthread_attr_t *ret_attrp = NULL;   /* задаёт attrp, если мы

                                           инициализируем объект

                                           атрибутов нити */

    allocate_stack = 0;

    stack_size = -1;

    guard_size = -1;

    while ((opt = getopt(argc, argv, "ag:s:")) != -1) {

        switch (opt) {

        case 'a':   allocate_stack = 1;                     break;

        case 'g':   guard_size = strtoul(optarg, NULL, 0);  break;

        case 's':   stack_size = strtoul(optarg, NULL, 0);  break;

        default:    usage(argv[0], NULL);

        }

    }

    if (allocate_stack && stack_size == -1)

        usage(argv[0], "Указывать -a без -s не имеет смысла\n");

    if (argc > optind)

        usage(argv[0], "Посторонние аргументы в командной строке\n");

    if (stack_size >= 0 || guard_size > 0) {

        ret_attrp = attrp;

        s = pthread_attr_init(attrp);

        if (s != 0)

            handle_error_en(s, "pthread_attr_init");

    }

    if (stack_size >= 0) {

        if (!allocate_stack) {

            s = pthread_attr_setstacksize(attrp, stack_size);

            if (s != 0)

                handle_error_en(s, "pthread_attr_setstacksize");

        } else {

            s = posix_memalign(&stack_addr, sysconf(_SC_PAGESIZE),

                               stack_size);

            if (s != 0)

                handle_error_en(s, "posix_memalign");

            printf("Выделен стек нити по адресу %p\n\n", stack_addr);

            s = pthread_attr_setstack(attrp, stack_addr, stack_size);

            if (s != 0)

                handle_error_en(s, "pthread_attr_setstacksize");

        }

    }

    if (guard_size >= 0) {

        s = pthread_attr_setguardsize(attrp, guard_size);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setstacksize");

    }

    return ret_attrp;
}
int
main(int argc, char *argv[])
{

    int s;

    pthread_t thr;

    pthread_attr_t attr;

    pthread_attr_t *attrp = NULL;    /* задаёт &attr, если мы

                                        инициализируем объект

                                        атрибутов нити */

    attrp = get_thread_attributes_from_cl(argc, argv, &attr);

    if (attrp != NULL) {

        printf("Объект атрибутов нити после инициализации:\n");

        display_stack_related_attributes(attrp, "\t");

        printf("\n");

    }

    s = pthread_create(&thr, attrp, &thread_start, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_create");

    if (attrp != NULL) {

        s = pthread_attr_destroy(attrp);

        if (s != 0)

            handle_error_en(s, "pthread_attr_destroy");

    }

    pause();    /* Завершается, когда другая нить вызывает exit() */
}
```

## СМОТРИТЕ ТАКЖЕ
pthread_attr_getaffinity_np(3), pthread_attr_getdetachstate(3), pthread_attr_getguardsize(3), pthread_attr_getinheritsched(3), pthread_attr_getschedparam(3), pthread_attr_getschedpolicy(3), pthread_attr_getscope(3), pthread_attr_getstack(3), pthread_attr_getstackaddr(3), pthread_attr_getstacksize(3), pthread_attr_init(3), pthread_create(3), pthreads(7)


title: pthread_getcpuclockid(3)

summary: возвращает ID таймера времени ЦП у нити

text:
# pthread_getcpuclockid(3)

## ИМЯ
pthread_getcpuclockid - возвращает ID таймера времени ЦП у нити

## ОБЗОР

```
#include <pthread.h>
#include <time.h>
```

```
int pthread_getcpuclockid(pthread_t thread, clockid_t *clock_id);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_getcpuclockid() возвращает ID таймера времени ЦП у нити thread.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функция возвращает 0; при ошибке возвращается ненулевой номер ошибки.

## ОШИБКИ
ENOENT

В системе не поддерживаются выделенные таймеры времени ЦП для каждой нити.

ESRCH

Нить с идентификатором thread не найдена.

## ВЕРСИИ
Эта функция доступна в glibc начиная с версии 2.2.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_getcpuclockid()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Если thread указывает на вызвавшую нить, то функция возвращает идентификатор, указывающий на таймер, управляемый clock_gettime(2) и clock_settime(2), если ID таймера равно CLOCK_THREAD_CPUTIME_ID.

## ПРИМЕР
Программа, показанная далее, создаёт нить и используя clock_gettime(2) показывает общее время ЦП и время ЦП, затраченное на работу нитей по отдельности. Пример сеанса работы:

```
$ ./a.out
Главная нить спит
Вторая нить входит в бесконечный цикл
Главная нить использует немного времени ЦП…
Общее время ЦП для процесса:    1.368
Время ЦП для главной нити:      0.376
Время ЦП для второй нити:       0.992
```

### Исходный код программы

```
/* компоновка с "-lrt" */
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <string.h>
#include <errno.h>
#define handle_error(msg) \

        do { perror(msg); exit(EXIT_FAILURE); } while (0)
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void *
thread_start(void *arg)
{

    printf("Вторая нить входит в бесконечный цикл\n");

    for (;;)

        continue;
}
static void
pclock(char *msg, clockid_t cid)
{

    struct timespec ts;

    printf("%s", msg);

    if (clock_gettime(cid, &ts) == -1)

        handle_error("clock_gettime");

    printf("%4ld.%03ld\n", ts.tv_sec, ts.tv_nsec / 1000000);
}
int
main(int argc, char *argv[])
{

    pthread_t thread;

    clockid_t cid;

    int j, s;

    s = pthread_create(&thread, NULL, thread_start, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_create");

    printf("Главная нить спит\n");

    sleep(1);

    printf("Главная нить использует немного времени ЦП…\n");

    for (j = 0; j < 2000000; j++)

        getppid();

    pclock("Общее время ЦП для процесса: ", CLOCK_PROCESS_CPUTIME_ID);

    s = pthread_getcpuclockid(pthread_self(), &cid);

    if (s != 0)

        handle_error_en(s, "pthread_getcpuclockid");

    pclock("Время ЦП для главной нити:   ", cid);

    /* предыдущие 4 строки можно заменить на:

       pclock("Время ЦП для главной нити:", CLOCK_THREAD_CPUTIME_ID); */

    s = pthread_getcpuclockid(thread, &cid);

    if (s != 0)

        handle_error_en(s, "pthread_getcpuclockid");

    pclock("Время ЦП для второй нити:     ", cid);

    exit(EXIT_SUCCESS);         /* завершаем обе нити */
}
```

## СМОТРИТЕ ТАКЖЕ
clock_gettime(2), clock_settime(2), timer_create(2), clock_getcpuclockid(3), pthread_self(3), pthreads(7), time(7)


title: pthread_join(3)

summary: присоединение к завершённой нити

text:
# pthread_join(3)

## ИМЯ
pthread_join - присоединение к завершённой нити

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_join(pthread_t thread, void **retval);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
Функция pthread_join() ждёт завершения нити, указанной в thread. Если нить уже завершила работу, то pthread_join() завершается сразу. Нить, задаваемая в thread, должна позволять присоединение.

Если retval не равно NULL, то pthread_join() копирует код выхода нити назначения (т. е., значение, которое нить назначения передала через pthread_exit(3)) в расположение по указателю retval. Если нить назначения была отменена, то в расположение по указателю retval помещается значение PTHREAD_CANCELED.

Если к одной нити одновременно пытаются присоединиться несколько нитей, то результат не определён. Если нити вызвавшая pthread_join(), отменяется, то нить назначения остаётся доступной для присоединения (т. е., не будет отсоединена).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_join() возвращается 0; при ошибке возвращается номер ошибки.

## ОШИБКИ
EDEADLK

Обнаружена взаимная блокировка (например, когда две нити пытаются присоединиться друг к другу); или в thread указана вызывающая нить.

EINVAL

Нить thread не является присоединяемой.

EINVAL

Другая нить уже ждёт присоединения к этой нити.

ESRCH

Нить с идентификатором thread не найдена.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_join()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
После успешного выполнения pthread_join() вызывающему гарантируется, что целевая нить завершила работу. Вызывающий теперь может сделать нужные после завершения нити операции по очистке (например, освободить память или другие ресурсы, которые использовались целевой нитью).

Присоединение к нити, из которой уже был получен результат присоединения, приводит к непредсказуемым последствиям.

Ошибка присоединения к нити, доступной для присоединения (т. е., не отсоединённой), создаёт «нить-зомби». Лучше их избегать, так как нить-зомби потребляет некоторые системные ресурсы, и когда накапливается много нитей-зомби становится невозможно создание новых нитей (или процессов).

Аналога waitpid(-1, &status, 0) в pthreads не существует, то есть присоединиться к любой завершившейся нити». Если вы уверены, что вам нужна такая возможность, то, вероятно, стоит пересмотреть проект приложения.

Все нити в процессе равноправны: любая нить может присоединиться к любой другой нити процесса.

## ПРИМЕР
Смотрите pthread_create(3).

## СМОТРИТЕ ТАКЖЕ
pthread_cancel(3), pthread_create(3), pthread_detach(3), pthread_exit(3), pthread_tryjoin_np(3), pthreads(7)


title: pthread_kill(3)

summary: посылает сигнал в нить

text:
# pthread_kill(3)

## ИМЯ
pthread_kill - посылает сигнал в нить

## ОБЗОР

```
#include <signal.h>
```

```
int pthread_kill(pthread_t thread, int sig);
```

Компилируется и компонуется вместе с -pthread.

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

pthread_kill():

_POSIX_C_SOURCE >= 199506L || _XOPEN_SOURCE >= 500

## ОПИСАНИЕ
Функция pthread_kill() посылает сигнал sig в thread — нить из того же процесса, что и вызвавший функцию. Сигнал доставляется thread асинхронно.

Если sig равно 0, то сигнал не посылается, но выполняется проверка на ошибки.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_kill() возвращается 0; при ошибке возвращается номер ошибки и сигнал не посылается.

## ОШИБКИ
EINVAL

Указан некорректный сигнал.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_kill()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Область действия сигнала — весь процесс: если установлен обработчик сигнала, то он будет вызван в нити thread, но если этот сигнал «stop», «continue» или «terminate», то это действие повлияет на весь процесс.

Реализация sigaction() в glibc выдаёт ошибку (EINVAL) при попытке послать сигналы реального времени, которые используются внутри реализации NPTL. Подробности смотрите в nptl(7).

В POSIX.1-2008 рекомендуется, что если реализация обнаруживает использование ID нити после её срока жизни, то pthread_kill() должна возвращать ошибку ESRCH. Реализация glibc возвращает эту ошибку в случае, когда обнаруживается некорректный ID нити. Но также заметим, что в POSIX говорится, что попытка использовать ID нити с завершённым сроком жизни приводит к непредсказуемому поведению, и попытка использовать некорректный ID нити в вызове pthread_kill() может приводить, например, к ошибке сегментирования.

## СМОТРИТЕ ТАКЖЕ
kill(2), sigaction(2), sigpending(2), pthread_self(3), pthread_sigmask(3), raise(3), pthreads(7), signal(7)


title: pthread_kill_other_threads_np(3)

summary: завершает все остальные нити процесса

text:
# pthread_kill_other_threads_np(3)

## ИМЯ
pthread_kill_other_threads_np - завершает все остальные нити процесса

## ОБЗОР

```
#include <pthread.h>
```

```
void pthread_kill_other_threads_np(void);
```

## ОПИСАНИЕ
Функция pthread_kill_other_threads_np() эффективна только в реализации нитей LinuxThreads. В этой реализации вызов данной функции приводит к немедленному завершению всех нитей приложения, кроме той, из которой вызвана функция. Состояние и тип отмены завершаемых нитей игнорируются, а очищающие обработчики не вызываются.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_kill_other_threads_np()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Эта функция является нестандартным расширением GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## ЗАМЕЧАНИЯ
Функция pthread_kill_other_threads_np() предназначена для вызова из нити execve(2) или подобной функции. Она разработана для преодоления ограничения в устаревшей реализации LinuxThreads, где нити приложения не завершаются автоматически (как того требуется в POSIX.1-2001) при execve(2).

В реализации нитей NPTL функция pthread_kill_other_threads_np() также существует, но ничего не делает (делать ничего не нужно, так как реализация правильно работает во время execve(2)).

## СМОТРИТЕ ТАКЖЕ
execve(2), pthread_cancel(3), pthread_setcancelstate(3), pthread_setcanceltype(3), pthreads(7)


title: pthread_mutex_consistent(3)

summary: делает устойчивый мьютекс согласованным

text:
# pthread_mutex_consistent(3)

## ИМЯ
pthread_mutex_consistent - делает устойчивый мьютекс согласованным

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_mutex_consistent(pthread_mutex_t *mutex);
```

Компилируется и компонуется вместе с -pthread.

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

pthread_mutex_consistent():

_POSIX_C_SOURCE >= 200809L

## ОПИСАНИЕ
Данная функция делает устойчивый мьютекс согласованным, если он находится в рассогласованном состоянии. Мьютекс может остаться в рассогласованном состоянии, если владелец завершил работу, удерживая мьютекс; в этом случае следующий владелец, захвативший мьютекс вызовом pthread_mutex_lock(), получит уведомление возвращаемым значением EOWNERDEAD .

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_mutex_consistent() возвращает 0. В противном случае возвращается положительный номер, указывающий на причину ошибки.

## ОШИБКИ
EINVAL

Мьютекс находит не в согласованном состоянии и не в рассогласованном состоянии.

## ВЕРСИИ
Функция pthread_mutex_consistent() впервые появилась в glibc 2.12.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2008.

## ЗАМЕЧАНИЯ
Функция pthread_mutex_consistent() просто информирует реализацию, что состояние (общие данные) защищаемые мьютексом, были восстановлены в согласованное состояние и что теперь с мьютексом можно выполнять обычные операции. Перед вызовом pthread_mutex_consistent() приложение само должно приводить данные в согласованное состояние.

До появления pthread_mutex_consistent() в POSIX, в glibc определялся следующий эквивалент нестандартной функции, если определён _GNU_SOURCE:

```
int pthread_mutex_consistent(const pthread_mutex_t *mutex);
```

Данный имеющийся только в GNU программный интерфейс, впервые появившийся в glibc 2.4, в настоящее время устарел и не должен использоваться в новых программах.

## ПРИМЕР
Смотрите pthread_mutexattr_setrobust(3).

## СМОТРИТЕ ТАКЖЕ
pthread_mutexattr_init(3), pthread_mutex_lock(3), pthread_mutexattr_getrobust(3), pthread_mutexattr_setrobust(3), pthreads(7)


title: pthread_mutexattr_getpshared(3)

text:
# pthread_mutexattr_getpshared(3)

## ИМЯ
pthread_mutexattr_getpshared, pthread_mutexattr_setpshared - возвращает/изменяет общепроцессный атрибут мьютекса

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_mutexattr_getpshared(const pthread_mutexattr_t *attr,
                                 int *pshared);
int pthread_mutexattr_setpshared(pthread_mutexattr_t *attr,
                                 int pshared);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
Эти функции возвращают и изменяют общепроцессный атрибут мьютекса в объекте атрибутов мьютекса. Данный атрибут должен быть установлен соответствующим образом для обеспечения правильной, эффективной работы мьютекса, созданного с использованием данного объекта атрибутов.

В общепроцессном аргументе можно указать одно из следующих значений:

PTHREAD_PROCESS_PRIVATE

Мьютексы, созданные с таким объектом атрибутов, будут считаться общими только для нитей одного процесса, инициализировавшего мьютекс. Это значение используется по умолчанию для общепроцессного атрибута мьютекса.

PTHREAD_PROCESS_SHARED

Мьютексы, созданные с таким объектом атрибутов, будут считаться общими между всеми нитями, имеющими доступ к памяти, содержащей объект, даже нити разных процессов.

Функция pthread_mutexattr_getpshared() помещает значения общепроцессного атрибута объекта атрибутов мьютекса, на который указывает attr, в расположение, указанное в pshared.

Функция pthread_mutexattr_setpshared() изменяет значения общепроцессного атрибута объекта атрибутов мьютекса, на который указывает attr, на значение, заданное в pshared.

Если attr не ссылается на инициализированный объект атрибутов мьютекса, то поведение не определено.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0. При ошибке возвращается положительный номер ошибки.

## ОШИБКИ
Функция pthread_mutexattr_setpshared() может завершаться со следующими ошибками:

EINVAL

Неверное значение в pshared.

ENOTSUP

Значение pshared равно PTHREAD_PROCESS_SHARED, но реализация не поддерживает общепроцессные мьютексы.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## СМОТРИТЕ ТАКЖЕ
pthread_mutexattr_init(3), pthreads(7)


title: pthread_mutexattr_init(3)

summary: инициализирует и

text:
# pthread_mutexattr_init(3)

## ИМЯ
pthread_mutexattr_init, pthread_mutexattr_destroy - инициализирует и уничтожает объект атрибутов мьютекса

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_mutexattr_init(pthread_mutexattr_t *attr);
int pthread_mutexattr_destroy(pthread_mutexattr_t *attr);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
Функция pthread_mutexattr_init() инициализирует объект атрибутов мьютекса, на который указывает attr, значениями по умолчанию для всех атрибутов, определённых реализацией.

Если для инициализации указан уже инициализированный объект атрибутов мьютекса, то результат не определён.

Функция pthread_mutexattr_destroy() уничтожает объект атрибутов мьютекса (делает его не инициализированным). После уничтожения объекта атрибутов мьютекса, его можно инициализировать с помощью pthread_mutexattr_init().

Если для уничтожения указан не инициализированный объект атрибутов мьютекса, то результат не определён.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0. При ошибке возвращается положительный номер ошибки.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Изменения объекта атрибутов мьютекса не влияют на мьютексы, которые уже были инициализированы с помощью этого объекта.

## СМОТРИТЕ ТАКЖЕ
pthread_mutex_init(3), pthread_mutexattr_getpshared(3), pthread_mutexattr_getrobust(3), pthreads(7)


title: pthread_mutexattr_setrobust(3)

summary: возвращает и

text:
# pthread_mutexattr_setrobust(3)

## ИМЯ
pthread_mutexattr_getrobust, pthread_mutexattr_setrobust - возвращает и изменяет атрибут устойчивости в объекте мьютексных атрибутов

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_mutexattr_getrobust(const pthread_mutexattr_t *attr,
                                int *robustness);
int pthread_mutexattr_setrobust(const pthread_mutexattr_t *attr,
                                int robustness);
```

Компилируется и компонуется вместе с -pthread.

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

pthread_mutexattr_getrobust(), pthread_mutexattr_setrobust():

_POSIX_C_SOURCE >= 200809L

## ОПИСАНИЕ
Функция pthread_mutexattr_getrobust() помещает значение атрибута устойчивости (robustness) из объекта мьютексных атрибутов, на который указывает attr, в *robustness. Функция pthread_mutexattr_setrobust() изменяет значение атрибута устойчивости в объекте мьютексных атрибутов, на который указывает attr, на значение, заданное в *robustness.

Атрибут устойчивости определяет поведение мьютекса после того как владеющая нить завершает работу, но не разблокировала мьютекс. Для robustness возможны следующие значения:

PTHREAD_MUTEX_STALLED

Значение по умолчанию для объекта мьютексных атрибутов. Если мьютекс инициализирован с атрибутом PTHREAD_MUTEX_STALLED и его владелец завершает работу без его разблокировки, то после этого мьютекс остаётся заблокированным и все последующие попытки вызова pthread_mutex_lock(3) для этого мьютекса будут заблокированы навсегда.

PTHREAD_MUTEX_ROBUST

Если мьютекса инициализирован с атрибутом PTHREAD_MUTEX_ROBUST и и его владелец завершает работу без его разблокировки,то все последующие попытки вызова pthread_mutex_lock(3) для этого мьютекса будут успешно выполнены возвращается EOWNERDEAD, чтобы показать, что первоначальный владелец не существует и мьютекс находится в неопределенном состоянии. Обычно, после возврата EOWNERDEAD перед началом использования следующий владелец должен вызвать pthread_mutex_consistent(3) над полученным мьютексом, чтобы снова сделать его согласованным.

Если следующий владелец разблокирует мьютекс с помощью pthread_mutex_unlock(3) до того, как сделать его согласованным, мьютекс станет необратимо неработоспособен и последующие попытки заблокировать его с помощью pthread_mutex_lock(3) будут завершаться ошибкой ENOTRECOVERABLE. Для такого мьютекса доступна только одна операция — pthread_mutex_destroy(3).

Если следующий владелец завершит работу до вызова pthread_mutex_consistent(3), то последующие операций pthread_mutex_lock(3) с этим мьютексом будут по прежнему возвращать EOWNERDEAD.

Заметим, что аргумент attr у pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() должен указывать на объект мьютексных атрибутов, который был инициализирован pthread_mutexattr_init(3), в противном случае поведение не определено.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0. При ошибке возвращается положительный номер ошибки.

В реализации glibc функция pthread_mutexattr_getrobust() всегда возвращает ноль.

## ОШИБКИ
EINVAL

Помимо PTHREAD_MUTEX_STALLED или PTHREAD_MUTEX_ROBUST в pthread_mutexattr_setrobust() передано что-то ещё.

## ВЕРСИИ
Функции pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() добавлены в glibc версии 2.12.

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2008.

## ЗАМЕЧАНИЯ
В реализации Linux при использовании общих для процессов устойчивых мьютексов ожидающая нить также получает уведомление EOWNERDEAD, если владелец устойчивого мьютекса выполняет execve(2) без предварительной разблокировки мьютекса. В POSIX.1 не указана данная подробность, но такое же поведение также встречается и в нескольких других реализациях.

До появления pthread_mutexattr_getrobust() и pthread_mutexattr_setrobust() в POSIX, в glibc определись следующие эквиваленты нестандартных функций, если определён _GNU_SOURCE:

```
int pthread_mutexattr_getrobust_np(const pthread_mutexattr_t *attr,
                                   int *robustness);
int pthread_mutexattr_setrobust_np(const pthread_mutexattr_t *attr,
                                   int robustness);
```

Соответственно, также определены константы PTHREAD_MUTEX_STALLED_NP и PTHREAD_MUTEX_ROBUST_NP.

Данный имеющийся только в GNU программный интерфейс, впервые появившийся в glibc 2.4, в настоящее время устарел и не должен использоваться в новых программах.

## ПРИМЕР
В программе, представленной далее, показывается использование атрибута устойчивости в объекте мьютексных атрибутов. В этой программе нить, удерживающая мьютекс, завершает работу без разблокировки мьютекса. После этого главная нить захватывает мьютекс и получает ошибку EOWNERDEAD, после чего делает мьютекс согласованным.

Пример сеанса работы с программой:

```
$ ./a.out
[первый владелец] Установка блокировки…
[первый владелец] Готово. Теперь выходим без разблокировки.
[главная нить] Пытаемся получить заблокировать устойчивый мьютекс.
[главная нить] pthread_mutex_lock() вернула EOWNERDEAD
[главная нить] Теперь делаем мьютекс согласованным
[главная нить] Мьютекс согласован; разблокируем
```

### Исходный код программы

```
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <pthread.h>
#include <errno.h>
#define handle_error_en(en, msg) \

               do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static pthread_mutex_t mtx;
static void *
original_owner_thread(void *ptr)
{

    printf("[первый владелец] Установка блокировки…\n");

    pthread_mutex_lock(&mtx);

    printf("[original owner] Готово. Теперь выходим без разблокировки.\n");

    pthread_exit(NULL);
}
int
main(int argc, char *argv[])
{

    pthread_t thr;

    pthread_mutexattr_t attr;

    int s;

    pthread_mutexattr_init(&attr);

                                /* инициализируем объект атрибутов */

    pthread_mutexattr_setrobust(&attr, PTHREAD_MUTEX_ROBUST);

                               /* задаём устойчивость */

    pthread_mutex_init(&mtx, &attr);   /* инициализируем мьютекс */

    pthread_create(&thr, NULL, original_owner_thread, NULL);

    sleep(2);

    /* «нить_первый_владелец» к этому моменту должна завершиться */

    printf("[главная нить] Пытаемся получить заблокировать устойчивый мьютекс.\n");

    s = pthread_mutex_lock(&mtx);

    if (s == EOWNERDEAD) {

        printf("[главная нить] pthread_mutex_lock() вернула EOWNERDEAD\n");

        printf("[главная нить] Теперь делаем мьютекс согласованным\n");

        s = pthread_mutex_consistent(&mtx);

        if (s != 0)

            handle_error_en(s, "pthread_mutex_consistent");

        printf("[главная нить] Мьютекс согласован; разблокируем\n");

        s = pthread_mutex_unlock(&mtx);

        if (s != 0)

            handle_error_en(s, "pthread_mutex_unlock");

        exit(EXIT_SUCCESS);

    } else if (s == 0) {

        printf("[главная нить] pthread_mutex_lock() неожиданно завершилась успешно\n");

        exit(EXIT_FAILURE);

    } else {

        printf("[главная нить] pthread_mutex_lock() завершилась с ошибкой\n");

        handle_error_en(s, "pthread_mutex_lock");

    }
}
```

## СМОТРИТЕ ТАКЖЕ
get_robust_list(2), set_robust_list(2), pthread_mutex_consistent(3), pthread_mutex_init(3), pthread_mutex_lock(3), pthreads(7)


title: pthread_rwlockattr_setkind_np(3)

text:
# pthread_rwlockattr_setkind_np(3)

## ИМЯ
pthread_rwlockattr_setkind_np, pthread_rwlockattr_getkind_np - изменяет/возвращает вид блокировки чтения-записи у объекта-атрибута блокировки чтения-записи нити

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_rwlockattr_setkind_np(pthread_rwlockattr_t *attr,
                                   int pref);
int pthread_rwlockattr_getkind_np(const pthread_rwlockattr_t *attr,
                                   int *pref);
```

```
Компилируется и компонуется вместе с -pthread.
```

```

```

Требования макроса тестирования свойств для glibc (см. feature_test_macros(7)):

pthread_rwlockattr_setkind_np(), pthread_rwlockattr_getkind_np():

_XOPEN_SOURCE >= 500 || _POSIX_C_SOURCE >= 200809L

## ОПИСАНИЕ
Функция pthread_rwlockattr_setkind_np() изменяет атрибут «вида блокировки» у объекта-атрибута блокировки чтения-записи, на который указывает attr, в значение pref. Значением pref может быть одно из:

PTHREAD_RWLOCK_PREFER_READER_NP

Значение по умолчанию. Нить может удерживать многократную блокировку чтения; то есть блокировки чтения рекурсивны. Согласно Single Unix Specification, поведение не определено, если читатель пытается установить блокировку и отсутствует блокировка записи, но писатели ждут. Давая преимущество читателю установкой PTHREAD_RWLOCK_PREFER_READER_NP подразумевается, что читатель будет получать запрашиваемую блокировку даже, если ждёт писатель. Пока есть читатели писатель будет ждать.

PTHREAD_RWLOCK_PREFER_WRITER_NP

Аналог PTHREAD_RWLOCK_PREFER_READER_NP, но для блокировки записи. Игнорируется glibc, так как с учётом требований POSIX рекурсивная блокировка записи, привела был к созданию вечной блокировки (deadlocks); вместо неё используется PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, которая не позволяет разработчику приложения получить рекурсивную блокировку чтения, и поэтому вечной блокировки не случится.

PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP

Данный вид блокировки помогает избежать ожидания писателя всё время пока не освободится рекурсивная блокировка чтения.

Функция pthread_rwlockattr_getkind_np() сохраняет атрибут «вида блокировки» у объекта-атрибута блокировки чтения-записи, на который указывает attr, в указатель pref.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0. При корректных аргументах указателей pthread_rwlockattr_getkind_np() всегда выполняется успешно. При ошибке pthread_rwlockattr_setkind_np() возвращает ненулевой номер ошибки.

## ОШИБКИ
EINVAL

Неподдерживаемое значение pref.

## ВЕРСИИ
Функции pthread_rwlockattr_getkind_np() и pthread_rwlockattr_setkind_np() впервые появились в glibc 2.1.

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные функции являются не стандартизированными расширениями GNU, о чем свидетельствует суффикс «_np» (nonportable).

## СМОТРИТЕ ТАКЖЕ
pthreads(7)


title: pthread_self(3)

summary: возвращает ID вызвавшей нити

text:
# pthread_self(3)

## ИМЯ
pthread_self - возвращает ID вызвавшей нити

## ОБЗОР

```
#include <pthread.h>
```

```
pthread_t pthread_self(void);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_self() возвращает идентификатор вызвавшей нити. Это значение совпадает с возвращаемым в *thread вызовом pthread_create(3) при создании этой нити.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
Данная функция всегда завершается успешно, возвращая идентификатор вызвавшей нити.

## ОШИБКИ
Данная функция всегда завершается успешно.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_self()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
В POSIX.1 предоставляет реализации большую свободу выбора типа, используемого под идентификатор нити; например, допускается представление как виде целого числа так и структуры. Поэтому переменные типа pthread_t нельзя сравнивать оператором равенства C (==); для этого предназначена функция pthread_equal(3).

Состав идентификаторов нити следует считать «чёрным ящиком»: все попытки использовать ID нити кроме как в вызовах pthreads являются непереносимыми и могут приводить к непредсказуемым результатам.

Для идентификаторов нити гарантируется их уникальность только внутри процесса. Идентификатор нити может использоваться повторно после присоединения завершённой нити или завершения отключённой нити.

Идентификатор нити, возвращаемый pthread_self() не тоже самое что идентификатор нити возвращаемый вызовом ядра gettid(2).

## СМОТРИТЕ ТАКЖЕ
pthread_create(3), pthread_equal(3), pthreads(7)


title: pthread_setaffinity_np(3)

summary: получить/назначить

text:
# pthread_setaffinity_np(3)

## ИМЯ
pthread_setaffinity_np, pthread_getaffinity_np - получить/назначить увязываемый ЦП для нити

## ОБЗОР

```
#define _GNU_SOURCE             /* Смотрите feature_test_macros(7) */
#include <pthread.h>
```

```
int pthread_setaffinity_np(pthread_t thread, size_t cpusetsize,
                           const cpu_set_t *cpuset);
int pthread_getaffinity_np(pthread_t thread, size_t cpusetsize,
                           cpu_set_t *cpuset);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setaffinity_np() устанавливает маску увязывания ЦП для нити thread равной набору ЦП, указанному в cpuset. Если вызов выполняется без ошибок и нить не запущена ни на одном из ЦП в cpuset, то она перемещается на один из этих ЦП.

Функция pthread_getaffinity_np() помещает маску увязывания ЦП для нити thread в буфер, на который указывает cpuset.

Дополнительную информацию по маскам увязывания ЦП смотрите в sched_setaffinity(2). Описание набора макросов, которые можно использовать для просмотра и изменения наборов ЦП, смотрите в CPU_SET(3).

В аргументе cpusetsize указывается длина буфера (в байтах), на который указывает cpuset. Обычно, этот аргумент должен задаваться как sizeof(cpu_set_t) (он может иметь и другое значение, если используются макросы динамического выделения набора ЦП, описанные в CPU_SET(3)).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0; при ошибке возвращается ненулевой номер ошибки.

## ОШИБКИ
EFAULT

Указан некорректный адрес памяти.

EINVAL

(pthread_setaffinity_np()) В маске увязывания ЦП mask указаны процессоры, которых физически нет в системе, и которые разрешены нити согласно любым ограничениям, которые могут налагаться механизмом «cpuset», описанном в cpuset(7).

EINVAL

(pthread_setaffinity_np()) В cpuset указан ЦП, который находится вне набора поддерживаемых ядром (в параметре сборки ядра CONFIG_NR_CPUS определён диапазон для набора, поддерживаемого типом данных ядра, который используется для представления наборов ЦП).

EINVAL

(pthread_getaffinity_np()) Значение cpusetsize меньше размера маски увязывания, используемой в ядре.

ESRCH

Нить с идентификатором thread не найдена.

## ВЕРСИИ
Эти функции определены в glibc начиная с версии 2.3.4.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setaffinity_np(), pthread_getaffinity_np()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные функции являются не стандартизированными расширениями GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## ЗАМЕЧАНИЯ
После вызова pthread_setaffinity_np() набор процессоров, на которых действительно будет выполняться нить, вычисляется пересечением набора из аргумента cpuset и набором процессоров, присутствующих в системе. В дальнейшем, система может ограничить набор процессоров нити, если задействован механизм «cpuset», описанный в cpuset(7). Эти ограничения на действительный набор процессоров, используемых для нити, без уведомления налагаются ядром.

Эти функции реализованы через системные вызовы sched_setaffinity(2) и sched_getaffinity(2).

В glibc 2.3.3 версии этих функций не имеют аргумента cpusetsize. Вместо него размер набора ЦП, передаваемый используемым системным вызовам, всегда равен sizeof(cpu_set_t).

Новая нить, созданная pthread_create(3), наследует копию маски увязывания ЦП своего создателя.

## ПРИМЕР
В этой программе главная нить использует pthread_setaffinity_np() для включения в свою маску увязывания ЦП процессоры с 0 по 7 (которых может не быть в системе), а затем вызывает pthread_getaffinity_np() для проверки получившейся маски увязывания ЦП у нити.

```
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
int
main(int argc, char *argv[])
{

    int s, j;

    cpu_set_t cpuset;

    pthread_t thread;

    thread = pthread_self();

    /* включаем ЦП с 0 по 7 в маску увязывания */

    CPU_ZERO(&cpuset);

    for (j = 0; j < 8; j++)

        CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

    if (s != 0)

        handle_error_en(s, "pthread_setaffinity_np");

    /* проверяем маску увязывания, назначенную нити */

    s = pthread_getaffinity_np(thread, sizeof(cpu_set_t), &cpuset);

    if (s != 0)

        handle_error_en(s, "pthread_getaffinity_np");

    printf("Набор, возвращённый pthread_getaffinity_np(), содержит:\n");

    for (j = 0; j < CPU_SETSIZE; j++)

        if (CPU_ISSET(j, &cpuset))

            printf("    ЦП %d\n", j);

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
sched_setaffinity(2), CPU_SET(3), pthread_attr_setaffinity_np(3), pthread_self(3), sched_getcpu(3), cpuset(7), pthreads(7), sched(7)


title: pthread_setcancelstate(3)

summary: изменяет состояния и тип

text:
# pthread_setcancelstate(3)

## ИМЯ
pthread_setcancelstate, pthread_setcanceltype - изменяет состояния и тип отменяемости

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_setcancelstate(int state, int *oldstate);
int pthread_setcanceltype(int type, int *oldtype);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setcancelstate() изменяет состояние отменяемости вызывающий нити на значение state. Предыдущее состояние отменяемости нити возвращается в буфер, на который указывает oldstate. Аргументом state должно быть одно из следующих значений:

PTHREAD_CANCEL_ENABLE

Нить является отменяемой. Для всех новых нитей, включая начальную, это состояние является основным по умолчанию. Тип отменяемости нити определяет, когда нить будет отвечать на запрос об отмене.

PTHREAD_CANCEL_DISABLE

Нить является неотменяемой. Если был получен запрос об отмене, он будет блокироваться до тех пор, пока не будет включена отменяемость.

Функция pthread_setcanceltype() изменяет тип отменяемости вызывающий нити на значение type. Предыдущий тип отменяемости нити возвращается в буфер, на который указывает oldstate. Аргументом type должно быть одно из следующих значений:

PTHREAD_CANCEL_DEFERRED

Запрос отменяемости откладывается до тех пор, пока нить не вызовет функцию, являющуюся точкой отмены (смотрите pthreads(7)). Данный тип является умолчательным для всех нитей, включая начальную.

PTHREAD_CANCEL_ASYNCHRONOUS

Нить может быть отменена в любой момент (практически сразу же после получения запроса об отмене, однако система не гарантирует этого).

Операции установки и получения (set-and-get), выполняемые каждой из этих функций, являются атомарными для предотвращения пересечения с другими процессами, вызывающими ту же функцию.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0; при ошибке возвращается ненулевой номер ошибки.

## ОШИБКИ
Функция pthread_setcancelstate() может завершиться со следующей ошибкой:

EINVAL

Неправильное значение для state.

Функция pthread_setcanceltype() может завершиться со следующей ошибкой:

EINVAL

Неправильное значение для type.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setcancelstate(), pthread_setcanceltype()

Безвредность в нитях

MT-Safe

pthread_setcancelstate(), pthread_setcanceltype()

Async-cancel-safety

AC-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Информацию о том, что происходит с отменяемой нитью, смотрите в pthread_cancel(3).

Запрет отмены на короткое время полезен, если нить выполняет какое-то важное действие, которое не должно прерываться запросом отмены. Остерегайтесь запретов отмены на длительный срок или для операций, которые могут занять много времени, так как нить при этом перестанет отвечать на запросы отмены.

### Асинхронная отменяемость
Задание типа отменяемости PTHREAD_CANCEL_ASYNCHRONOUS полезно редко. Так как нить может быть отменена в любой момент, невозможно безопасно резервировать ресурсы (например, выделять память с помощью malloc(3)), захватывать мьютексы, семафоры или блокировки и так далее. Резервирование ресурсов небезопасно, так как приложение не может узнать состояние этих ресурсов при отмене нити; то есть, произошла ли отмена до резервирования ресурсов, во время из резервирования или после их освобождения? Кроме того, некоторые внутренние структуры данных (например, связные списки свободных блоков, управляемые семейством функций malloc(3)) могут остаться в не целостном состоянии, если отмена происходит в середине вызова функции. Следовательно, обработчики очистки перестают быть полезными.

Функции, которые можно безопасно асинхронно отменять называются функциями async-cancel-safe. В POSIX.1-2001 и POSIX.1-2008 требуется, чтобы такими функция были только pthread_cancel(3), pthread_setcancelstate() и pthread_setcanceltype(). В общем, другие функции библиотеки нельзя безопасно вызывать из асинхронно отменяемой нити.

Одной из нескольких ситуаций, в которых асинхронная отменяемость полезна, является отменяемость нити, которая находится в цикле, занимающимся только вычислениями.

### Замечания о переносимости
Реализации нитей в Linux позволяют присваивать аргументу oldstate функции pthread_setcancelstate() значение NULL; в этом случае информация о предыдущем состоянии отмены не возвращается вызывающему. Многие другие реализации также допускают NULL в качестве значения oldstat, но POSIX.1 этот случай не рассматривается, поэтому переносимые приложения должны всегда указывать в oldstate значение, отличное от NULL. Эти утверждения относятся и к аргументу oldtype функции pthread_setcanceltype().

## ПРИМЕР
Смотрите pthread_cancel(3).

## СМОТРИТЕ ТАКЖЕ
pthread_cancel(3), pthread_cleanup_push(3), pthread_testcancel(3), pthreads(7)


title: pthread_setconcurrency(3)

summary: изменяет/возвращает уровень

text:
# pthread_setconcurrency(3)

## ИМЯ
pthread_setconcurrency, pthread_getconcurrency - изменяет/возвращает уровень распараллеливания

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_setconcurrency(int new_level);
int pthread_getconcurrency(void);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setconcurrency() информирует реализацию приложения о желаемом уровне распараллеливания (concurrency level), задаваемом в new_level. Реализация принимает это только как рекомендацию: в POSIX.1 не указан уровень распараллеливания, который должен получиться в результате вызова pthread_setconcurrency().

Значение new_level равное 0 указывает реализации использовать уровень распараллеливания по своему усмотрению.

Функция pthread_getconcurrency() возвращает текущее значение уровня распараллеливания для этого процесса.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении pthread_setconcurrency() возвращается 0; при ошибке возвращается ненулевой номер ошибки.

Функция pthread_getconcurrency() всегда завершается успешно, возвращая уровень распараллеливания, заданный предыдущим вызовом pthread_setconcurrency(), или 0, если функция pthread_setconcurrency() не вызывалась.

## ОШИБКИ
Функция pthread_setconcurrency() может завершиться со следующей ошибкой:

EINVAL

Значение new_level отрицательно.

В POSIX.1 также описана ошибка EAGAIN («значение, указанное в new_level, привело бы к превышению системного ограничения»).

## ВЕРСИИ
Эти функции доступны в glibc начиная с версии 2.1.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setconcurrency(), pthread_getconcurrency()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Значение уровня распараллеливания по умолчанию равно 0.

Уровни распараллеливания имеют смысл только в реализациях нитей M:N, где в любой момент времени поднабор из набора пользовательских нитей процесса может быть ограничен меньшим количеством единиц планирования ядра. Назначение уровня распараллеливания позволяет приложению дать системе подсказку о количестве единиц планирования ядра для эффективного выполнения приложения.

В реализациях нитей LinuxThreads и NPTL используется отношение 1:1, поэтому назначение уровня распараллеливания не имеет смысла. Другими словами, в Linux эти функции существуют только лишь для совместимости с другими системами и никак не влияют на выполнение программы.

## СМОТРИТЕ ТАКЖЕ
pthread_attr_setscope(3), pthreads(7)


title: pthread_setname_np(3)

summary: изменяет/возвращает имя нити

text:
# pthread_setname_np(3)

## ИМЯ
pthread_setname_np, pthread_getname_np - изменяет/возвращает имя нити

## ОБЗОР

```
#define _GNU_SOURCE             /* смотрите feature_test_macros(7) */
#include <pthread.h>
int pthread_setname_np(pthread_t thread, const char *name);
int pthread_getname_np(pthread_t thread,
                       char *name, size_t len);
```

Компилируется и компонуется вместе с -pthread.

## ОПИСАНИЕ
По умолчанию, все нити, созданные pthread_create(), наследуют имя программы. Функция pthread_setname_np() позволяет задать уникальное имя нити, которое можно использовать при отладки многонитевых приложений. Имя нити задаётся по правилам строк языка C, его длина ограничена 16 символами, включая конечный байт null ('\0'). В аргументе thread указывается нить, чьё имя будет изменено; в name указывается новое имя.

Функция pthread_getname_np() возвращает имя нити. В аргументе thread указывает нить, чьё имя будет возвращено. В буфер name возвращается имя нити; в аргументе len указывается количество байт, доступное в name. Длина буфера name должна быть не менее 16 символов. Возвращаемое имя в выходном буфере завершается байтом null.

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0; при ошибке возвращается ненулевой номер ошибки.

## ОШИБКИ
Функция pthread_setname_np() может завершиться со следующей ошибкой:

ERANGE

Длина строки, на которую ссылается name, превышает разрешённую.

Функция pthread_getname_np() может завершиться со следующей ошибкой:

ERANGE

Буфер, задаваемый name и len, слишком мал для имени нити.

Если одна из этих функций завершается с ошибкой открытия /proc/self/task/[tid]/comm, то вызов может завершиться одной из ошибок, описанных в open(2).

## ВЕРСИИ
Эти функции впервые появились в glibc 2.12.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setname_np(), pthread_getname_np()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
Данные функции являются не стандартизированными расширениями GNU, о чём свидетельствует наличие суффикса «_np» (nonportable).

## ЗАМЕЧАНИЯ
Запись pthread_setname_np() выполняет через файл нити comm из файловой системы /proc: /proc/self/task/[tid]/comm. Функция pthread_getname_np() также используется его для возврата имени.

## ПРИМЕР
Представленная ниже программа показывает использование pthread_setname_np() и pthread_getname_np().

Пример сеанса работы с программой:

```
$ ./a.out
Нить создана. Имя по умолчанию: a.out
Имя нити после изменения — THREADFOO.
^Z                           # Приостановка программы
[1]+  Stopped           ./a.out
$ ps H -C a.out -o 'pid tid cmd comm'

  PID   TID CMD                         COMMAND

 5990  5990 ./a.out                     a.out

 5990  5991 ./a.out                     THREADFOO
$ cat /proc/5990/task/5990/comm
a.out
$ cat /proc/5990/task/5991/comm
THREADFOO
```

### Исходный код программы

```
#define _GNU_SOURCE
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#define NAMELEN 16
#define errExitEN(en, msg) \

            do { errno = en; perror(msg); exit(EXIT_FAILURE); \

        } while (0)
static void *
threadfunc(void *parm)
{

    sleep(5);          // позволить главной программе изменить имя нити

    return NULL;
}
int
main(int argc, char **argv)
{

    pthread_t thread;

    int rc;

    char thread_name[NAMELEN];

    rc = pthread_create(&thread, NULL, threadfunc, NULL);

    if (rc != 0)

        errExitEN(rc, "pthread_create");

    rc = pthread_getname_np(thread, thread_name, NAMELEN);

    if (rc != 0)

        errExitEN(rc, "pthread_getname_np");

    printf("Нить создана. Имя по умолчанию: %s\n", thread_name);

    rc = pthread_setname_np(thread, (argc > 1) ? argv[1] : "THREADFOO");

    if (rc != 0)

        errExitEN(rc, "pthread_setname_np");

    sleep(2);

    rc = pthread_getname_np(thread, thread_name,

                            (argc > 2) ? atoi(argv[1]) : NAMELEN);

    if (rc != 0)

        errExitEN(rc, "pthread_getname_np");

    printf("Имя нити после изменения — %s.\n", thread_name);

    rc = pthread_join(thread, NULL);

    if (rc != 0)

        errExitEN(rc, "pthread_join");

    printf("Done\n");

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
prctl(2), pthread_create(3), pthreads(7)


title: pthread_setschedparam(3)

summary: изменяет/возвращает параметры

text:
# pthread_setschedparam(3)

## ИМЯ
pthread_setschedparam, pthread_getschedparam - изменяет/возвращает параметры и алгоритм планирования нити

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_setschedparam(pthread_t thread, int policy,
                          const struct sched_param *param);
int pthread_getschedparam(pthread_t thread, int *policy,
                          struct sched_param *param);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setschedparam() назначает параметры и алгоритм планирования нити thread.

В policy указывается новый алгоритм планирования thread. Поддерживаемые значения policy и их семантика описана в sched(7).

Структура, на которую указывает param определяет новые параметры планирования thread. Параметры планирования хранятся в структуре следующего вида:

```
struct sched_param {

    int sched_priority;     /* планируемый приоритет */
};
```

Из той структуры видно, что поддерживается только один параметр. Подробности о разрешённых диапазонах планируемых приоритетов для каждого алгоритма планирования смотрите в sched(7).

Функция pthread_getschedparam() возвращает параметры и алгоритм планирования нити thread в буфер, указанный policy и param, соответственно. Возвращаемое значение приоритета совпадает с заданным с помощью последнего вызова pthread_setschedparam(), pthread_setschedprio(3) или pthread_create(3), относящегося к thread. Возвращаемые приоритет не отражает каких-либо временных подстроек приоритета в результате вызовов функций наследования приоритета или потолка (например, смотрите pthread_mutexattr_setprioceiling(3) и pthread_mutexattr_setprotocol(3)).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении эти функции возвращают 0; при ошибке возвращается ненулевой номер ошибки. Если pthread_setschedparam() завершается ошибкой, то параметры и алгоритм планирования thread не изменяется.

## ОШИБКИ
Это функции могут завершиться со следующей ошибкой:

ESRCH

Нить с идентификатором thread не найдена.

Функция pthread_setschedparam() может также завершиться со следующими ошибками:

EINVAL

Неизвестное значение policy или значение param не имеет смысла для policy.

EPERM

Вызывающий не имеет соответствующих прав для установки указанного алгоритма планирования и параметров.

Для pthread_setschedparam() в POSIX.1 также описана необязательная ошибка ENOTSUP («попытка изменить параметры и алгоритм планирования на не поддерживаемое значение»).

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setschedparam(), pthread_getschedparam()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Список требуемых прав, результат, изменение алгоритма и приоритета планирования нити и подробности разрешённых диапазонов приоритетов для каждого алгоритма планирования смотрите в sched(7).

## ПРИМЕР
Представленная ниже программа показывает использование pthread_setschedparam() и pthread_getschedparam(), а также других относящихся к планированию функций программного интерфейса pthreads.

В этом сеансе, главная нить изменяет свой алгоритм планирования на SCHED_FIFO с приоритетом 10, и инициализирует объект атрибутов нити с атрибутом алгоритма планирования SCHED_RR и атрибутом приоритета планирования 20. Затем программа изменяет (с помощью pthread_attr_setinheritsched(3)) атрибут наследования планировщика в объекте атрибутов нити на PTHREAD_EXPLICIT_SCHED, из-за чего создаваемые с использованием данного объекта атрибутов нити получат значения атрибуты планирования из объекта атрибутов нити. Затем программа создаёт нить с учётом объекта атрибутов нити, после чего эта нить выводит значения своего алгоритма и приоритета планирования.

```
$ su      # требуются права для назначения алгоритмов

            планирования реального времени
Пароль:
# ./a.out -mf10 -ar20 -i e
Настройки планировщика главной нити

    алгоритм=SCHED_FIFO, приоритет=10
Настройки планировщика в 'attr'

    алгоритм=SCHED_RR, приоритет=20

    наследование планировщика ЯВНОЕ
Атрибуты планировщика в новой нити

    алгоритм=SCHED_RR, приоритет=20
```

В показанном выше выводе можно видеть приоритет и алгоритм планирования, которые были взяты из объекта атрибутов нити.

Следующий сеанс похож на предыдущий, то в нём атрибут наследования планировщика равен PTHREAD_INHERIT_SCHED, то есть создаваемые с использованием объекта атрибутов нити игнорируют значения параметров и алгоритм планирования, заданные в объекте атрибутов нити, и берут их от создавшей нити.

```
# ./a.out -mf10 -ar20 -i i
Настройки планировщика главной нити

    алгоритм=SCHED_FIFO, приоритет=10
Настройки планировщика в 'attr'

    алгоритм=SCHED_RR, приоритет=20

    наследование планировщика ВКЛЮЧЕНО
Атрибуты планировщика в новой нити

    алгоритм=SCHED_FIFO, приоритет=10
```

В показанном выше выводе можно видеть приоритет и алгоритм планирования, которые были взяты из создаваемой нити, а не из объекта атрибутов нити.

Заметим, чти если не указать параметр -i i, то вывод будет тем же самым, так как PTHREAD_INHERIT_SCHED является значением по умолчанию для атрибута наследования планировщика.

### Исходный код программы

```
/* pthreads_sched_test.c */
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#define handle_error_en(en, msg) \

        do { errno = en; perror(msg); exit(EXIT_FAILURE); } while (0)
static void
usage(char *prog_name, char *msg)
{

    if (msg != NULL)

        fputs(msg, stderr);

    fprintf(stderr, "Использование: %s [параметры]\n", prog_name);

    fprintf(stderr, "Параметры:\n");
#define fpe(msg) fprintf(stderr, "\t%s", msg);       /* для краткости */

    fpe("-a<алгоритм><приоритет> Алгоритм и приоритет планирования\n");

    fpe("                 объекте атрибутов нити\n");

    fpe("                 значения для <алгоритм>:\n");

    fpe("                     f  SCHED_FIFO\n");

    fpe("                     r  SCHED_RR\n");

    fpe("                     o  SCHED_OTHER\n");

    fpe("-A               Исп. объект атрибутов нити по умолчанию\n");

    fpe("-i {e|i}         Атрибут наследования планировщика\n");

    fpe("                 'явный' or 'унаследованный'\n");

    fpe("-m<алгоритм><приоритет> Алгоритм и приоритет планирования\n");

    fpe("               главной нити перед вызовом pthread_create()\n");

    exit(EXIT_FAILURE);
}
static int
get_policy(char p, int *policy)
{

    switch (p) {

    case 'f': *policy = SCHED_FIFO;     return 1;

    case 'r': *policy = SCHED_RR;       return 1;

    case 'o': *policy = SCHED_OTHER;    return 1;

    default:  return 0;

    }
}
static void
display_sched_attr(int policy, struct sched_param *param)
{

    printf("    алгоритм=%s, приоритет=%d\n",

            (policy == SCHED_FIFO)  ? "SCHED_FIFO" :

            (policy == SCHED_RR)    ? "SCHED_RR" :

            (policy == SCHED_OTHER) ? "SCHED_OTHER" :

            "???",

            param->sched_priority);
}
static void
display_thread_sched_attr(char *msg)
{

    int policy, s;

    struct sched_param param;

    s = pthread_getschedparam(pthread_self(), &policy, &param);

    if (s != 0)

        handle_error_en(s, "pthread_getschedparam");

    printf("%s\n", msg);

    display_sched_attr(policy, &param);
}
static void *
thread_start(void *arg)
{

    display_thread_sched_attr("Атрибуты планировщика в новой нити");

    return NULL;
}
int
main(int argc, char *argv[])
{

    int s, opt, inheritsched, use_null_attrib, policy;

    pthread_t thread;

    pthread_attr_t attr;

    pthread_attr_t *attrp;

    char *attr_sched_str, *main_sched_str, *inheritsched_str;

    struct sched_param param;

    /* обработка параметров командной строки */

    use_null_attrib = 0;

    attr_sched_str = NULL;

    main_sched_str = NULL;

    inheritsched_str = NULL;

    while ((opt = getopt(argc, argv, "a:Ai:m:")) != -1) {

        switch (opt) {

        case 'a': attr_sched_str = optarg;      break;

        case 'A': use_null_attrib = 1;          break;

        case 'i': inheritsched_str = optarg;    break;

        case 'm': main_sched_str = optarg;      break;

        default:  usage(argv[0], "Неизвестный параметр\n");

        }

    }

    if (use_null_attrib &&

            (inheritsched_str != NULL || attr_sched_str != NULL))

        usage(argv[0], "Нельзя указывать -A вместе с -i или -a\n");

    /* необязательная установка атрибутов планирования главной нити

       вывод этих атрибутов */

    if (main_sched_str != NULL) {

        if (!get_policy(main_sched_str[0], &policy))

            usage(argv[0], "Некоррект. алгоритм для главной нити (-m)\n");

        param.sched_priority = strtol(&main_sched_str[1], NULL, 0);

        s = pthread_setschedparam(pthread_self(), policy, &param);

        if (s != 0)

            handle_error_en(s, "pthread_setschedparam");

    }

    display_thread_sched_attr("Настройки планировщика главной нити");

    printf("\n");

    /* инициализация объекта атрибутов нити согласно параметрам */

    attrp = NULL;

    if (!use_null_attrib) {

        s = pthread_attr_init(&attr);

        if (s != 0)

            handle_error_en(s, "pthread_attr_init");

        attrp = &attr;

    }

    if (inheritsched_str != NULL) {

        if (inheritsched_str[0] == 'e')

            inheritsched = PTHREAD_EXPLICIT_SCHED;

        else if (inheritsched_str[0] == 'i')

            inheritsched = PTHREAD_INHERIT_SCHED;

        else

            usage(argv[0], "Значение -i должно быть 'e' или 'i'\n");

        s = pthread_attr_setinheritsched(&attr, inheritsched);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setinheritsched");

    }

    if (attr_sched_str != NULL) {

        if (!get_policy(attr_sched_str[0], &policy))

            usage(argv[0],

                    "Некорректный алгоритм для 'attr' (-a)\n");

        param.sched_priority = strtol(&attr_sched_str[1], NULL, 0);

        s = pthread_attr_setschedpolicy(&attr, policy);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setschedpolicy");

        s = pthread_attr_setschedparam(&attr, &param);

        if (s != 0)

            handle_error_en(s, "pthread_attr_setschedparam");

    }

    /* если мы инициализируем объект атрибутов нити, то покажем

       атрибуты планирования, установленные в объекте */

    if (attrp != NULL) {

        s = pthread_attr_getschedparam(&attr, &param);

        if (s != 0)

            handle_error_en(s, "pthread_attr_getschedparam");

        s = pthread_attr_getschedpolicy(&attr, &policy);

        if (s != 0)

            handle_error_en(s, "pthread_attr_getschedpolicy");

        printf("Настройки планировщика в 'attr'\n");

        display_sched_attr(policy, &param);

        s = pthread_attr_getinheritsched(&attr, &inheritsched);

        printf("    наследование планировщика %s\n",

                (inheritsched == PTHREAD_INHERIT_SCHED)  ? "ВКЛЮЧЕНО" :

                (inheritsched == PTHREAD_EXPLICIT_SCHED) ? "ЯВНОЕ" :

                "???");

        printf("\n");

    }

    /* создаём нить, которая покажет свои атрибуты планирования */

    s = pthread_create(&thread, attrp, &thread_start, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_create");

    /* уничтожаем ненужный объект атрибутов нити */

    if (!use_null_attrib) {

      s = pthread_attr_destroy(&attr);

      if (s != 0)

          handle_error_en(s, "pthread_attr_destroy");

    }

    s = pthread_join(thread, NULL);

    if (s != 0)

        handle_error_en(s, "pthread_join");

    exit(EXIT_SUCCESS);
}
```

## СМОТРИТЕ ТАКЖЕ
getrlimit(2), sched_get_priority_min(2), pthread_attr_init(3), pthread_attr_setinheritsched(3), pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3), pthread_create(3), pthread_self(3), pthread_setschedprio(3), pthreads(7), sched(7)


title: pthread_setschedprio(3)

summary: изменяет приоритет планирования нити

text:
# pthread_setschedprio(3)

## ИМЯ
pthread_setschedprio - изменяет приоритет планирования нити

## ОБЗОР

```
#include <pthread.h>
```

```
int pthread_setschedprio(pthread_t thread, int prio);
```

```
Компилируется и компонуется вместе с -pthread.
```

## ОПИСАНИЕ
Функция pthread_setschedprio() изменяет приоритет планирования нити thread на значение, указанное в prio (по сравнению с pthread_setschedparam(3), которая изменяет сразу алгоритм планирования и приоритет нити).

## ВОЗВРАЩАЕМОЕ ЗНАЧЕНИЕ
При успешном выполнении функция возвращает 0; при ошибке возвращается ненулевой номер ошибки. Если pthread_setschedprio() завершается ошибкой, то приоритет планирования thread не изменяется.

## ОШИБКИ
EINVAL

Значение prio некорректно для приоритета планирования указанной нити.

EPERM

Вызывающий не имеет соответствующих прав для установки указанного приоритета.

ESRCH

Нить с идентификатором thread не найдена.

Для pthread_setschedparam(3) в POSIX.1 также описана необязательная ошибка ENOTSUP («попытка изменить приоритет на не поддерживаемое значение»).

## ВЕРСИИ
Эта функция доступна в glibc начиная с версии 2.3.4.

## АТРИБУТЫ
Описание терминов данного раздела смотрите в attributes(7).

Интерфейс

Атрибут

Значение

pthread_setschedprio()

Безвредность в нитях

MT-Safe

## СООТВЕТСТВИЕ СТАНДАРТАМ
POSIX.1-2001, POSIX.1-2008.

## ЗАМЕЧАНИЯ
Список требуемых прав, результат, изменение приоритета планирования нити и подробности разрешённых диапазонов приоритетов для каждого алгоритма планирования смотрите в sched(7).

## СМОТРИТЕ ТАКЖЕ
getrlimit(2), sched_get_priority_min(2), pthread_attr_init(3), pthread_attr_setinheritsched(3), pthread_attr_setschedparam(3), pthread_attr_setschedpolicy(3), pthread_create(3), pthread_self(3), pthread_setschedparam(3), pthreads(7), sched(7)