本节提供了一个简单程序来说明 RSMAPI 的用法。此程序在两个节点上运行:导出者节点和导入者节点。导出者节点用于创建和发布内存段,然后等待将消息写入段。导入者节点用于连接到导出的段,写入消息,然后通知导出者。
/*
* 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;
}
}