This section provides a simple program to illustrate the usage of the RSMAPI. The program runs on two nodes: an exporter node and an importer node. The exporter node creates and publishes a memory segment, then waits for a message to be written in the segment. The importer node connects to the exported segment, writes a message, and then signals the exporter.
/* * Copyright (c) 1998 by Sun Microsystems, Inc. * All rights reserved. */ #include <stdio.h> #include <rsm/rsmpai.h> #include <errno.h> /* To run this program do the following: First node(assuming node id = 1): rsmtest -e -n 2 Second node(assuming node id = 2): rsmtest -i -n 1 The program will prompt the importer for a message at the console. Enter any message and hit return. The message will be displayed on the export console. */ 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 *); /* The following function exports a segment and publishes it. */ static int export() { int i; /* allocate and clear memory */ 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; /* Create an export memory segment */ 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); } /* Set up access list for publishing to nodes 1 and 2 */ list[0].ae_node = tp->topology_hdr.local_nodeid ; /* Allow read and write permissions */ list[0].ae_permission = RSM_ACCESS_TRUSTED; list[1].ae_node = tp->topology_hdr.local_nodeid + 1; /* Allow read and write permissions */ list[1].ae_permission = RSM_ACCESS_TRUSTED; /* Publish the created export segment */ 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); } /* The following function is used to connect to an exported memory segment. */ static void import() { /* Connect to exported segment and set up mapping for * access through local virtual addresses. */ 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); } } /* Unpublish and destroy the export segment */ 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); } } /* Unmap the virtual address mapping and disconnect the segment */ 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; /* Barrier to report error */ 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; } }