ThreadCtl(), ThreadCtl_r()

Управлять потоком

Прототип:

#include <sys/neutrino.h>
int ThreadCtl( int cmd,
void *data );
int ThreadCtl_r( int cmd,
void *data );

Аргументы:

cmd
Команда для исполнения:
data
Указатель на данные, связанные с определённой командой.

Библиотека:

libc

Описание:

Эти вызовы ядра позволяют сделать специфичные для ЗОСРВ «Нейтрино» изменения в потоке.

Функции ThreadCtl() и ThreadCtl_r() идентичны, за исключением способа сообщения об ошибках.

Ниже описаны возможные команды.

_NTO_TCTL_ALIGN_FAULT

ThreadCtl( _NTO_TCTL_ALIGN_FAULT, data );

Эта команда управляет ответом на обращение к невыровненным данным. Аргумент data должен быть указателем на int, значение которого задаёт желаемое поведение:

Функция устанавливает в data положительное или отрицательное число, сообщая предыдущее желаемое поведение.


Note: Потоки, созданные вызывающим потоком, наследуют _NTO_TCTL_ALIGN_FAULT.

_NTO_TCTL_IO, _NTO_TCTL_IO_PRIV

ThreadCtl( _NTO_TCTL_IO, 0 );
ThreadCtl( _NTO_TCTL_IO_PRIV, 0 );

Перевести память процесса в режим суперблокировки и запросить I/O привилегии. I/O привилегии позволяют потоку:

В некоторых случаях нехватка I/O привилегий может привести к формированию сигнала SIGSEGV или SIGILL.

Команда _NTO_TCTL_IO_PRIV предоставляет все привилегии, что и команда _NTO_TCTL_IO, плюс добавляет следующее:


Note:
  • Для успешного выполнения команд _NTO_TCTL_IO и _NTO_TCTL_IO_PRIV процесс должен обладать правами администратора.
  • Потоки, созданные вызывающим потоком, наследуют _NTO_TCTL_IO и _NTO_TCTL_IO_PRIV.

Флаг _NTO_TCTL_IO_PRIV добавлен в ЗОСРВ «Нейтрино» редакции 2021

_NTO_TCTL_NAME

ThreadCtl( _NTO_TCTL_NAME, data );

Задать или получить имя текущего потока. Аргумент data должен быть указателем на struct _thread_name.

Пример:

#include <stdio.h>
#include <sys/neutrino.h>
#include <stdlib.h>
int main()
{
struct _thread_name *tname;
int size;
size = sizeof( *tname ) * 2 + _NTO_THREAD_NAME_MAX * sizeof( char );
tname = malloc( size );
if ( tname == NULL )
{
perror( "malloc" );
return (EXIT_FAILURE);
} else {
memset( tname, 0x00, size );
tname->name_buf_len = _NTO_THREAD_NAME_MAX;
/* To change the name, put the name into name_buf and set new_name_len to the length of the new name. */
strcpy( tname->name_buf, "Hello!" );
tname->new_name_len = strlen( tname->name_buf );
if ( ThreadCtl( _NTO_TCTL_NAME, tname ) == -1 )
{
perror( "ThreadCtl()" );
return (EXIT_FAILURE);
} else {
printf( "The old name was: '%s'.\n", tname->name_buf );
}
/* To get the current name, set new_name_len to -1. */
tname->new_name_len = -1;
if ( ThreadCtl( _NTO_TCTL_NAME, tname ) == -1 )
{
perror( "ThreadCtl()" );
return (EXIT_FAILURE);
} else {
printf( "The current name is: '%s'.\n", tname->name_buf );
}
/* To delete the name, set new_name_len to 0. */
tname->new_name_len = 0;
if ( ThreadCtl( _NTO_TCTL_NAME, tname ) == -1 )
{
perror( "ThreadCtl()" );
return (EXIT_FAILURE);
} else {
printf( "The old name was: '%s'.\n", tname->name_buf );
}
free( tname );
}
return (EXIT_SUCCESS);
}

_NTO_TCTL_ONE_THREAD_CONT

ThreadCtl( _NTO_TCTL_ONE_THREAD_CONT, data );

Разморозить поток с указанным идентификатором, который был заморожен командой _NTO_TCTL_ONE_THREAD_HOLD. Аргумент data - идентификатор потока, приведённый к указателю (т.е. (void *)tid). Команда возвращает ESRCH, если потока с таким tid не существует.

_NTO_TCTL_ONE_THREAD_HOLD

ThreadCtl( _NTO_TCTL_ONE_THREAD_HOLD, data );

Хранить поток с указанным идентификатором в вызывающем процессе. Аргумент data - идентификатор потока, приведённый к указателю (т.е. (void *)tid). Команда возвращает ESRCH, если потока с таким tid не существует.

_NTO_TCTL_RUNMASK

ThreadCtl( _NTO_TCTL_RUNMASK, data );

Задать специализацию процессоров для вызывающего потока в многопроцессорной системе. Аргумент data - маска, приведённая к указателю (т.е. (void *)runmask). Каждый установленный бит в runmask означает процессор, на котором поток может исполняться.

По умолчанию в маске runmask потока установлены все единицы, что позволяет потоку исполняться на любом доступном процессоре. Значение 0x01 например, заставит поток исполняться только на первом процессоре.

Можно использовать _NTO_TCTL_RUNMASK для оптимизации производительности системы путём отнесения потоков, не требующих реального времени, к определённому процессору. В общем, это не должно быть необходимо, поскольку в ЗОСРВ «Нейтрино» планировщик всегда немедленно вытесняет поток с более низким приоритетом, когда поток с более высоким приоритетом переходит в состояние READY.

Главный эффект привязки процессоров - эффективность кэша ЦПУ, поскольку можно предотвратить миграцию потоков.


Note: Потоки, созданные вызывающим потоком, не наследуют маску.

_NTO_TCTL_RUNMASK_GET_AND_SET

ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET, data );

Получить и установить маску специализации процессоров в заданное значение для вызывающего потока в многопроцессорной системе. Параметр data является указателем на маску. На входе указатель на значение используется для установки новой маски потока (см. _NTO_TCTL_SET_RUNMASK). После выполнения функции, содержимое *data будет замещено предыдущей маской потока. Повторный вызов ThreadCtl() с таким же указателем восстановит предыдущую маску.

_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT

ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, data );

Изменить маску вызывающего процесса и наследовать её. Аргумент data должен быть указателем на struct _thread_runmask.

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

Пример:

#include <sys/neutrino.h>
#include <sys/syspage.h>
#include <malloc.h>
#include <stdio.h>
int main()
{
int *rsizep, rsize, size_tot;
unsigned *rmaskp, *inheritp;
unsigned buf[8];
void *freep;
/*
* struct _thread_runmask is not uniquely sized, so we construct our own.
*/
rsize = RMSK_SIZE( _syspage_ptr->num_cpu );
size_tot = sizeof( *rsizep );
size_tot += sizeof( *rmaskp ) * rsize;
size_tot += sizeof( *inheritp ) * rsize;
if ( size_tot <= sizeof( buf ) )
{
rsizep = buf;
freep = NULL;
} else
if ( (rsizep = freep = malloc( size_tot )) == NULL )
{
perror( "malloc" );
return (1);
}
memset( rsizep, 0x00, size_tot );
*rsizep = rsize;
rmaskp = (unsigned *)(rsizep + 1);
inheritp = rmaskp + rsize;
/*
* Both masks set to 0 means get the current values without alteration.
*/
if ( ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, rsizep ) == -1 )
{
perror( "_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT" );
free( freep );
return (1);
}
/*
* Restrict our inherit mask to the last cpu; leave the runmask unaltered.
*/
memset( rsizep, 0x00, size_tot );
*rsizep = rsize;
RMSK_SET( _syspage_ptr->num_cpu - 1, inheritp );
if ( ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT, rsizep ) == -1 )
{
perror( "_NTO_TCTL_RUNMASK_GET_AND_SET_INHERIT" );
free( freep );
return (1);
}
free( freep );
return (0);
}

_NTO_TCTL_THREADS_CONT

ThreadCtl( _NTO_TCTL_THREADS_CONT, 0 );

Разморозить все потоки текущего процесса, замороженные ранее при помощи команды _NTO_TCTL_THREADS_HOLD.

_NTO_TCTL_THREADS_HOLD

ThreadCtl( _NTO_TCTL_THREADS_HOLD, 0 );

Удерживать все потоки текущего процесса, кроме вызывающего.


Note: Потоки, созданные вызывающим потоком, не замораживаются.

Состояния блокировки:

Эти вызовы не блокируют.

Возвращаемое значение:

ThreadCtl()
Если возникла ошибка функция возвращает -1, код ошибки записывается в errno. Любое другое возвращенное значение считается успешным завершением.
ThreadCtl_r()
EOK возвращается при успешном завершении. Функция НЕ устанавливает errno. При возникновении ошибки функция возвращает один из представленных ниже кодов.

Коды ошибок:

E2BIG
Слишком длинное имя.
EINVAL
Длина буфера имени некорректная либо меньше длины нового имени или передаваемая маска некорректна.
EPERM
У процесса нет прав на исполнение команды.
ESRCH
Не существует потока с таким tid.

Классификация:

ЗОСРВ «Нейтрино»

Безопасность использования
Точка остановки потока
Нет
Обработчик прерываний
Нет
Обработчик сигналов
Да
В потоке
Да

Тематические ссылки:

struct _thread_name, struct _thread_runmask, InterruptDisable(), InterruptEnable(), InterruptMask(), InterruptUnmask(), procnto-*, pthread_getname_np(), pthread_setname_np()




Предыдущий раздел: Описание API системной библиотеки