Advertisement
Guest User

Untitled

a guest
Oct 25th, 2016
107
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.59 KB | None | 0 0
  1. /*
  2. * Copyright (C) 2007-2011 Gilles Chanteperdrix <gch@xenomai.org>
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining
  5. * a copy of this software and associated documentation files (the
  6. * "Software"), to deal in the Software without restriction, including
  7. * without limitation the rights to use, copy, modify, merge, publish,
  8. * distribute, sublicense, and/or sell copies of the Software, and to
  9. * permit persons to whom the Software is furnished to do so, subject to
  10. * the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included
  13. * in all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16. * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  18. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
  19. * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
  20. * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
  21. * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23.  
  24. #ifndef __XENO_SIM__
  25. #ifndef __KERNEL__
  26. #include <stdio.h>
  27. #define xnarch_printf printf
  28. #endif
  29.  
  30. #include <time.h>
  31. #include <errno.h>
  32. #include <unistd.h>
  33. #include <signal.h>
  34. #include <sys/mman.h>
  35. #include <pthread.h>
  36. #include <mqueue.h>
  37. #else /* __XENO_SIM */
  38. #include <posix/posix.h>
  39. #endif /* __XENO_SIM */
  40.  
  41. #define CONSUMER_TASK_PRI 1
  42. #define CONSUMER_STACK_SIZE 8192
  43.  
  44. #define PRODUCER_TASK_PRI 2
  45. #define PRODUCER_STACK_SIZE 8192
  46.  
  47. #define CONSUMER_WAIT 150
  48. #define PRODUCER_TRIG 40
  49.  
  50. #define MQ_NAME "/satchmq"
  51. #define SHM_NAME "/satchshm"
  52.  
  53. void normalize(struct timespec *ts)
  54. {
  55. if (ts->tv_nsec > 1000000000)
  56. {
  57. ts->tv_sec += ts->tv_nsec / 1000000000;
  58. ts->tv_nsec %= 1000000000;
  59. }
  60.  
  61. if (ts->tv_nsec < 0)
  62. {
  63. ts->tv_sec -= (-ts->tv_nsec) / 1000000000 + 1;
  64. ts->tv_nsec = 1000000000 - (-ts->tv_nsec % 1000000000);
  65. }
  66. }
  67.  
  68. void abort_perror(const char *pref)
  69. {
  70. printf("%s: %d\n", pref, errno);
  71. pthread_exit(NULL);
  72. }
  73.  
  74. #ifdef PRODUCER
  75.  
  76. static const char *private_satch_s_tunes[] = {
  77. "Surfing With The Alien",
  78. "Lords of Karma",
  79. "Banana Mango",
  80. "Psycho Monkey",
  81. "Luminous Flesh Giants",
  82. "Moroccan Sunset",
  83. "Satch Boogie",
  84. "Flying In A Blue Dream",
  85. "Ride",
  86. "Summer Song",
  87. "Speed Of Light",
  88. "Crystal Planet",
  89. "Raspberry Jam Delta-V",
  90. "Champagne?",
  91. "Clouds Race Across The Sky",
  92. "Engines Of Creation"
  93. };
  94.  
  95. static unsigned satch_s_tunes[sizeof(private_satch_s_tunes)/sizeof(char *)];
  96. static timer_t producer_tm = (timer_t) -1;
  97. static mqd_t producer_mq = (mqd_t) -1;
  98. static void *producer_shm = MAP_FAILED;
  99. static pthread_t producer_task;
  100.  
  101. void *producer (void *cookie)
  102.  
  103. {
  104. struct itimerspec its;
  105. sigset_t blocked;
  106. unsigned pos;
  107. int next_msg;
  108.  
  109. /* Copy the strings to shared memory. */
  110. pos = 0;
  111. for (next_msg = 0;
  112. next_msg < sizeof(private_satch_s_tunes)/sizeof(char *);
  113. next_msg++)
  114. {
  115. const char *msg = private_satch_s_tunes[next_msg];
  116. size_t len = strlen(msg) + 1;
  117. memcpy(producer_shm + pos, msg, len);
  118. satch_s_tunes[next_msg] = pos;
  119. pos += len;
  120. }
  121. next_msg = 0;
  122.  
  123. sigemptyset(&blocked);
  124. sigaddset(&blocked, SIGRTMIN+1);
  125. pthread_sigmask(SIG_BLOCK, &blocked, NULL);
  126.  
  127. its.it_value.tv_sec = 0;
  128. its.it_value.tv_nsec = 10000000 * PRODUCER_TRIG;
  129. normalize(&its.it_value);
  130. its.it_interval.tv_sec = 0;
  131. its.it_interval.tv_nsec = 0;
  132. normalize(&its.it_interval);
  133.  
  134. for (;;)
  135. {
  136. unsigned msg_off;
  137. siginfo_t si;
  138. int nchar;
  139.  
  140. if (timer_settime(producer_tm, 0, &its, NULL))
  141. abort_perror("timer_settime");
  142. while (sigwaitinfo(&blocked, &si) == -1 && errno == EINTR)
  143. ;
  144.  
  145. msg_off = satch_s_tunes[next_msg++];
  146. next_msg %= (sizeof(satch_s_tunes) / sizeof(satch_s_tunes[0]));
  147.  
  148. do
  149. {
  150. nchar = mq_send(producer_mq, (char *)&msg_off, sizeof(msg_off), 0);
  151. }
  152. while (nchar == -1 && errno == EINTR);
  153.  
  154. if (nchar == -1)
  155. abort_perror("mq_send");
  156. }
  157.  
  158. return NULL;
  159. }
  160.  
  161. #endif /* PRODUCER */
  162.  
  163. #ifdef CONSUMER
  164.  
  165. static timer_t consumer_tm = (timer_t) -1;
  166. static mqd_t consumer_mq = (mqd_t) -1;
  167. static void *consumer_shm = MAP_FAILED;
  168. static pthread_t consumer_task;
  169.  
  170. void *consumer (void *cookie)
  171.  
  172. {
  173. struct itimerspec its;
  174. sigset_t blocked;
  175.  
  176. sigemptyset(&blocked);
  177. sigaddset(&blocked, SIGALRM);
  178. pthread_sigmask(SIG_BLOCK, &blocked, NULL);
  179.  
  180. its.it_value.tv_sec = 0;
  181. its.it_value.tv_nsec = CONSUMER_WAIT * 10000000; /* 10 ms */
  182. normalize(&its.it_value);
  183. its.it_interval.tv_sec = 0;
  184. its.it_interval.tv_nsec = CONSUMER_WAIT * 10000000;
  185. normalize(&its.it_interval);
  186.  
  187. if(timer_settime(consumer_tm, 0, &its, NULL))
  188. abort_perror("timer_settime");
  189.  
  190. for (;;)
  191. {
  192. siginfo_t si;
  193. while (sigwaitinfo(&blocked, &si) == -1 && errno == EINTR)
  194. ;
  195.  
  196. for (;;)
  197. {
  198. unsigned prio;
  199. unsigned msg;
  200. int nchar;
  201.  
  202. do
  203. {
  204. nchar = mq_receive(consumer_mq,(char *)&msg, sizeof(msg), &prio);
  205. }
  206. while (nchar == -1 && errno == EINTR);
  207.  
  208. if (nchar == -1 && errno == EAGAIN)
  209. break;
  210.  
  211. if (nchar == -1)
  212. abort_perror("mq_receive");
  213.  
  214. printf("Now playing %s...\n",(char *) consumer_shm + msg);
  215. }
  216. }
  217.  
  218. return NULL;
  219. }
  220.  
  221. #endif /* CONSUMER */
  222.  
  223. void __xeno_user_exit (void)
  224.  
  225. {
  226. #ifdef PRODUCER
  227. if (producer_task)
  228. {
  229. pthread_cancel(producer_task);
  230. pthread_join(producer_task, NULL);
  231. }
  232. if (producer_tm != (timer_t) -1)
  233. timer_delete(producer_tm);
  234. if (producer_mq != (mqd_t) -1)
  235. mq_close(producer_mq);
  236. mq_unlink(MQ_NAME);
  237. if (producer_shm != MAP_FAILED)
  238. munmap(producer_shm, 65536);
  239. shm_unlink(SHM_NAME);
  240. #endif /* PRODUCER */
  241.  
  242. #ifdef CONSUMER
  243. if (consumer_task)
  244. {
  245. pthread_cancel(consumer_task);
  246. pthread_join(consumer_task, NULL);
  247. }
  248. if (consumer_tm != (timer_t) -1)
  249. timer_delete(consumer_tm);
  250. if (consumer_mq != (mqd_t) -1)
  251. mq_close(consumer_mq);
  252. if (consumer_shm != MAP_FAILED)
  253. munmap(consumer_shm, 65536);
  254. #endif /* CONSUMER */
  255. }
  256.  
  257. int __xeno_user_init (void)
  258.  
  259. {
  260. struct sched_param parm;
  261. pthread_attr_t attr;
  262. int rc = 0, fd = -1;
  263. struct mq_attr mattr;
  264. struct sigevent evt;
  265.  
  266. fd = shm_open(SHM_NAME, O_CREAT | O_RDWR, 0777);
  267. if (fd == -1)
  268. {
  269. printf("shm_open: %d\n", errno);
  270. return -errno;
  271. }
  272.  
  273. if (ftruncate(fd, 65536))
  274. {
  275. printf("ftruncate: %d\n", errno);
  276. goto out;
  277. }
  278.  
  279. pthread_attr_init(&attr);
  280. pthread_attr_setinheritsched(&attr, 1);
  281. pthread_attr_setschedpolicy(&attr, SCHED_FIFO);
  282.  
  283. #ifdef PRODUCER
  284. mattr.mq_maxmsg = 30;
  285. mattr.mq_msgsize = sizeof(unsigned);
  286. producer_mq = mq_open(MQ_NAME, O_CREAT| O_EXCL| O_WRONLY, 0, &mattr);
  287. if (producer_mq == (mqd_t) -1)
  288. {
  289. if (errno == EEXIST)
  290. {
  291. printf("Satch: producer module is already running, please "
  292. "only launch one producer instance.\n");
  293. goto out;
  294. }
  295.  
  296. printf("mq_open(producer_mq): %d\n", errno);
  297. goto out;
  298. }
  299.  
  300. producer_shm = mmap(NULL, 65536, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  301. if (producer_shm == MAP_FAILED)
  302. {
  303. printf("mmap(producer_shm): %d\n", errno);
  304. return -errno;
  305. }
  306.  
  307. evt.sigev_notify = SIGEV_SIGNAL;
  308. evt.sigev_signo = SIGRTMIN+1;
  309. evt.sigev_value.sival_ptr = &producer_tm;
  310. if (timer_create(CLOCK_REALTIME, &evt, &producer_tm))
  311. {
  312. printf("timer_create(producer_tm): %d\n", errno);
  313. goto out;
  314. }
  315.  
  316. pthread_attr_setstacksize(&attr, PRODUCER_STACK_SIZE);
  317. parm.sched_priority = PRODUCER_TASK_PRI;
  318. pthread_attr_setschedparam(&attr, &parm);
  319. rc = pthread_create(&producer_task, &attr, &producer, NULL);
  320.  
  321. if (rc)
  322. {
  323. printf("pthread_create(producer_task): %d\n", rc);
  324. goto out;
  325. }
  326. #endif /* PRODUCER */
  327.  
  328. #ifdef CONSUMER
  329. mattr.mq_maxmsg = 30;
  330. mattr.mq_msgsize = sizeof(unsigned);
  331. consumer_mq = mq_open(MQ_NAME, O_NONBLOCK| O_RDONLY, 0, &mattr);
  332. if (consumer_mq == (mqd_t) -1)
  333. {
  334. if (errno == ENOENT)
  335. {
  336. printf("Satch: producer module not running, please launch producer"
  337. " module before\nlaunching consumer application.\n");
  338. goto out;
  339. }
  340.  
  341. printf("mq_open(consumer_mq): %d\n", errno);
  342. goto out;
  343. }
  344.  
  345. consumer_shm = mmap(NULL, 65536, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
  346. if (consumer_shm == MAP_FAILED)
  347. {
  348. printf("mmap(consumer_shm): %d\n", errno);
  349. goto out;
  350. }
  351.  
  352. evt.sigev_notify = SIGEV_SIGNAL;
  353. evt.sigev_signo = SIGALRM;
  354. evt.sigev_value.sival_ptr = &consumer_tm;
  355. if(timer_create(CLOCK_REALTIME, &evt, &consumer_tm))
  356. {
  357. printf("timer_create(consumer_tm): %d\n", errno);
  358. goto out;
  359. }
  360.  
  361. pthread_attr_setstacksize(&attr, CONSUMER_STACK_SIZE);
  362. parm.sched_priority = CONSUMER_TASK_PRI;
  363. pthread_attr_setschedparam(&attr, &parm);
  364. rc = pthread_create(&consumer_task, &attr, &consumer, NULL);
  365. if (rc)
  366. {
  367. printf("pthread_create(consumer_task): %d\n", rc);
  368. goto out;
  369. }
  370. #endif /* CONSUMER */
  371.  
  372. if (close(fd))
  373. {
  374. printf("close: %d\n", errno);
  375. rc = -errno;
  376. goto err;
  377. }
  378.  
  379. return 0;
  380.  
  381. out:
  382. rc = -rc ?: -errno;
  383. if (close(fd))
  384.  
  385. printf("close: %d\n", errno);
  386. err:
  387. __xeno_user_exit();
  388. return rc;
  389. }
  390.  
  391. #ifdef __KERNEL__
  392. MODULE_AUTHOR("gilles.chanteperdrix@xenomai.org");
  393. MODULE_LICENSE("GPL");
  394. module_init(__xeno_user_init);
  395. module_exit(__xeno_user_exit);
  396.  
  397. #elif !defined(__XENO_SIM__)
  398. int main (int ac, char *av[])
  399.  
  400. {
  401. sigset_t mask;
  402. int rc, sig;
  403.  
  404. sigemptyset(&mask);
  405. sigaddset(&mask,SIGINT);
  406. sigaddset(&mask,SIGTERM);
  407. sigaddset(&mask,SIGHUP);
  408. sigaddset(&mask,SIGALRM);
  409.  
  410. pthread_sigmask(SIG_BLOCK, &mask, NULL);
  411.  
  412. mlockall(MCL_CURRENT|MCL_FUTURE);
  413.  
  414. rc = __xeno_user_init();
  415.  
  416. if (rc)
  417. {
  418. printf("__xeno_user_init: %d\n", -rc);
  419. return -rc;
  420. }
  421.  
  422. sigwait(&mask, &sig);
  423. __xeno_user_exit();
  424.  
  425. return 0;
  426. }
  427. #endif /* !__XENO_SIM__ && !__KERNEL__ */
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement