jack2 codebase
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

263 lines
7.9KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. Copyright (C) 2013 Samsung Electronics
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU Lesser General Public License as published by
  6. the Free Software Foundation; either version 2.1 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU Lesser General Public License for more details.
  12. You should have received a copy of the GNU Lesser General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  15. */
  16. #include "JackAndroidSemaphore.h"
  17. #include "JackTools.h"
  18. #include "JackConstants.h"
  19. #include "JackError.h"
  20. #include <fcntl.h>
  21. #include <stdio.h>
  22. #include <sys/time.h>
  23. #include "IAndroidShm.h"
  24. #include "shm.h"
  25. #include "android/Shm.h" //android extension of shm.h
  26. namespace Jack
  27. {
  28. pthread_mutex_t JackAndroidSemaphore::mutex = PTHREAD_MUTEX_INITIALIZER;
  29. void JackAndroidSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size)
  30. {
  31. char ext_client_name[SYNC_MAX_NAME_SIZE + 1];
  32. JackTools::RewriteName(client_name, ext_client_name);
  33. if (getenv("JACK_PROMISCUOUS_SERVER")) {
  34. snprintf(res, size, "jack_sem.%s_%s", server_name, ext_client_name);
  35. } else {
  36. snprintf(res, size, "jack_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name);
  37. }
  38. }
  39. bool JackAndroidSemaphore::Signal()
  40. {
  41. int res;
  42. if (!fSemaphore) {
  43. jack_error("JackAndroidSemaphore::Signal name = %s already deallocated!!", fName);
  44. return false;
  45. }
  46. if (fFlush)
  47. return true;
  48. if ((res = sem_post(fSemaphore)) != 0) {
  49. jack_error("JackAndroidSemaphore::Signal name = %s err = %s", fName, strerror(errno));
  50. }
  51. return (res == 0);
  52. }
  53. bool JackAndroidSemaphore::SignalAll()
  54. {
  55. int res;
  56. if (!fSemaphore) {
  57. jack_error("JackAndroidSemaphore::SignalAll name = %s already deallocated!!", fName);
  58. return false;
  59. }
  60. if (fFlush)
  61. return true;
  62. if ((res = sem_post(fSemaphore)) != 0) {
  63. jack_error("JackAndroidSemaphore::SignalAll name = %s err = %s", fName, strerror(errno));
  64. }
  65. return (res == 0);
  66. }
  67. /*
  68. bool JackAndroidSemaphore::Wait()
  69. {
  70. int res;
  71. if (!fSemaphore) {
  72. jack_error("JackAndroidSemaphore::Wait name = %s already deallocated!!", fName);
  73. return false;
  74. }
  75. if ((res = sem_wait(fSemaphore)) != 0) {
  76. jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
  77. }
  78. return (res == 0);
  79. }
  80. */
  81. bool JackAndroidSemaphore::Wait()
  82. {
  83. int res;
  84. while ((res = sem_wait(fSemaphore) < 0)) {
  85. jack_error("JackAndroidSemaphore::Wait name = %s err = %s", fName, strerror(errno));
  86. if (errno != EINTR) {
  87. break;
  88. }
  89. }
  90. return (res == 0);
  91. }
  92. bool JackAndroidSemaphore::TimedWait(long usec)
  93. {
  94. int res;
  95. struct timeval now;
  96. timespec time;
  97. if (!fSemaphore) {
  98. jack_error("JackAndroidSemaphore::TimedWait name = %s already deallocated!!", fName);
  99. return false;
  100. }
  101. gettimeofday(&now, 0);
  102. time.tv_sec = now.tv_sec + usec / 1000000;
  103. long tv_usec = (now.tv_usec + (usec % 1000000));
  104. time.tv_sec += tv_usec / 1000000;
  105. time.tv_nsec = (tv_usec % 1000000) * 1000;
  106. while ((res = sem_timedwait(fSemaphore, &time)) < 0) {
  107. jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
  108. jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
  109. jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
  110. if (errno == ETIMEDOUT) {
  111. timespec ts;
  112. clock_gettime(CLOCK_REALTIME, &ts);
  113. ts.tv_sec = time.tv_sec - ts.tv_sec;
  114. ts.tv_nsec = time.tv_nsec - ts.tv_nsec;
  115. if (ts.tv_nsec < 0) {
  116. ts.tv_nsec += 1000000000;
  117. ts.tv_sec -= 1;
  118. }
  119. if (ts.tv_sec < 0 || ts.tv_nsec < 0) {
  120. jack_error("JackAndroidSemaphore::TimedWait time may changed or client killed already! wait again!");
  121. gettimeofday(&now, 0);
  122. time.tv_sec = now.tv_sec + usec / 1000000;
  123. long tv_usec = (now.tv_usec + (usec % 1000000));
  124. time.tv_sec += tv_usec / 1000000;
  125. time.tv_nsec = (tv_usec % 1000000) * 1000;
  126. if ((res = sem_timedwait(fSemaphore, &time)) < 0) {
  127. jack_error("JackAndroidSemaphore::TimedWait err = %s", strerror(errno));
  128. jack_log("JackAndroidSemaphore::TimedWait now : %ld %ld ", now.tv_sec, now.tv_usec);
  129. jack_log("JackAndroidSemaphore::TimedWait next : %ld %ld ", time.tv_sec, time.tv_nsec/1000);
  130. }
  131. }
  132. }
  133. if (errno != EINTR) {
  134. break;
  135. }
  136. }
  137. return (res == 0);
  138. }
  139. // Server side : publish the semaphore in the global namespace
  140. bool JackAndroidSemaphore::Allocate(const char* name, const char* server_name, int value)
  141. {
  142. pthread_mutex_lock (&mutex);
  143. BuildName(name, server_name, fName, sizeof(fName));
  144. jack_log("JackAndroidSemaphore::Allocate name = %s val = %ld", fName, value);
  145. android::sp<android::IAndroidShm> service = android::Shm::getShmService();
  146. if(service == NULL){
  147. jack_error("shm service is null");
  148. return false;
  149. }
  150. fSemaphoreMemory = service->InitSemaphore(fName);
  151. if(fSemaphoreMemory != NULL){
  152. fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
  153. }
  154. if(fSemaphore == NULL) {
  155. jack_error("Allocate: can't check in named semaphore name = %s err = %s", fName, strerror(errno));
  156. pthread_mutex_unlock (&mutex);
  157. return false;
  158. } else {
  159. sem_init(fSemaphore, 1, 0);
  160. jack_log("sem_init()");
  161. pthread_mutex_unlock (&mutex);
  162. return true;
  163. }
  164. }
  165. // Client side : get the published semaphore from server
  166. bool JackAndroidSemaphore::ConnectInput(const char* name, const char* server_name)
  167. {
  168. pthread_mutex_lock (&mutex);
  169. BuildName(name, server_name, fName, sizeof(fName));
  170. jack_log("JackAndroidSemaphore::Connect name = %s", fName);
  171. // Temporary...
  172. if (fSemaphore) {
  173. jack_log("Already connected name = %s", name);
  174. pthread_mutex_unlock (&mutex);
  175. return true;
  176. }
  177. android::sp<android::IAndroidShm> service = android::Shm::getShmService();
  178. if(service == NULL){
  179. jack_error("shm service is null");
  180. return false;
  181. }
  182. fSemaphoreMemory = service->InitSemaphore(fName);
  183. if(fSemaphoreMemory != NULL){
  184. fSemaphore = (sem_t*)(fSemaphoreMemory->getBase());
  185. }
  186. if(fSemaphore == NULL) {
  187. jack_error("Connect: can't connect named semaphore name = %s err = %s", fName, strerror(errno));
  188. pthread_mutex_unlock (&mutex);
  189. return false;
  190. } else {
  191. int val = 0;
  192. sem_getvalue(fSemaphore, &val);
  193. jack_log("JackAndroidSemaphore::Connect sem_getvalue %ld", val);
  194. pthread_mutex_unlock (&mutex);
  195. return true;
  196. }
  197. }
  198. bool JackAndroidSemaphore::Connect(const char* name, const char* server_name)
  199. {
  200. return ConnectInput(name, server_name);
  201. }
  202. bool JackAndroidSemaphore::ConnectOutput(const char* name, const char* server_name)
  203. {
  204. return ConnectInput(name, server_name);
  205. }
  206. bool JackAndroidSemaphore::Disconnect()
  207. {
  208. if (fSemaphore) {
  209. jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
  210. fSemaphore = NULL;
  211. }
  212. return true;
  213. }
  214. // Server side : destroy the semaphore
  215. void JackAndroidSemaphore::Destroy()
  216. {
  217. if (fSemaphore != NULL) {
  218. jack_log("JackAndroidSemaphore::Disconnect name = %s", fName);
  219. fSemaphore = NULL;
  220. } else {
  221. jack_error("JackAndroidSemaphore::Destroy semaphore == NULL");
  222. }
  223. }
  224. } // end of namespace