semshm.c
上传用户:xiejiait
上传日期:2007-01-06
资源大小:881k
文件大小:10k
源码类别:

SCSI/ASPI

开发平台:

MultiPlatform

  1. /* @(#)semshm.c 1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt */
  2. #ifndef lint
  3. static char     sccsid[] =
  4. "@(#)semshm.c 1.2 99/12/19 Copyright 1998,1999 Heiko Eissfeldt";
  5. #endif
  6. #define IPCTST
  7. #undef IPCTST
  8. /* -------------------------------------------------------------------- */
  9. /*        semshm.c                                                      */
  10. /* -------------------------------------------------------------------- */
  11. /*               int seminstall(key,amount)                             */
  12. /*               int semrequest(semid,semnum)                           */
  13. /*               int semrelease(semid,semnum)                           */
  14. /* -------------------------------------------------------------------- */
  15. #include "config.h"
  16. #if     !defined(HAVE_SMMAP) && !defined(HAVE_USGSHM) && !defined(HAVE_DOSALLOCSHAREDMEM)
  17. #undef  FIFO                    /* We cannot have a FIFO on this platform */
  18. #endif
  19. #if !defined(USE_MMAP) && !defined(USE_USGSHM)
  20. #define USE_MMAP
  21. #endif
  22. #ifndef HAVE_SMMAP
  23. #       undef   USE_MMAP
  24. #       define  USE_USGSHM      /* SYSV shared memory is the default    */
  25. #endif
  26. #ifdef  USE_MMAP                /* Only want to have one implementation */
  27. #       undef   USE_USGSHM      /* mmap() is preferred                  */
  28. #endif
  29. #ifdef HAVE_DOSALLOCSHAREDMEM
  30. #       undef   USE_MMAP
  31. #       undef   USE_USGSHM
  32. # define USE_OS2SHM
  33. #endif
  34. #include <stdio.h>
  35. #include <stdlib.h>
  36. #if defined (HAVE_UNISTD_H) && (HAVE_UNISTD_H == 1)
  37. #include <sys/types.h>
  38. #include <unistd.h>
  39. #endif
  40. #include <fctldefs.h>
  41. #include <errno.h>
  42. #include <standard.h>
  43. #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
  44. #include <sys/types.h>
  45. #include <sys/ipc.h>
  46. #include <sys/sem.h>
  47. #endif
  48. #ifdef  USE_USGSHM
  49. #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
  50. #include <sys/types.h>
  51. #include <sys/ipc.h>
  52. #include <sys/shm.h>
  53. #endif
  54. #endif
  55. #ifdef  USE_MMAP
  56. #if defined(HAVE_SMMAP) && defined(USE_MMAP)
  57. #include <sys/mman.h>
  58. #endif
  59. #endif
  60. #include <scg/scsitransp.h>
  61. #include "mytype.h"
  62. #include "interface.h"
  63. #include "ringbuff.h"
  64. #include "global.h"
  65. #include "semshm.h"
  66. #ifdef DEBUG_SHM
  67. char *start_of_shm;
  68. char *end_of_shm;
  69. #endif
  70. int flush_buffers __PR((void));
  71. /*------ Semaphore interfacing (for special cases only) ----------*/
  72. /*------ Synchronization with pipes is preferred        ----------*/
  73. #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
  74. int sem_id;
  75. static int seminstall __PR((key_t key, int amount));
  76. static int seminstall(key, amount)
  77. key_t key;
  78. int amount;
  79. {
  80.   int           ret_val;
  81.   int           semflag;
  82.   semflag = IPC_CREAT | 0600;
  83. #ifdef IPCTST
  84.   fprintf(stderr,"seminstall: key: %d, #sems %d, flags %4xn",
  85.           key,amount,semflag);
  86. #endif
  87.   ret_val = semget(key,amount,semflag);
  88.   if ( ret_val == -1 )
  89.   {
  90.     fprintf(stderr,"semget: (Key %lx, #%d) failed: ",
  91.             (long)key,amount);
  92.     perror("");
  93.   }
  94.   return ret_val;
  95. }
  96. /*-----------------------------------------------------------------*/
  97. int semrequest(semid, semnum)
  98. int semid;
  99. int semnum;
  100. {
  101.   struct sembuf sops[1];
  102.   int    ret_val;
  103. #ifdef IPCTST
  104.   fprintf(stderr,"pid %d, ReQuest id:num %d:%dn",getpid(),semid,semnum);
  105. #endif
  106.   sops[0].sem_op  = -1;
  107.   sops[0].sem_num = (short) semnum;
  108.   sops[0].sem_flg = 0;
  109.   do {
  110.     errno = 0;
  111.     ret_val = semop(semid,sops,1);
  112.     if (ret_val == -1 && errno != EAGAIN && errno != EINTR)
  113.       {
  114. fprintf(stderr,"Request Sema %d(%d) failed: ",semid,semnum);
  115. perror("");
  116.       }
  117.   } while (errno == EAGAIN || errno == EINTR);
  118.   return(ret_val);
  119. }
  120. /*-----------------------------------------------------------------*/
  121. int semrelease(semid, semnum, amount)
  122. int semid;
  123. int semnum;
  124. int amount;
  125. {
  126.   struct sembuf sops[1];
  127.   int    ret_val;
  128. #ifdef IPCTST
  129.   fprintf(stderr,"%d RL %d:%dn",getpid(),semid,semnum);
  130. #endif
  131.   sops[0].sem_op  = amount;
  132.   sops[0].sem_num = (short) semnum;
  133.   sops[0].sem_flg = 0;
  134.   ret_val = semop(semid,sops,1);
  135.   if ( ret_val == -1 && errno != EAGAIN)
  136.   {
  137.     fprintf(stderr,"Release Sema %d(%d) failed: ",semid,semnum);
  138.     perror("");
  139.   }
  140.   return(ret_val);
  141. }
  142. int flush_buffers()
  143. {
  144. return 0;
  145. }
  146. #else
  147. /*------ Synchronization with pipes ----------*/
  148. int pipefdp2c[2];
  149. int pipefdc2p[2];
  150. void init_pipes()
  151. {
  152.   if (pipe(pipefdp2c) < 0) {
  153.     perror("cannot create pipe parent to child");
  154.     exit(1);
  155.   }
  156.   if (pipe(pipefdc2p) < 0) {
  157.     perror("cannot create pipe child to parent");
  158.     exit(1);
  159.   }
  160. }
  161. void init_parent()
  162. {
  163.   close(pipefdp2c[0]);
  164.   close(pipefdc2p[1]);
  165. }
  166. void init_child()
  167. {
  168.   close(pipefdp2c[1]);
  169.   close(pipefdc2p[0]);
  170. }
  171. int semrequest(dummy, semnum)
  172. int dummy;
  173. int semnum;
  174. {
  175.   if (semnum == FREE_SEM /* 0 */)  {
  176.       int retval;
  177.     if ((*total_segments_read) - (*total_segments_written) >= global.buffers) {
  178.       /* child/reader waits for freed buffers from the parent/writer */
  179.       *child_waits = 1;
  180.       retval = read(pipefdp2c[0], &dummy, 1) != 1;
  181.       return retval;
  182.     }
  183.   } else {
  184.       int retval;
  185.     if ((*total_segments_read) == (*total_segments_written)) {
  186.       /* parent/writer waits for defined buffers from the child/reader */
  187.       *parent_waits = 1;
  188.       retval = read(pipefdc2p[0], &dummy, 1) != 1;
  189.       return retval;
  190.     }
  191.   }
  192.   return 0;
  193. }
  194. int semrelease(dummy, semnum, amount)
  195. int dummy;
  196. int semnum;
  197. int amount;
  198. {
  199.   PRETEND_TO_USE(dummy);
  200.   if (semnum == FREE_SEM /* 0 */)  {
  201.     if (*child_waits == 1) {
  202.       int retval;
  203.       /* parent/writer signals freed buffer to the child/reader */
  204.       *child_waits = 0;
  205.       retval = write(pipefdp2c[1], "12345678901234567890", amount) != amount;
  206.       return retval;
  207.     }
  208.   } else {
  209.     if (*parent_waits == 1) {
  210.       int retval;
  211.       /* child/reader signals defined buffers to the parent/writer */
  212.       *parent_waits = 0;
  213.       retval = write(pipefdc2p[1], "12345678901234567890", amount) != amount;
  214.       return retval;
  215.     }
  216.   }
  217.   return 0;
  218. }
  219. int flush_buffers()
  220. {
  221. if ((*total_segments_read) > (*total_segments_written)) {
  222. return write(pipefdc2p[1], "1", 1) != 1;
  223. }
  224. return 0;
  225. }
  226. #endif
  227. /*------------------- Shared memory interfacing -----------------------*/
  228. #ifdef  USE_USGSHM
  229. #if defined(HAVE_SHMAT) && (HAVE_SHMAT == 1)
  230. static int shm_request __PR((unsigned int size, unsigned char **memptr));
  231. /* request a shared memory block */
  232. static int shm_request(size, memptr)
  233. unsigned int size;
  234. unsigned char **memptr;
  235. {
  236.   int   ret_val;
  237.   int   shmflag;
  238.   int   SHMEM_ID;
  239.   int    cmd;
  240.   struct shmid_ds buf;
  241.   key_t key = IPC_PRIVATE;
  242.   shmflag = IPC_CREAT | 0600;
  243.   ret_val = shmget(key,(int)size,shmflag);
  244.   if ( ret_val == -1 )
  245.   {
  246.     perror("shmget");
  247.     return -1;
  248.   }
  249.   SHMEM_ID = ret_val;
  250.   cmd = IPC_STAT;
  251.   ret_val = shmctl(SHMEM_ID,cmd,&buf);
  252. #ifdef IPCTST
  253.   fprintf(stderr, "%d: shmctl STAT= %d, SHM_ID: %d, key %ld cuid %d cgid %d mode %3o size %dn",
  254.           getpid(),ret_val,SHMEM_ID,
  255.           (long) buf.shm_perm.key,buf.shm_perm.cuid,buf.shm_perm.cgid,
  256.           buf.shm_perm.mode,buf.shm_segsz);
  257. #endif
  258.   *memptr = (unsigned char *) shmat(SHMEM_ID, NULL, 0);
  259.   if (*memptr == (unsigned char *) -1) {
  260.     *memptr = NULL;
  261.     fprintf( stderr, "shmat failed for %u bytesn", size);
  262.     return -1;
  263.   }
  264.   if (shmctl(SHMEM_ID, IPC_RMID, 0) < 0) {
  265.     fprintf( stderr, "shmctl failed to detach shared memory segmentn");
  266.     return -1;
  267.   }
  268. #ifdef DEBUG_SHM
  269.   start_of_shm = *memptr;
  270.   end_of_shm = (char *)(*memptr) + size;
  271.   fprintf(stderr, "Shared memory from %p to %p (%u bytes)n", start_of_shm, end_of_shm, size);
  272. #endif
  273.   return 0;
  274. }
  275. #endif
  276. #endif
  277. #ifdef  USE_MMAP
  278. #if defined(HAVE_SMMAP) && defined(USE_MMAP)
  279. static int shm_request __PR((unsigned int size, unsigned char **memptr));
  280. int shm_id;
  281. /* request a shared memory block */
  282. static int shm_request(size, memptr)
  283. unsigned int size;
  284. unsigned char **memptr;
  285. {
  286. int     f;
  287. char    *addr;
  288. #ifdef  MAP_ANONYMOUS   /* HP/UX */
  289. f = -1;
  290. addr = mmap(0, (int) size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_ANONYMOUS, f, 0);
  291. #else
  292. if ((f = open("/dev/zero", O_RDWR)) < 0)
  293. comerr("Cannot open '/dev/zero'.n");
  294. addr = mmap(0, (int) size, PROT_READ|PROT_WRITE, MAP_SHARED, f, 0);
  295. #endif
  296. if (addr == (char *)-1)
  297. comerr("Cannot get mmap for %u Bytes on /dev/zero.n", size);
  298. close(f);
  299. if (memptr != NULL)
  300. *memptr = (unsigned char *)addr;
  301. return 0;
  302. }
  303. /* release semaphores and shared memory */
  304. void free_sem __PR(( void ));
  305. void free_sem()
  306. {
  307. #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
  308.   int   mycmd;
  309.   union my_semun unused_arg;
  310.   mycmd = IPC_RMID;
  311.   /* HP-UX warns here, but 'unused_arg' is not used for this operation */
  312.   /* This warning is difficult to avoid, since the structure of the union
  313.    * generally is not known (os dependent). So we cannot initialize it
  314.    * properly.
  315.    */
  316.   semctl(sem_id,0,mycmd,unused_arg);
  317. #endif
  318. }
  319. #endif
  320. #endif
  321. #ifdef USE_OS2SHM
  322. static int shm_request __PR((unsigned int size, unsigned char **memptr));
  323. /* request a shared memory block */
  324. static int shm_request(size, memptr)
  325. unsigned int size;
  326. unsigned char **memptr;
  327. {
  328. char    *addr;
  329. /*
  330.  * The OS/2 implementation of shm (using shm.dll) limits the size of one         * memory segment to 0x3fa000 (aprox. 4MBytes). Using OS/2 native API we         * no such restriction so I decided to use it allowing fifos of arbitrar         */
  331. if(DosAllocSharedMem(&addr,NULL,size,0X100L | 0x1L | 0x2L | 0x10L))
  332.        comerr("DosAllocSharedMem() failedn");
  333. if (memptr != NULL)
  334. *memptr = (unsigned char *)addr;
  335. return 0;
  336. }
  337. #endif
  338. void *request_shm_sem(amount_of_sh_mem, pointer)
  339. unsigned amount_of_sh_mem;
  340. unsigned char **pointer;
  341. {
  342. #if defined(HAVE_SEMGET) && defined(USE_SEMAPHORES)
  343.     /* install semaphores for double buffer usage */
  344.     sem_id = seminstall(IPC_PRIVATE,2);
  345.     if ( sem_id == -1 ) {
  346.       perror("seminstall");
  347.       exit(1);
  348.     }
  349. #endif
  350. #if defined(FIFO)
  351.     if (-1 == shm_request(amount_of_sh_mem, pointer)) {
  352. perror("shm_request");
  353. exit(1);
  354.     }
  355.     return *pointer;
  356. #else
  357.     return NULL;
  358. #endif
  359. }