home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume22 / ftape / part01 / ftapeipc.c < prev    next >
C/C++ Source or Header  |  1991-09-04  |  6KB  |  278 lines

  1. #ifndef lint
  2. static char sccs_id[] = "@(#)2.4    ftapeipc.c 91/09/03 FAST TAPE";
  3. #endif
  4. /*
  5.  * Original author: Kari Yli-Kuha, SQ Consulting Ltd.
  6.  * Address: Kanslerinkatu 8, 33720 Tampere, Finland
  7.  * Phone: (358) 31 165200 
  8.  *
  9.  * Shared memory handling for FAST TAPE
  10.  * Uses SysV shared memory and semaphores
  11.  *
  12.  * Functions:
  13.  *
  14.  *  create_shared()  creates shared memory buffer SHBUF and attaches
  15.  *      global pointer "shbuf" to it. 
  16.  *
  17.  *  attach_shared() attaches to an already existing shared memory with "shbuf"
  18.  *
  19.  *  delete_shared() releases shared memory and semaphores
  20.  *
  21.  *  read_cpio() reads cpio(1) stdout from given pipe fd and fills
  22.  *      shared memory buffers.
  23.  *
  24.  *  write_cpio() reads shared memory buffers and writes to cpio(1) stdin
  25.  *      thru given pipe fd
  26.  *
  27.  *  semdown() decrements given semaphore (waiting for a buffer)
  28.  *
  29.  *  semdown() increments given semaphore (releasing a buffer)
  30.  */
  31.  
  32. #include <stdio.h>
  33. #include <fcntl.h>
  34. #include <errno.h>
  35. #include <sys/types.h>
  36. #include <sys/ipc.h>
  37. #include <sys/shm.h>
  38. #include <sys/sem.h>
  39. #include <sys/stat.h>
  40.  
  41. #include "ftape.h"
  42.  
  43. struct SHBUF *shbuf;       /* shared memory address - GLOBAL */
  44. static int sem_id;         /* semaphore id - STATIC     */
  45. static int shm_id;         /* shared memory id - STATIC */
  46.  
  47. extern char *shmat();
  48.  
  49.  
  50. /*
  51.  * create_shared() allocates 'shbufs' SHBUF structures in shared memory.
  52.  * Shared memory base address is placed in global variable "shbuf".
  53.  *
  54.  * Upon successful operation 0 is returned.
  55.  * Otherwise -1 is returned and error is written to stderr.
  56.  * Reason for failure is normally that SHMMAX is exceeded.
  57.  */
  58. create_shared(key, shm_addr, shbufs)
  59. char  *key;                /* param to ftok(), normally /dev/tape */
  60. char  *shm_addr;           /* address to attach to (normally NULL) */
  61. int   shbufs;              /* # of buffer to allocate */
  62. {
  63.   key_t core_key = ftok(key, 0);
  64.   if (core_key == -1) {
  65.     perror("ftok");
  66.     return(-1);
  67.   }
  68.  
  69.   /* get semaphores */
  70.   sem_id = semget (core_key, NSEMS, 0600 | IPC_CREAT);
  71.   if (sem_id < 0) {
  72.     perror ("semget");
  73.     return (-1);
  74.   }
  75.  
  76.   /* get shm */
  77.   if ((shm_id = shmget(core_key, shbufs * sizeof(struct SHBUF ), 
  78.                IPC_CREAT | 0600)) == -1) {
  79.     perror ("shmget");
  80.     return(-1);
  81.   }
  82.   /* attach */
  83.   if ((shbuf = (struct SHBUF *)shmat(shm_id, (char *) shm_addr, 0)) 
  84.       == (struct SHBUF *) -1) {
  85.     perror ("shmat");
  86.     return(-1);
  87.   }
  88.  
  89.   /* initialize free buffers */
  90.   semup (BUFFERS_FREE, shbufs);
  91.   return (0);
  92. }
  93.  
  94. /*
  95.  * delete_shared() releases shared memory and semaphores
  96.  * sem_id and shm_id are static
  97.  */
  98. delete_shared()
  99. {
  100.   /* release semaphores */
  101.   if (semctl (sem_id, 0, IPC_RMID, NULL) < 0)
  102.     perror ("semctl IPC_RMID");
  103.     
  104.   /* release shared memory */
  105.   if (shmctl(shm_id, IPC_RMID, (struct shmid_ds *)0) == -1)
  106.     perror ("shmctl IPC_RMID");
  107.  
  108.   return(0);
  109. }
  110.  
  111.  
  112. /*
  113.  * attach_shared() attaches to an already existing shared memory
  114.  * and semaphores. 'key' is used as a parameter to ftok().
  115.  */
  116. attach_shared(key)
  117. char  *key;
  118. {
  119.   key_t core_key = ftok (key, 0);
  120.  
  121.   if (core_key == -1) {
  122.     perror ("ftok");
  123.     return(-1);
  124.   }
  125.  
  126.   /* get semaphores */
  127.   sem_id = semget (core_key, NSEMS, 00600);
  128.   if (sem_id < 0) {
  129.     perror ("semget");
  130.     return (-1);
  131.   }
  132.  
  133.   /* get already allocated shared memory */
  134.   if ((shm_id = shmget(core_key, 0, IPC_ALLOC | 0600)) == -1) {
  135.     perror ("shmget (IPC_ALLOC)");
  136.     return(-1);
  137.   }
  138.   if ((shbuf = (struct SHBUF *)shmat(shm_id, 0, 0)) == (struct SHBUF *) -1) {
  139.     perror ("shmat");
  140.     return(-1);
  141.   }
  142.   return (0);
  143. }
  144.  
  145.  
  146. /*
  147.  * read_cpio
  148.  *
  149.  * Write to shared memory buffers from the given file descriptor.
  150.  *
  151.  * Reading is stopped when we get less than SHBUFSIZE bytes.
  152.  * The next buffer is marked to contain 0 bytes.
  153.  */
  154. read_cpio(fd, shbufs)
  155. int fd;
  156. int shbufs;
  157. {
  158.   int nbuf;
  159.   struct SHBUF *buf = shbuf;
  160.  
  161.   nbuf = 0;
  162.   do {
  163.     semdown (BUFFERS_FREE, 1);
  164.  
  165.     /* check errors while reading tape */
  166.     while ((buf->nread = read (fd, buf->buf, SHBUFSIZE*512)) == -1) {
  167.       if (errno != EINTR) {  /* signal, eg SIGCLD from cpio */
  168.     perror ("read");
  169.     buf->nread = 0;
  170.     return (-1);
  171.       }
  172.     }
  173.  
  174.     semup (BUFFERS_AVAIL, 1);
  175.  
  176.     if (buf->nread == 0)
  177.       break;   /* EOF */
  178.  
  179.     buf++; nbuf++;
  180.     if (nbuf == shbufs) {
  181.       nbuf = 0;
  182.       buf = shbuf;
  183.     }
  184.   } while (1);
  185.  
  186.   /* 
  187.    * End of file, mark next buffer to contain 0 bytes 
  188.    * so "ftapewrite" knows to finish.
  189.    */
  190.   buf++; nbuf++;
  191.   if (nbuf == shbufs) {
  192.     nbuf = 0;
  193.     buf = shbuf;
  194.   }
  195.   semdown (BUFFERS_FREE, 1);
  196.   buf->nread = 0;
  197.   semup (BUFFERS_AVAIL, 1);
  198.   return (0);
  199. }
  200.  
  201. /*
  202.  * write_cpio
  203.  *
  204.  * writes from shared memory buffers to given file descriptor.
  205.  * 
  206.  * Writing is stopped when we get a byffer with 0 bytes in it.
  207.  */
  208. write_cpio(fd, shbufs)
  209. int fd;
  210. int shbufs;
  211. {
  212.   int nbuf = 0;               /* buffer counter */
  213.   struct SHBUF *buf = shbuf;
  214.  
  215.   nbuf = 0;
  216.   while (1) {
  217.     semdown (BUFFERS_AVAIL, 1);
  218.  
  219.     if (buf->nread == 0) /* end of archive */
  220.       break;
  221.  
  222.     write (fd, (char *)buf->buf, buf->nread);
  223.     semup (BUFFERS_FREE, 1);
  224.  
  225.     buf++; nbuf++;
  226.     if (nbuf == shbufs) {
  227.       nbuf = 0;
  228.       buf = shbuf;
  229.     }
  230.   }
  231.   (void) close(fd); /* close to flush the pipe */
  232.   return (0);
  233. }
  234.  
  235.  
  236. /*
  237.  * Increment a semaphore 
  238.  */
  239.  
  240. void semup (sem, val) 
  241. int sem;
  242. int val;
  243. {
  244.   struct sembuf sop;
  245.  
  246.   sop.sem_num = sem;
  247.   sop.sem_op = val;
  248.   sop.sem_flg = 0;
  249.  
  250.   if (semop (sem_id, &sop, 1) < 0) {
  251.     if (errno != EINVAL) {
  252.       perror("semop up");
  253.       exit(1);
  254.     }
  255.   }
  256. }
  257.  
  258.  
  259. /* Decrement a semaphore */
  260.  
  261. void semdown (sem, val) 
  262. int sem;
  263. int val;
  264. {
  265.   struct sembuf sop;
  266.  
  267.   sop.sem_num = sem;
  268.   sop.sem_op = -val;
  269.   sop.sem_flg = 0;
  270.  
  271.   while (semop (sem_id, &sop, 1) < 0) {
  272.     if (errno != EINTR) {
  273.       perror ("semop down");
  274.       exit (1);
  275.     }
  276.   }
  277. }
  278.