Управлять потоком
#include <sys/neutrino.h>int ThreadCtl( int cmd,void *data );int ThreadCtl_r( int cmd,void *data );
libc
Эти вызовы ядра позволяют сделать специфичные для ЗОСРВ «Нейтрино» изменения в потоке.
Функции ThreadCtl() и ThreadCtl_r() идентичны, за исключением способа сообщения об ошибках.
Ниже описаны возможные команды.
ThreadCtl( _NTO_TCTL_ALIGN_FAULT, data );
Эта команда управляет ответом на обращение к невыровненным данным. Аргумент data должен быть указателем на int
, значение которого задаёт желаемое поведение:
SIGBUS
, если это разрешено архитектурой. SIGBUS
.
Потоки, созданные вызывающим потоком, наследуют _NTO_TCTL_ALIGN_FAULT . |
ThreadCtl( _NTO_TCTL_IO, 0 );ThreadCtl( _NTO_TCTL_IO_PRIV, 0 );
Перевести память процесса в режим суперблокировки и запросить I/O привилегии. I/O привилегии позволяют потоку:
in
, ins
, out
, outs
I/O операции на архитектуре x86; В некоторых случаях нехватка I/O привилегий может привести к формированию сигнала SIGSEGV
или SIGILL
.
Команда _NTO_TCTL_IO_PRIV
предоставляет все привилегии, что и команда _NTO_TCTL_IO
, плюс добавляет следующее:
|
_NTO_TCTL_IO_PRIV
добавлен в ЗОСРВ
«Нейтрино»
редакции 2021
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);}
ThreadCtl( _NTO_TCTL_ONE_THREAD_CONT, data );
Разморозить поток с указанным идентификатором, который был заморожен командой _NTO_TCTL_ONE_THREAD_HOLD
. Аргумент data - идентификатор потока, приведённый к указателю (т.е. (void *)tid). Команда возвращает ESRCH
, если потока с таким tid не существует.
ThreadCtl( _NTO_TCTL_ONE_THREAD_HOLD, data );
Хранить поток с указанным идентификатором в вызывающем процессе. Аргумент data - идентификатор потока, приведённый к указателю (т.е. (void *)tid). Команда возвращает ESRCH
, если потока с таким tid не существует.
ThreadCtl( _NTO_TCTL_RUNMASK, data );
Задать специализацию процессоров для вызывающего потока в многопроцессорной системе. Аргумент data - маска, приведённая к указателю (т.е. (void *)runmask). Каждый установленный бит в runmask означает процессор, на котором поток может исполняться.
По умолчанию в маске runmask потока установлены все единицы, что позволяет потоку исполняться на любом доступном процессоре. Значение 0x01
например, заставит поток исполняться только на первом процессоре.
Можно использовать _NTO_TCTL_RUNMASK
для оптимизации производительности системы путём отнесения потоков, не требующих реального времени, к определённому процессору. В общем, это не должно быть необходимо, поскольку в ЗОСРВ «Нейтрино» планировщик всегда немедленно вытесняет поток с более низким приоритетом, когда поток с более высоким приоритетом переходит в состояние READY.
Главный эффект привязки процессоров - эффективность кэша ЦПУ, поскольку можно предотвратить миграцию потоков.
Потоки, созданные вызывающим потоком, не наследуют маску. |
ThreadCtl( _NTO_TCTL_RUNMASK_GET_AND_SET, data );
Получить и установить маску специализации процессоров в заданное значение для вызывающего потока в многопроцессорной системе. Параметр data является указателем на маску. На входе указатель на значение используется для установки новой маски потока (см. _NTO_TCTL_SET_RUNMASK
). После выполнения функции, содержимое *data будет замещено предыдущей маской потока. Повторный вызов ThreadCtl() с таким же указателем восстановит предыдущую маску.
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;} elseif ( (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);}
ThreadCtl( _NTO_TCTL_THREADS_CONT, 0 );
Разморозить все потоки текущего процесса, замороженные ранее при помощи команды _NTO_TCTL_THREADS_HOLD
.
ThreadCtl( _NTO_TCTL_THREADS_HOLD, 0 );
Удерживать все потоки текущего процесса, кроме вызывающего.
Потоки, созданные вызывающим потоком, не замораживаются. |
Эти вызовы не блокируют.
-1
, код ошибки записывается в errno. Любое другое возвращенное значение считается успешным завершением.EOK
возвращается при успешном завершении. Функция НЕ устанавливает errno. При возникновении ошибки функция возвращает один из представленных ниже кодов.
ЗОСРВ «Нейтрино»
struct _thread_name, struct _thread_runmask, InterruptDisable(), InterruptEnable(), InterruptMask(), InterruptUnmask(), procnto-*, pthread_getname_np(), pthread_setname_np()
Предыдущий раздел: Описание API системной библиотеки