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.

215 lines
6.3KB

  1. /*
  2. Copyright (C) 2004-2008 Grame
  3. This program is free software; you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation; either version 2 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program; if not, write to the Free Software
  13. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  14. */
  15. #include "JackMachSemaphore.h"
  16. #include "JackError.h"
  17. #include <stdio.h>
  18. namespace Jack
  19. {
  20. mach_port_t JackMachSemaphore::fBootPort = 0;
  21. void JackMachSemaphore::BuildName(const char* name, const char* server_name, char* res)
  22. {
  23. sprintf(res, "jack_mach_sem.%s_%s", server_name, name);
  24. }
  25. bool JackMachSemaphore::Signal()
  26. {
  27. kern_return_t res;
  28. if (!fSemaphore) {
  29. jack_error("JackMachSemaphore::Signal name = %s already desallocated!!", fName);
  30. return false;
  31. }
  32. if (fFlush)
  33. return true;
  34. if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) {
  35. jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res));
  36. }
  37. return (res == KERN_SUCCESS);
  38. }
  39. bool JackMachSemaphore::SignalAll()
  40. {
  41. kern_return_t res;
  42. if (!fSemaphore) {
  43. jack_error("JackMachSemaphore::SignalAll name = %s already desallocated!!", fName);
  44. return false;
  45. }
  46. if (fFlush)
  47. return true;
  48. // When signaled several times, do not accumulate signals...
  49. if ((res = semaphore_signal_all(fSemaphore)) != KERN_SUCCESS) {
  50. jack_error("JackMachSemaphore::SignalAll name = %s err = %s", fName, mach_error_string(res));
  51. }
  52. return (res == KERN_SUCCESS);
  53. }
  54. bool JackMachSemaphore::Wait()
  55. {
  56. kern_return_t res;
  57. if (!fSemaphore) {
  58. jack_error("JackMachSemaphore::Wait name = %s already desallocated!!", fName);
  59. return false;
  60. }
  61. if ((res = semaphore_wait(fSemaphore)) != KERN_SUCCESS) {
  62. jack_error("JackMachSemaphore::Wait name = %s err = %s", fName, mach_error_string(res));
  63. }
  64. return (res == KERN_SUCCESS);
  65. }
  66. bool JackMachSemaphore::TimedWait(long usec)
  67. {
  68. kern_return_t res;
  69. mach_timespec time;
  70. time.tv_sec = usec / 1000000;
  71. time.tv_nsec = (usec % 1000000) * 1000;
  72. if (!fSemaphore) {
  73. jack_error("JackMachSemaphore::TimedWait name = %s already desallocated!!", fName);
  74. return false;
  75. }
  76. if ((res = semaphore_timedwait(fSemaphore, time)) != KERN_SUCCESS) {
  77. jack_error("JackMachSemaphore::TimedWait name = %s usec = %ld err = %s", fName, usec, mach_error_string(res));
  78. }
  79. return (res == KERN_SUCCESS);
  80. }
  81. // Server side : publish the semaphore in the global namespace
  82. bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value)
  83. {
  84. BuildName(name, server_name, fName);
  85. mach_port_t task = mach_task_self();
  86. kern_return_t res;
  87. if (fBootPort == 0) {
  88. if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) {
  89. jack_error("Allocate: Can't find bootstrap mach port err = %s", mach_error_string(res));
  90. return false;
  91. }
  92. }
  93. if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) {
  94. jack_error("Allocate: can create semaphore err = %s", mach_error_string(res));
  95. return false;
  96. }
  97. if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) {
  98. jack_error("Allocate: can't check in mach semaphore name = %s err = %s", fName, mach_error_string(res));
  99. switch (res) {
  100. case BOOTSTRAP_SUCCESS :
  101. /* service not currently registered, "a good thing" (tm) */
  102. break;
  103. case BOOTSTRAP_NOT_PRIVILEGED :
  104. jack_log("bootstrap_register(): bootstrap not privileged");
  105. break;
  106. case BOOTSTRAP_SERVICE_ACTIVE :
  107. jack_log("bootstrap_register(): bootstrap service active");
  108. break;
  109. default :
  110. jack_log("bootstrap_register() err = %s", mach_error_string(res));
  111. break;
  112. }
  113. return false;
  114. }
  115. jack_log("JackMachSemaphore::Allocate name = %s", fName);
  116. return true;
  117. }
  118. // Client side : get the published semaphore from server
  119. bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name)
  120. {
  121. BuildName(name, server_name, fName);
  122. kern_return_t res;
  123. // Temporary... A REVOIR
  124. /*
  125. if (fSemaphore > 0) {
  126. jack_log("Already connected name = %s", name);
  127. return true;
  128. }
  129. */
  130. if (fBootPort == 0) {
  131. if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) {
  132. jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res));
  133. return false;
  134. }
  135. }
  136. if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) {
  137. jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res));
  138. return false;
  139. }
  140. jack_log("JackMachSemaphore::Connect name = %s ", fName);
  141. return true;
  142. }
  143. bool JackMachSemaphore::Connect(const char* name, const char* server_name)
  144. {
  145. return ConnectInput(name, server_name);
  146. }
  147. bool JackMachSemaphore::ConnectOutput(const char* name, const char* server_name)
  148. {
  149. return ConnectInput(name, server_name);
  150. }
  151. bool JackMachSemaphore::Disconnect()
  152. {
  153. if (fSemaphore > 0) {
  154. jack_log("JackMachSemaphore::Disconnect name = %s", fName);
  155. fSemaphore = 0;
  156. }
  157. // Nothing to do
  158. return true;
  159. }
  160. // Server side : destroy the JackGlobals
  161. void JackMachSemaphore::Destroy()
  162. {
  163. kern_return_t res;
  164. if (fSemaphore > 0) {
  165. jack_log("JackMachSemaphore::Destroy");
  166. if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) {
  167. jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res));
  168. }
  169. fSemaphore = 0;
  170. } else {
  171. jack_error("JackMachSemaphore::Destroy semaphore < 0");
  172. }
  173. }
  174. } // end of namespace