BSR 共有メモリー

バリア同期レジスター (BSR) は、小規模または高密度のメモリー領域を効率的に共有するためのハードウェア機能です。 メモリー領域は複数のスレッドにより並行して更新されます。

BSR メモリーにより、格納されたメモリーがシステム内を通常のキャッシュされたメモリーよりも速く伝搬することができます。 BSRメモリーは、複数のプロセッサーから少量のメモリーを操作する高度に並列化されたアプリケーションに割り当てられるキャッシュ管理セマンティクスを使用します。 キャッシュ管理セマンティクスは、汎用の共有メモリーに使用するものではありません。 この機能は、ワークロードを高度に並列化した状況で使用されるバリア同期構造を効率的に実装するために役立ちます。

BSR メモリーには特別なプロセッサー・サポートが必要であり、論理区画 (LPAR) が BSR 機能を使用できるように、リソースを LPAR に構成する必要があります。

BSR 共有メモリーを割り当てるには、以下の手順を実行します。
  1. shmctl() サブルーチンを使用して、BSR 共有メモリーのシステム V 共有メモリー領域を割り当てます。
  2. shmctl() サブルーチンを使用し、SHM_BSR コマンドを指定することによって、割り振られたシステム V 共有メモリー領域が BSR メモリーによってバックアップされることを要求します。
    注: SHM_BSR コマンドで使用される shmctl() サブルーチンは、共用メモリーで使用されます。 このステップは、shmget() サブルーチンを使用してシステム V 共有メモリーが作成された直後、かつ任意のプロセスが共有メモリーに接続される前に実行されます。 SHM_BSR コマンドが使用されると、shmctl() サブルーチンは指定された共有メモリー領域に対して BSR メモリーを使用しようとします。
  3. 使用可能な BSR メモリーが不足している場合、またはハードウェア・プラットフォームで BSR 機能がサポートされていない場合にエラーを表示します。 shmget() サブルーチンは失敗し、errnoENOMEM に設定されます。
    注: 非 root ユーザーには、BSR メモリーを割り振るための CAP_BYPASS_RAC_VMM 機能が必要です。 非 root ユーザーがこの機能を持っていない場合、 SHM_BSR コマンドを指定した shmctl() サブルーチンは、 errnoEPERMに設定されて失敗します。

BSR 共有メモリーを使用する場合、共有メモリー領域には 1 バイトおよび 2 バイトのストア命令のみ使用できます。 2 バイト超を使用するストア命令は、BSR 共有メモリーでは正しく機能しません。 ロード命令では任意のサイズが BSR 共有メモリーにロードできます。

VMINFO コマンドは、vmgetinfo() サブルーチンで実行され、利用可能な BSR サポートに関する情報を収集するために使用されます。 VMINFO コマンドが vmgetinfo() サブルーチンに指定されている場合は、vminfo 構造体が戻されます。 bsr_mem_total フィールドには、LPAR に構成された BSR メモリーの合計量が報告されます。 bsr_mem_free フィールドには、現在割り当て可能な BSR の合計量が報告されます。

BSR 共用メモリー領域は、 shmctl() サブルーチンに SHM_SIZE オプションを指定して動的にサイズ変更することはできません。 アプリケーションが shmctl() サブルーチンに SHM_SIZE パラメーターを指定して BSR 共有メモリー領域をサイズ変更しようとすると、shmctl() は失敗して errnoEINVAL に設定されます。 BSR 共有メモリーは、EXTSHM 環境変数ではサポートされません。 EXTSHM 環境変数が設定されている場合、SHM_BSR フラグを使用して shmctl() が呼び出されると、shmctl()EINVAL で失敗します。

次の例は、アプリケーションがシステムで使用可能な BSR メモリーの量を照会して、BSR 共有メモリー領域を割り当て、接続できることを示しています。 この例は、アプリケーションがどのように BSR 共有メモリー領域を分離して削除するかを示しています。
#include <errno.h>
#include <stdio.h>
#include <sys/shm.h>
#include <sys/vminfo.h>

/* shm_rgn_size is the size of the shared memory region to
 * allocate. In this example, 4KB (PAGESIZE) is chosen.  4KB is the
 * smallest shared memory region size supported.  It is expected that
 * 4KB should be sufficient for most users of BSR memory.
 */
const size_t shm_rgn_size = PAGESIZE;

int main(int argc, char *argv[])
{
	struct vminfo my_info = { 0 };
	int           id;
	void          *ptr;
	
	/* Determine the amount of BSR memory available */
	if (vmgetinfo(&my_info, VMINFO, sizeof(my_info)) != 0)
	{
		perror("vmgetinfo() unexpectedly failed");
		return 1;
	}

	/* Check to see that sufficient BSR memory is available */
	if (my_info.bsr_mem_free < shm_rgn_size)
	{
		fprintf(stderr, "insufficient BSR memory\n");
		return 2;
	}

	/* Allocate a new shared memory region */
	id = shmget(IPC_PRIVATE, shm_rgn_size, IPC_CREAT|IPC_EXCL);

	if (id == -1)
	{
		perror("shmget() failed");
		return 3;
	}

	/* Request BSR memory for the shared memory region */
	if (shmctl(id, SHM_BSR, NULL))
	{
		perror("shmctl(SHM_BSR) failed");
		shmctl(id, IPC_RMID, 0);
		return 4;
	}
	
	/* Attach the shared memory region */
	ptr = shmat(id, NULL, 0);
	if ((int)ptr == -1)
	{
		perror("shmat() failed");
		shmctl(id, IPC_RMID, 0);
		return 5;
	}

	/* BSR memory can now be accessed starting at address - ptr */

	/* Detach shared memory region */
	if (shmdt(ptr))
	{
		perror("shmdt() failed");
		shmctl(id, IPC_RMID, 0);
		return 6;
	}

	/* Delete shared memory region */
	if (shmctl(id, IPC_RMID, 0))
	{
		perror("shmctl(IPC_RMID) failed");
		return 7;
	}

	return 0;
}