Общая память BSR

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

Память BSR обеспечивает сохраненным блокам памяти более быструю передачу в системе, чем обычная кэш-память. Память BSR использует семантику управления кэш-памятью, которая выделена для манипулирования небольшими блоками памяти от нескольких процессоров в параллельных вычислениях. Семантика управления кэш-памятью изначально не предназначалась для управления разделяемой памятью, но этот механизм полезен для эффективной реализации схемы синхронизации границ, которая используется в высокопроизводительных параллельных потоках.

Для памяти BSR требуется поддержка процессора, и ресурсы логического раздела (LPAR) должны быть настроены на использование функции BSR.

Для выделения общей памяти BSR необходимо выполнить следующее:
  1. Выделить общую память V для областей общей памяти системы BSR с помощью функции shmctl().
  2. Включить резервное копирование выделенных областей общей системной памяти V в память BSR, для чего вызвать функцию shmctl() и выполнить команду SHM_BSR.
    Прим.: В общей памяти используется функция shmctl() с командой SHM_BSR. Этот шаг выполняется непосредственно после создания резервной копии с помощью функции shmget() и до того, как первый процесс будет добавлен в общую память. С помощью команды SHM_BSR функция shmctl() пытается использовать память BSR для заданной области общей памяти.
  3. При недостатке памяти BSR и в том случае, если функции BSR не поддерживаются аппаратной платформой, выводится сообщение об ошибке. Функция shmget() завершается с errno, установленным в ENOMEM
    Прим.: Пользователь, не имеющий прав доступа root, должен иметь разрешение CAP_BYPASS_RAC_VMM для выделения памяти BSR. В противном случае функция shmctl() с командой SHM_BSR завершится с errno, установленным в EPERM.

При использовании общей памяти BSR, в области общей памяти разрешаются только 1-байтовые и 2-байтовые команды хранилища. Команды хранилища, длина которых превышает 2 байта, не работают правильно с общей памятью BSR. Команды загрузки любого размера разрешаются для разделяемой памяти BSR.

Команда VMINFO функции vmgetinfo() используется для сбора сведений об имеющейся поддержке BSR. При указании команды VMINFO в функции vmgetinfo() возвращается структура vminfo. В поле bsr_mem_total указан общий объем памяти, настроенный LPAR. В поле bsr_mem_free указан общий объем BSR, который в настоящее время доступен для выделения.

Области общей памяти BSR не изменяются динамически с помощью опции SHM_SIZE функции shmctl(). При попытке изменения размера области общей памяти BSR путем указания параметра SHM_SIZE в функции shmctl() функция shmctl() завершается с errno, установленным в EINVAL. Общая память BSR не поддерживается с переменной среды EXTSHM. В том случае если переменная среды EXTSHM задана, при вызовеshmctl() с флагом SHM_BSR функция shmctl() завершается с EINVAL.

Пример

Следующий пример показывает, что приложение может запрашивать объем доступной памяти BSR системы и затем выделять и присоединять область общей памяти BSR. В примере показано, как приложение будет отсоединять и удалять область общей памяти BSR.
#include <errno.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/vminfo.h>

/* shm_rgn_size - размер области общей памяти область для выделения.
 * В этом примере выбрано - 4 КБ (PAGESIZE).  4 КБ - наименьший поддерживаемый
 * размер области общей памяти.  Ожидается, что 4 КБ должно быть достаточно для
 * большинства пользователей.
 */
const size_t shm_rgn_size = PAGESIZE;

int main(int argc, char *argv[])
{
	struct vminfo my_info = { 0 };
	int           id;
	void          *ptr;
	
	/* Определяется объем доступной памяти BSR */
	if (vmgetinfo(&my_info, VMINFO, sizeof(my_info)) != 0)
	{
		perror("неожиданный сбой vmgetinfo()");
		return 1;
	}

	/* Проверка, что имеется достаточно памяти BSR */
	if (my_info.bsr_mem_free < shm_rgn_size)
	{
		fprintf(stderr, "недостаточно памяти BSR\n");
		return 2;
	}

	/* Выделяется новая область общей памяти */
	id = shmget(IPC_PRIVATE, shm_rgn_size, IPC_CREAT|IPC_EXCL);

	if (id == -1)
	{
		perror("не удалось выполнить shmget()");
		return 3;
	}

	/* Запрос памяти BSR для области общей памяти */
	if (shmctl(id, SHM_BSR, NULL))
	{
		perror("не удалось выполнить shmctl(SHM_BSR)");
		shmctl(id, IPC_RMID, 0);
		return 4;
	}
	
	/* Присоединение области общей памяти */
	ptr = shmat(id, NULL, 0);
	if ((int)ptr == -1)
	{
		perror("не удалось выполнить shmat()");
		shmctl(id, IPC_RMID, 0);
		return 5;
	}

	/* BSR память может быть доступна, начиная с адреса - ptr */

	/* Отсоединение области общей памяти */
	if (shmdt(ptr))
	{
		perror("не удалось выполнить shmdt()");
		shmctl(id, IPC_RMID, 0);
		return 6;
	}

	/* Удаление области общей памяти */
	if (shmctl(id, IPC_RMID, 0))
	{
		perror("не удалось выполнить shmctl(IPC_RMID)");
		return 7;
	}

	return 0;
}