この節では、簡単なプログラムを使用して RSMAPI の使用例を示します。このプログラムはエクスポータノードとインポータノードの 2 つのノード上で動作します。エクスポータノードはメモリーセグメントを作成および公開し、メッセージがセグメントに書き込まれるまで待機します。インポータノードはエクスポートされたセグメントに接続し、メッセージを書き込み、次に、エクスポータにシグナルを送信します。
/* * Copyright (c) 1998 by Sun Microsystems, Inc. * All rights reserved. */ #include <stdio.h> #include <rsm/rsmpai.h> #include <errno.h> /* このプログラムを実行するには次の手順を行う: 1 つ目のノード (ノード ID = 1): rsmtest -e -n 2 2 つ目のノード (ノード ID = 2): rsmtest -i -n 1 プログラムはコンソールでインポータにメッセージをプロンプト 表示する。任意のメッセージを入力してリターンキーを入力する。 エクスポートコンソールにメッセージが表示される。 */ typedef struct { char out; char in; char data[1]; }msg_t; #define SEG_ID 0x400000 #define EXPORT 0 #define IMPORT 1 #define BUFSIZE (1024 * 8) #define DEFAULT_SEGSZ BUFSIZE #define RSM_PERM_READ 0400 #define RSM_PERM_WRITE 0200 #define RSM_PERM_RDWR (RSM_PERM_READ|RSM_PERM_WRITE) #define RSM_ACCESS_TRUSTED 0666 rsm_topology_t *tp; int iterations = 10; int mode = EXPORT; int test = 0; char *buf; int buflen = BUFSIZE; int offset = 0; volatile char *iva; int status; rsm_memseg_id_t segid; rsmapi_controller_handle_t ctrl; rsmapi_controller_attr_t attr; rsm_memseg_export_handle_t seg; rsm_memseg_import_handle_t imseg; rsm_access_entry_t list[2]; rsm_node_id_t dest; extern void *valloc(size_t); extern void exit(); extern void sleep(); extern int atoi(const char *); /* 次の関数はセグメントをエクスポートし、それを発行する */ static int export() { int i; /* メモリーを割り当て、クリアする */ buf = (char *)valloc(buflen); if (!buf) { (void) fprintf(stderr, "Unable to allocate memory\n"); exit (1); } for (i = 0; i < buflen; i++) buf[i] = 0; /* エクスポートメモリーセグメントを作成する */ status = rsm_memseg_export_create(ctrl, &seg, (void *)buf, buflen); if (status != 0) { (void) fprintf(stderr, "unable to create an exported segment %d\n", status); exit(1); } /* ノード 1 とノード 2 に発行するアクロスリストを設定する */ list[0].ae_node = tp->topology_hdr.local_nodeid ; /* 読み取り権と書き込み権を許可する */ list[0].ae_permission = RSM_ACCESS_TRUSTED; list[1].ae_node = tp->topology_hdr.local_nodeid + 1; /* 読み取り権とアクセス権を許可する */ list[1].ae_permission = RSM_ACCESS_TRUSTED; /* 作成されたエクスポートセグメントを発行する */ status = rsm_memseg_export_publish(seg, &segid, list, 0); if (status != 0) { (void) fprintf(stderr, "unable to pub segment %d\n", status); exit(1); } return (0); } /* 次の関数はエクスポートされたメモリーセグメントへの接続に使用される */ static void import() { /* ローカルの仮想アドレスを介してアクセスするために * エクスポートされたセグメントに接続してマッピングを設定する */ again: status = rsm_memseg_import_connect(ctrl, dest, segid, RSM_PERM_RDWR, &imseg); if (status != 0) { (void) fprintf(stderr, "unable to conect to segment %x err %x\n", segid, status); sleep(1); goto again; } iva = NULL; status = rsm_memseg_import_map(imseg, (void **)&iva, RSM_MAP_NONE, RSM_PERM_RDWR, 0, buflen); if (status != 0) { (void) fprintf(stderr, "unable to mmap segment %d\n", status); exit(1); } } /* エクスポートセグメントの発行を取り消して破壊する */ static void export_close() { again: status = rsm_memseg_export_unpublish(seg); if (status != 0) { (void) fprintf(stderr, "unable to create an unpub segment %d\n", status); sleep(10); goto again; } status = rsm_memseg_export_destroy(seg); if (status != 0) { (void) fprintf(stderr, "unable to destroy segment %d\n", status); exit(1); } } /* 仮想アドレスのマッピングを取り消してセグメントの接続を解除する */ static void import_close() { status = rsm_memseg_import_unmap(imseg); if (status != 0) { (void) fprintf(stderr, "unable to unmap segment %d\n", status); exit(1); } status = rsm_memseg_import_disconnect(imseg); if (status != 0) { (void) fprintf(stderr, "unable to disconnect segment %d\n", status); exit(1); } } static void test0() { volatile msg_t *mbuf; /* 報告エラーへのバリア */ rsmapi_barrier_t bar; int i; if (mode == EXPORT) { (void) export(); mbuf = (msg_t *)(buf + offset); mbuf->in = mbuf->out = 0; } else { import(); mbuf = (msg_t *)(iva + offset); rsm_memseg_import_init_barrier(imseg, RSM_BARRIER_NODE, &bar); } (void) printf("Mbuf is %x\n", (uint_t)mbuf); while (iterations--> 0) { int e; switch (mode) { case EXPORT: while (mbuf->out == mbuf->in) { (void) rsm_intr_signal_wait(seg, 1000); } (void) printf("msg [0x%x %d %d] ", (uint_t)mbuf, (int)mbuf->out, mbuf->in); for (i = 0; mbuf->data[i] != '\0' && i < buflen; i++) { (void) putchar(mbuf->data[i]); mbuf->data[i] = '?'; } (void) putchar('\n'); mbuf->out++; break; case IMPORT: (void) printf("Enter msg [0x%x %d]: ", (uint_t)mbuf, mbuf->out, mbuf->in); retry: e = rsm_memseg_import_open_barrier(&bar); if (e != 0) { (void) printf("Barrier open failed %x\n", e); exit(1); } for (i = 0; (mbuf->data[i] = getchar()) != '\n'; i++) ; mbuf->data[i] = '\0'; rsm_memseg_import_order_barrier(&bar); mbuf->in++; e = rsm_memseg_import_close_barrier(&bar); if (e != 0) { (void) printf("Barrier close failed, %d\n", e); goto retry; } (void)rsm_intr_signal_post(imseg); break; } } if (mode == IMPORT) { import_close(); } else { export_close(); } } void main(int argc, char *argv[]) { int unit = 0; char *device = "sci0"; int i; segid = SEG_ID; buflen = DEFAULT_SEGSZ; while ((i = getopt(argc, argv, "OCGeid:b:sl:n:k:t:c:u:v")) != -1) { switch (i) { case 'e': mode = EXPORT; break; case 'i': mode = IMPORT; break; case 'n': dest = atoi(optarg); if ((int)dest < 0) dest = 0; break; default: (void) fprintf(stderr, "Usage: %s -ei -n dest\n", argv[0]); exit(1); } } status = rsm_get_controller(device, &ctrl); if (status != 0) { (void) fprintf(stderr, "Unable to get controller\n"); exit(1); } status = rsm_get_controller_attr(ctrl, &attr); status = rsm_get_interconnect_topology(&tp); if (status != 0) { (void) fprintf(stderr, "Unable to get topology\n"); exit(1); } else { (void) printf("Local node id = %d\n", tp->topology_hdr.local_nodeid); } if (dest == 0) { dest = tp->topology_hdr.local_nodeid; (void) printf("Dest is adjusted to %d\n", dest); } switch (test) { case 0: test0(); break; default: (void) printf("No test executed\n"); break; } }