"Fossies" - the Fresh Open Source Software Archive

Member "NetPIPE-3.7.2/src/knem.c" (19 Aug 2010, 9014 Bytes) of package /linux/privat/old/NetPIPE-3.7.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "knem.c" see the Fossies "Dox" file reference documentation.

    1 /*****************************************************************************/
    2 /* "NetPIPE" -- Network Protocol Independent Performance Evaluator.          */
    3 /* Copyright 1997, 1998 Iowa State University Research Foundation, Inc.      */
    4 /*                                                                           */
    5 /* This program is free software; you can redistribute it and/or modify      */
    6 /* it under the terms of the GNU General Public License as published by      */
    7 /* the Free Software Foundation.  You should have received a copy of the     */
    8 /* GNU General Public License along with this program; if not, write to the  */
    9 /* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
   10 /*                                                                           */
   11 /*     * knem.c           ---- knem Linux kernel module memory copy          */
   12 /*                             http://runtime.bordeaux.inria.fr/knem/        */
   13 /*****************************************************************************/
   14 #include    "netpipe.h"
   15 
   16 #include <sys/types.h>
   17 #include <sys/stat.h>
   18 #include <sys/mman.h>
   19 #include <unistd.h>
   20 #include <stdlib.h>
   21 #include <fcntl.h>
   22 #include <stdint.h>
   23 
   24 typedef struct shared_data_t {
   25     uint64_t cookies[2];
   26     double time;
   27     int repeat;
   28     uint8_t sync_counter;
   29 } shared_data_t;
   30 
   31 static int knem_fd = -1;
   32 
   33 static int shared_fd = -1;
   34 static volatile char *shared_map = NULL;
   35 static size_t shared_len = 0;
   36 static volatile shared_data_t *my_shared = NULL;
   37 static int my_cookie_index = 0;
   38 static volatile shared_data_t *peer_shared = NULL;
   39 static int peer_cookie_index = 0;
   40 static uint8_t last_sync_counter_value = 0;
   41 
   42 void Init(ArgStruct *p, int* pargc, char*** pargv)
   43 {
   44     /* Default to software copy mode; may be reset by command line
   45        args */
   46     p->prot.flags = 0;
   47 }
   48 
   49 void Setup(ArgStruct *p)
   50 {
   51     pid_t pid;
   52     struct knem_cmd_info info;
   53     char *filename = (char*) "NPknem.mmap";
   54     size_t pagesize = sysconf(_SC_PAGESIZE);
   55     int need_fork = 0, am_parent = 0, flags = O_RDWR;
   56 
   57     /* If no filename was specified, then we're the parent until we
   58        fork */
   59     if (NULL == p->host) {
   60         am_parent = 1;
   61         need_fork = 1;
   62         unlink(filename);
   63     } 
   64     /* If the file was specified, see if the file exists.  If it does,
   65        then we're the parent.  Otherwise, we're the "child". */
   66     else {
   67         int ret;
   68         struct stat sbuf;
   69 
   70         filename = p->host;
   71         need_fork = 0;
   72 
   73         ret = stat(filename, &sbuf);
   74         if (ret < 0 && errno == ENOENT) {
   75             am_parent = 1;
   76         }
   77     }
   78 
   79     /* Open a file so that we can mmap it */
   80     if (am_parent) {
   81         flags |= O_CREAT;
   82         printf("NPknem: creating shared file: %s\n", filename);
   83     } else {
   84         printf("NPknem: attaching to shared file: %s\n", filename);
   85     }
   86     shared_fd = open(filename, flags, 0600);
   87     if (shared_fd < 0) {
   88         fprintf(stderr, "Netpipe failed to create a file to mmap.  Aborting in despair.\n");
   89         exit(1);
   90     }
   91     shared_len = pagesize * 2;
   92     if (0 != ftruncate(shared_fd, shared_len)) {
   93         fprintf(stderr, "Netpipe failed to set the size of a shared file.  Aborting in despair.\n");
   94         exit(1);
   95     }
   96 
   97     /* Now fork the child and reset transmitter / receiver flags as
   98        appropriate */
   99     if (need_fork) {
  100         pid = fork();
  101         if (0 == pid) {
  102             am_parent = 0;
  103         } else {
  104             am_parent = 1;
  105         }
  106     }
  107     if (am_parent) {
  108         p->rcv = 0;
  109         p->tr = 1;
  110     } else {
  111         p->rcv = 1;
  112         p->tr = 0;
  113     }
  114 
  115     /* Map an anonymous shared memory segment between the two
  116        processes for passing cookies, etc. */
  117     shared_map = mmap(NULL, shared_len, (PROT_READ | PROT_WRITE), MAP_SHARED, 
  118                   shared_fd, 0);
  119     if (MAP_FAILED == shared_map) {
  120         if (am_parent || !need_fork) {
  121             perror("mmap");
  122             fprintf(stderr, "Netpipe failed to mmap a shared file.  Aborting in despair.\n");
  123         }
  124         exit(1);
  125     }
  126 
  127     /* Once we have both mmaped the file, parent unlinks the file so
  128        that we don't deal with filesystem synchronization.  Parent's
  129        data is the first page; child's data is the second.  This
  130        way we can pin them down to our local memory via "first touch"
  131        method. */
  132     if (am_parent) {
  133         my_shared = (shared_data_t*) shared_map;
  134         peer_shared = (shared_data_t*) (shared_map + pagesize);
  135     } else {
  136         peer_shared = (shared_data_t*) shared_map;
  137         my_shared = (shared_data_t*) (shared_map + pagesize);
  138     }
  139     memset((void*) my_shared, 0, sizeof(*my_shared));
  140     Sync(p);
  141     if (am_parent){ 
  142         unlink(filename);
  143     }
  144 
  145     /* See if we can find /dev/knem */
  146     knem_fd = open(KNEM_DEVICE_FILENAME, O_RDWR);
  147     if (knem_fd < 0) {
  148         if (am_parent || !need_fork) {
  149             fprintf(stderr, "Netpipe cannot open %s on this host.  Aborting in despair.\n", KNEM_DEVICE_FILENAME);
  150         }
  151         exit(1);
  152     }
  153 
  154     /* Check that we're compiled against the same ABI version that
  155        we're running with */
  156     if (ioctl(knem_fd, KNEM_CMD_GET_INFO, &info) < 0) {
  157         if (am_parent || !need_fork) {
  158             fprintf(stderr, "Netpipe failed to get ABI version from %s.  Aborting in despair.\n", KNEM_DEVICE_FILENAME);
  159         }
  160         exit(1);
  161     }
  162 
  163 #if KNEM_ABI_VERSION < 0x0000000c
  164 #error KNEM is too old, pleasse upgrade to 0.7 or later
  165 #endif
  166 
  167     if (KNEM_ABI_VERSION != info.abi) {
  168         if (am_parent || !need_fork) {
  169             fprintf(stderr, "The knem ABI that Netpipe was compiled against is different than that of %s.  Aborting in despair.\n", KNEM_DEVICE_FILENAME);
  170         }
  171         exit(1);
  172     }
  173 
  174     /* If DMA was asked for, ensure that it's available */
  175     if (0 != p->prot.flags && 0 == (info.features & KNEM_FEATURE_DMA)) {
  176         if (am_parent || !need_fork) {
  177             fprintf(stderr, "DMA copy mode was requested but is not supported in the running kernel.  Aborting in despair.\n");
  178         }
  179         exit(1);
  180     }
  181 }   
  182 
  183 void Sync(ArgStruct *p)
  184 {
  185     uint8_t save;
  186 
  187     ++my_shared->sync_counter;
  188     do {
  189         save = peer_shared->sync_counter;
  190         if (last_sync_counter_value != save) {
  191             ++last_sync_counter_value;
  192             break;
  193         }
  194     } while (1);
  195 }
  196 
  197 void PrepareToReceive(ArgStruct *p)
  198 {
  199 }
  200 
  201 void SendData(ArgStruct *p)
  202 {
  203     struct knem_cmd_param_iovec knem_iov = {
  204         .base = (uintptr_t) p->s_ptr,
  205         .len = p->bufflen
  206     };
  207     struct knem_cmd_create_region createregioncmd = {
  208         .iovec_array = (uintptr_t) &knem_iov,
  209         .iovec_nr = 1,
  210         .flags = KNEM_FLAG_SINGLEUSE,
  211         .protection = PROT_READ,
  212     };
  213 
  214     /* Create the region */
  215     if (0 != ioctl(knem_fd, KNEM_CMD_CREATE_REGION, &createregioncmd)) {
  216         fprintf(stderr, "Netpipe failed to KNEM_CMD_CREATE_REGION.  Aborting in despair.\n");
  217         exit(1);
  218     }
  219 
  220     /* Send the cookie to the peer */
  221     peer_shared->cookies[peer_cookie_index] = createregioncmd.cookie;
  222     peer_cookie_index = (0 == peer_cookie_index) ? 1 : 0;
  223 }
  224 
  225 void RecvData(ArgStruct *p)
  226 {
  227     uint64_t cookie;
  228 
  229     struct knem_cmd_param_iovec knem_iov = {
  230         .base = (uintptr_t) p->r_ptr,
  231         .len = p->bufflen
  232     };
  233     struct knem_cmd_inline_copy icopycmd = {
  234         .local_iovec_array = (uintptr_t) &knem_iov,
  235         .local_iovec_nr = 1,
  236         .write = 0,
  237         .async_status_index = 0,
  238         .flags = p->prot.flags
  239     };
  240 
  241     /* Wait for the sender to set my cookie */
  242     while (0 == (cookie = my_shared->cookies[my_cookie_index])) {
  243         continue;
  244     }
  245     icopycmd.remote_cookie = cookie;
  246     icopycmd.remote_offset = 0;
  247     my_shared->cookies[my_cookie_index] = 0;
  248     my_cookie_index = (0 == my_cookie_index) ? 1 : 0;
  249 
  250     /* Initiate the receive (synchronous mode) */
  251     if (0 != ioctl(knem_fd, KNEM_CMD_INLINE_COPY, &icopycmd)) {
  252         fprintf(stderr, "Netpipe failed to KNEM_CMD_INLINE_COPY.  Aborting in despair.\n");
  253         exit(1);
  254     }
  255 
  256     if (icopycmd.current_status != KNEM_STATUS_SUCCESS) {
  257         fprintf(stderr, "Netpipe failed to complete KNEM_CMD_INLINE_COPY.  Aborting in despair.\n");
  258         exit(1);
  259     }
  260 }
  261 
  262 void SendTime(ArgStruct *p, double *t)
  263 {
  264     /* Only child calls SendTime */
  265     peer_shared->time = *t;
  266     Sync(p);
  267 }
  268 
  269 void RecvTime(ArgStruct *p, double *t)
  270 {
  271     /* Only parent calls RecvTime */
  272     Sync(p);
  273     *t = my_shared->time;
  274 }
  275 
  276 void SendRepeat(ArgStruct *p, int rpt)
  277 {
  278     /* Only parent calls SendRepeat */
  279     peer_shared->repeat = rpt;
  280     Sync(p);
  281 }
  282 
  283 void RecvRepeat(ArgStruct *p, int *rpt)
  284 {
  285     /* Only child calls RecvRepeat */
  286     Sync(p);
  287     *rpt = my_shared->repeat;
  288 }
  289 
  290 void CleanUp(ArgStruct *p)
  291 {
  292     if (NULL != shared_map && 0 != shared_len) {
  293         munmap((void*) shared_map, shared_len);
  294     }
  295     if (-1 != shared_fd) {
  296         close(shared_fd);
  297     }
  298     close(knem_fd);
  299 }
  300 
  301 void Reset(ArgStruct *p)
  302 {
  303 }
  304 
  305 void AfterAlignmentInit(ArgStruct *p)
  306 {
  307 }