xfermem.c 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279
  1. /*
  2. * xfermem.c
  3. *
  4. * Oliver Fromme <oliver.fromme@heim3.tu-clausthal.de>
  5. * Sun Apr 6 02:26:26 MET DST 1997
  6. *
  7. * See xfermem.h for documentation/description.
  8. */
  9. #ifndef NOXFERMEM
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <string.h>
  13. #include <unistd.h>
  14. #include <errno.h>
  15. #include <sys/types.h>
  16. #include <sys/time.h>
  17. #include <sys/uio.h>
  18. #include <sys/mman.h>
  19. #include <sys/socket.h>
  20. #include <fcntl.h>
  21. #ifdef AIX
  22. #include <sys/select.h>
  23. #endif
  24. #include "mpg123.h"
  25. #ifndef USE_MMAP
  26. #include <sys/ipc.h>
  27. #include <sys/shm.h>
  28. #endif
  29. extern int errno;
  30. #if defined (USE_MMAP) && defined(MAP_ANONYMOUS) && !defined(MAP_ANON)
  31. #define MAP_ANON MAP_ANONYMOUS
  32. #endif
  33. void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf)
  34. {
  35. int regsize = bufsize + msize + skipbuf + sizeof(txfermem);
  36. extern int preload;
  37. #ifdef USE_MMAP
  38. # ifdef MAP_ANON
  39. if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
  40. MAP_ANON | MAP_SHARED, -1, 0)) == (txfermem *) -1) {
  41. perror ("mmap()");
  42. exit (1);
  43. }
  44. # else
  45. int devzero;
  46. if ((devzero = open("/dev/zero", O_RDWR, 0)) == -1) {
  47. perror ("open(/dev/zero)");
  48. exit (1);
  49. }
  50. if ((*xf = (txfermem *) mmap(0, regsize, PROT_READ | PROT_WRITE,
  51. MAP_SHARED, devzero, 0)) == (txfermem *) -1) {
  52. perror ("mmap()");
  53. exit (1);
  54. }
  55. close (devzero);
  56. # endif
  57. #else
  58. struct shmid_ds shmemds;
  59. int shmemid;
  60. if ((shmemid = shmget(IPC_PRIVATE, regsize, IPC_CREAT | 0600)) == -1) {
  61. perror ("shmget()");
  62. exit (1);
  63. }
  64. if ((*xf = (txfermem *) shmat(shmemid, 0, 0)) == (txfermem *) -1) {
  65. perror ("shmat()");
  66. shmctl (shmemid, IPC_RMID, &shmemds);
  67. exit (1);
  68. }
  69. if (shmctl(shmemid, IPC_RMID, &shmemds) == -1) {
  70. perror ("shmctl()");
  71. xfermem_done (*xf);
  72. exit (1);
  73. }
  74. #endif
  75. if (socketpair(AF_UNIX, SOCK_STREAM, 0, (*xf)->fd) < 0) {
  76. perror ("socketpair()");
  77. xfermem_done (*xf);
  78. exit (1);
  79. }
  80. (*xf)->freeindex = (*xf)->readindex = 0;
  81. (*xf)->wakeme[0] = (*xf)->wakeme[1] = FALSE;
  82. (*xf)->data = ((byte *) *xf) + sizeof(txfermem) + msize;
  83. (*xf)->metadata = ((byte *) *xf) + sizeof(txfermem);
  84. (*xf)->size = bufsize;
  85. (*xf)->metasize = msize + skipbuf;
  86. preload = bufsize>>3;
  87. }
  88. void xfermem_done (txfermem *xf)
  89. {
  90. if(!xf)
  91. return;
  92. #ifdef USE_MMAP
  93. munmap ((caddr_t) xf, xf->size + xf->metasize + sizeof(txfermem));
  94. #else
  95. if (shmdt((void *) xf) == -1) {
  96. perror ("shmdt()");
  97. exit (1);
  98. }
  99. #endif
  100. }
  101. void xfermem_init_writer (txfermem *xf)
  102. {
  103. if(xf)
  104. close (xf->fd[XF_READER]);
  105. }
  106. void xfermem_init_reader (txfermem *xf)
  107. {
  108. if(xf)
  109. close (xf->fd[XF_WRITER]);
  110. }
  111. int xfermem_get_freespace (txfermem *xf)
  112. {
  113. int freeindex, readindex;
  114. if(!xf)
  115. return 0;
  116. if ((freeindex = xf->freeindex) < 0
  117. || (readindex = xf->readindex) < 0)
  118. return (0);
  119. if (readindex > freeindex)
  120. return ((readindex - freeindex) - 1);
  121. else
  122. return ((xf->size - (freeindex - readindex)) - 1);
  123. }
  124. int xfermem_get_usedspace (txfermem *xf)
  125. {
  126. int freeindex, readindex;
  127. if(!xf)
  128. return 0;
  129. if ((freeindex = xf->freeindex) < 0
  130. || (readindex = xf->readindex) < 0)
  131. return (0);
  132. if (freeindex >= readindex)
  133. return (freeindex - readindex);
  134. else
  135. return (xf->size - (readindex - freeindex));
  136. }
  137. int xfermem_getcmd (int fd, int block)
  138. {
  139. fd_set selfds;
  140. byte cmd;
  141. for (;;) {
  142. struct timeval selto = {0, 0};
  143. FD_ZERO (&selfds);
  144. FD_SET (fd, &selfds);
  145. #ifdef HPUX
  146. switch (select(FD_SETSIZE, (int *) &selfds, NULL, NULL, block ? NULL : &selto)) {
  147. #else
  148. switch (select(FD_SETSIZE, &selfds, NULL, NULL, block ? NULL : &selto)) {
  149. #endif
  150. case 0:
  151. if (!block)
  152. return (0);
  153. continue;
  154. case -1:
  155. if (errno == EINTR)
  156. continue;
  157. return (-2);
  158. case 1:
  159. if (FD_ISSET(fd, &selfds))
  160. switch (read(fd, &cmd, 1)) {
  161. case 0: /* EOF */
  162. return (-1);
  163. case -1:
  164. if (errno == EINTR)
  165. continue;
  166. return (-3);
  167. case 1:
  168. return (cmd);
  169. default: /* ?!? */
  170. return (-4);
  171. }
  172. else /* ?!? */
  173. return (-5);
  174. default: /* ?!? */
  175. return (-6);
  176. }
  177. }
  178. }
  179. int xfermem_putcmd (int fd, byte cmd)
  180. {
  181. for (;;) {
  182. switch (write(fd, &cmd, 1)) {
  183. case 1:
  184. return (1);
  185. case -1:
  186. if (errno != EINTR)
  187. return (-1);
  188. }
  189. }
  190. }
  191. int xfermem_block (int readwrite, txfermem *xf)
  192. {
  193. int myfd = xf->fd[readwrite];
  194. int result;
  195. xf->wakeme[readwrite] = TRUE;
  196. if (xf->wakeme[1 - readwrite])
  197. xfermem_putcmd (myfd, XF_CMD_WAKEUP);
  198. result = xfermem_getcmd(myfd, TRUE);
  199. xf->wakeme[readwrite] = FALSE;
  200. return ((result <= 0) ? -1 : result);
  201. }
  202. #elif defined(WIN32) || defined(PLAN9)
  203. #include <stdio.h>
  204. #include <stdlib.h>
  205. #include <string.h>
  206. #include <errno.h>
  207. #include <sys/types.h>
  208. #include <fcntl.h>
  209. #include "mpg123.h"
  210. #include "xfermem.h"
  211. extern int errno;
  212. void xfermem_init (txfermem **xf, int bufsize, int msize, int skipbuf)
  213. {
  214. return;
  215. }
  216. void xfermem_done (txfermem *xf)
  217. {
  218. return;
  219. }
  220. void xfermem_init_writer (txfermem *xf)
  221. {
  222. return;
  223. }
  224. void xfermem_init_reader (txfermem *xf)
  225. {
  226. return;
  227. }
  228. int xfermem_get_freespace (txfermem *xf)
  229. {
  230. return 0;
  231. }
  232. int xfermem_get_usedspace (txfermem *xf)
  233. {
  234. return 0;
  235. }
  236. int xfermem_getcmd (int fd, int block)
  237. {
  238. return 0;
  239. }
  240. int xfermem_putcmd (int fd, byte cmd)
  241. {
  242. return 0;
  243. }
  244. int xfermem_block (int readwrite, txfermem *xf)
  245. {
  246. return 0;
  247. }
  248. #endif
  249. /* eof */