IBM Books

Administration Guide


Rmw and Rmw64 (C)

|Using LAPI_Rmw64 is like using LAPI_Rmw, with the |following exceptions: |

This C program is an example of LAPI_Rmw (read-modify-write function):

/* Rmw.c
** Example Program showing use of read modify write function (LAPI_Rmw).
*/
 
#include <lapi.h>
#include <signal.h>
#include <unistd.h>
 
#define A_MAX     2
 
/*
** User error handler function.
*/
 
void my_err_hndlr (lapi_handle_t *hndl, int *error_code,
                   lapi_err_t *err_type, int *task_id, int *src)
{
    char buf[LAPI_MAX_ERR_STRING];
 
    printf("In my error handler, hndl=%d, error_code=%d, err_type=%d, "
           "task_id=%d, src=%d\n", *hndl,*error_code,*err_type,*task_id,*src);
    LAPI_Msg_string(*error_code,buf);
    printf("In my error handler, error code = %d, error reason = %s\n",
           *error_code, buf);
    if (*error_code != LAPI_ERR_TIMEOUT)
        kill(getpid(),SIGTERM);  /* Cause program to exit */
}
 
int
main(int argc, char **argv)                                             main
{
    lapi_handle_t t_hndl;               /* LAPI context handle - returned */
    lapi_info_t   t_info;               /* LAPI info structure */
    int           task_id,              /* My task id */
                  num_tasks;            /* Number of tasks in my job */
    int           t_buf;                /* Buffer to manipulate */
    int           t2_buf;               /* Temporary Buffer */
    lapi_cntr_t   l_cntr;               /* Origin counter */
    lapi_cntr_t   t_cntr;               /* Target counter */
    void          *global_addr[A_MAX];  /* Array to store t_buf addr from */
                                        /* all the tasks.  The size of */
                                        /* this array needs to each */
                                        /* number of tasks */
    void          *tgt_addr[A_MAX];     /* Array to store target counter */
                                        /* addr from all the tasks. */
    int           loop, rc, tgt, val, cur_val, prev_tgt_val;
    char          err_msg_buf[LAPI_MAX_ERR_STRING];
    int           time_out;             /* Get current timeout value */
    int           intr_set;             /* Get current interrupt setting */
 
   bzero(&info_lapi, sizeof(lapi_info_t));
   t_info.err_hndlr = my_err_hndlr;    /* register an error handler */
                                        /* function */
 
    if ((rc = LAPI_Init(&t_hndl, &t_info)) != LAPI_SUCCESS) {
        LAPI_Msg_string(rc, err_msg_buf);
        printf("Error Message: %s, rc = %d\n", err_msg_buf, rc);
        exit (rc);
    }
 
    rc = LAPI_Qenv(t_hndl, TASK_ID, &task_id);
    rc = LAPI_Qenv(t_hndl, NUM_TASKS, &num_tasks);
 
    if (num_tasks != 2) {
        printf("Error Message: Run with MP_PROCS set to 2\n");
        LAPI_Term (t_hndl);
        exit(1);
    }
 
    rc = LAPI_Qenv(t_hndl, TIMEOUT, &time_out);  /* Value in seconds */
    rc = LAPI_Qenv(t_hndl, INTERRUPT_SET, &intr_set);
 
    if (time_out > 30) {
        rc = LAPI_Senv(t_hndl, TIMEOUT, 15);  /* Should be > */
                                              /* MIN_TIMEOUT */
    }
    if (intr_set == 1) {
        rc = LAPI_Senv(t_hndl, INTERRUPT_SET, 0);  /* Turn off */
                                                   /* interrupts */
    }
    /* Turn off parameter checking - default is on */
    rc = LAPI_Senv(t_hndl, ERROR_CHK, 0);
 
    /* Initialize counters to be zero at the start */
    rc = LAPI_Setcntr(t_hndl, &l_cntr, 0);
    rc = LAPI_Setcntr(t_hndl, &t_cntr, 0);
 
    /* Exchange buffer address to every task */
    rc = LAPI_Address_init(t_hndl, &t_buf, global_addr);       /* Collective */
                                                               /* call */
    rc = LAPI_Address_init(t_hndl, &t_cntr, tgt_addr);         /* Collective */
                                                               /* call */
 
    if (task_id == 0) { /* Task id is 0 , Origin */
        tgt = task_id + 1;
        t_buf = 1;  /* Initial value to add at target */
 
        rc = LAPI_Gfence(t_hndl);  /* Global fence to sync before */
                                   /* starting */
        rc = LAPI_Rmw(t_hndl, FETCH_AND_ADD, tgt, global_addr[tgt],
                                      &t_buf, &prev_tgt_val, &l_cntr);
        /* Wait for local Rmw completion */
        rc = LAPI_Waitcntr(t_hndl, &l_cntr, 1, NULL);
 
        printf("Node %d, done issuing Rmw to node %d\n", task_id, tgt);
 
        rc = LAPI_Get(t_hndl,tgt,sizeof(int),global_addr [tgt],
                            (void *)&t2_buf,tgt_addr [tgt],&l_cntr);
        /* Wait for local Get completion */
        rc = LAPI_Waitcntr(t_hndl, &l_cntr, 1, NULL);
        printf("Node %d, done issuing Get from node %d\n", task_id, tgt);
        printf("Result of Get after the Rmw from node %d:\n", tgt);
        printf("Correct value should be %d = %d\n",
                                      t_buf + prev_tgt_val, t2_buf);
    } else { /* Task id is 1 , Target */
        tgt = task_id - 1;
                                                                           ...main
        t_buf = 5; /* Set initial buffer value */
        rc = LAPI_Gfence(t_hndl);  /* Global fence to sync before */
                                   /* starting */
        /* Process Get */
        rc=LAPI_Getcntr(t_hndl, &t_cntr, &val);
        while (val < 1) {
            sleep(1); /* Do some work */
            rc = LAPI_Probe(t_hndl); /* Poll the adapter once */
            rc = LAPI_Getcntr(t_hndl, &t_cntr, &val);
        }
        /* To clear the t_cntr value */
        rc = LAPI_Waitcntr(t_hndl, &t_cntr, 1, &cur_val);
        printf("Node %d, done doing work and processing Get\n", task_id);
    }
    rc = LAPI_Gfence(t_hndl); /* Global fence to sync before */
                              /* terminating job */
    rc = LAPI_Term(t_hndl);
}


[ Top of Page | Previous Page | Next Page | Table of Contents | Index ]