Jack2 1.9.10
|
00001 /* 00002 Copyright (C) 2004-2008 Grame 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU Lesser General Public License as published by 00006 the Free Software Foundation; either version 2.1 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU Lesser General Public License for more details. 00013 00014 You should have received a copy of the GNU Lesser General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 00018 */ 00019 00020 #include "JackMachSemaphore.h" 00021 #include "JackConstants.h" 00022 #include "JackTools.h" 00023 #include "JackError.h" 00024 #include <stdio.h> 00025 00026 namespace Jack 00027 { 00028 00029 void JackMachSemaphore::BuildName(const char* client_name, const char* server_name, char* res, int size) 00030 { 00031 char ext_client_name[SYNC_MAX_NAME_SIZE + 1]; 00032 JackTools::RewriteName(client_name, ext_client_name); 00033 snprintf(res, size, "jack_mach_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 00034 } 00035 00036 bool JackMachSemaphore::Signal() 00037 { 00038 if (!fSemaphore) { 00039 jack_error("JackMachSemaphore::Signal name = %s already deallocated!!", fName); 00040 return false; 00041 } 00042 00043 if (fFlush) { 00044 return true; 00045 } 00046 00047 kern_return_t res; 00048 if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) { 00049 jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res)); 00050 } 00051 return (res == KERN_SUCCESS); 00052 } 00053 00054 bool JackMachSemaphore::SignalAll() 00055 { 00056 if (!fSemaphore) { 00057 jack_error("JackMachSemaphore::SignalAll name = %s already deallocated!!", fName); 00058 return false; 00059 } 00060 00061 if (fFlush) { 00062 return true; 00063 } 00064 00065 kern_return_t res; 00066 // When signaled several times, do not accumulate signals... 00067 if ((res = semaphore_signal_all(fSemaphore)) != KERN_SUCCESS) { 00068 jack_error("JackMachSemaphore::SignalAll name = %s err = %s", fName, mach_error_string(res)); 00069 } 00070 return (res == KERN_SUCCESS); 00071 } 00072 00073 bool JackMachSemaphore::Wait() 00074 { 00075 if (!fSemaphore) { 00076 jack_error("JackMachSemaphore::Wait name = %s already deallocated!!", fName); 00077 return false; 00078 } 00079 00080 kern_return_t res; 00081 if ((res = semaphore_wait(fSemaphore)) != KERN_SUCCESS) { 00082 jack_error("JackMachSemaphore::Wait name = %s err = %s", fName, mach_error_string(res)); 00083 } 00084 return (res == KERN_SUCCESS); 00085 } 00086 00087 bool JackMachSemaphore::TimedWait(long usec) 00088 { 00089 if (!fSemaphore) { 00090 jack_error("JackMachSemaphore::TimedWait name = %s already deallocated!!", fName); 00091 return false; 00092 } 00093 00094 kern_return_t res; 00095 mach_timespec time; 00096 time.tv_sec = usec / 1000000; 00097 time.tv_nsec = (usec % 1000000) * 1000; 00098 00099 if ((res = semaphore_timedwait(fSemaphore, time)) != KERN_SUCCESS) { 00100 jack_error("JackMachSemaphore::TimedWait name = %s usec = %ld err = %s", fName, usec, mach_error_string(res)); 00101 } 00102 return (res == KERN_SUCCESS); 00103 } 00104 00105 // Server side : publish the semaphore in the global namespace 00106 bool JackMachSemaphore::Allocate(const char* name, const char* server_name, int value) 00107 { 00108 BuildName(name, server_name, fName, sizeof(fName)); 00109 mach_port_t task = mach_task_self(); 00110 kern_return_t res; 00111 00112 if (fBootPort == 0) { 00113 if ((res = task_get_bootstrap_port(task, &fBootPort)) != KERN_SUCCESS) { 00114 jack_error("Allocate: Can't find bootstrap mach port err = %s", mach_error_string(res)); 00115 return false; 00116 } 00117 } 00118 00119 if ((res = semaphore_create(task, &fSemaphore, SYNC_POLICY_FIFO, value)) != KERN_SUCCESS) { 00120 jack_error("Allocate: can create semaphore err = %s", mach_error_string(res)); 00121 return false; 00122 } 00123 00124 if ((res = bootstrap_register(fBootPort, fName, fSemaphore)) != KERN_SUCCESS) { 00125 jack_error("Allocate: can't check in mach semaphore name = %s err = %s", fName, mach_error_string(res)); 00126 00127 switch (res) { 00128 case BOOTSTRAP_SUCCESS : 00129 /* service not currently registered, "a good thing" (tm) */ 00130 break; 00131 case BOOTSTRAP_NOT_PRIVILEGED : 00132 jack_log("bootstrap_register(): bootstrap not privileged"); 00133 break; 00134 case BOOTSTRAP_SERVICE_ACTIVE : 00135 jack_log("bootstrap_register(): bootstrap service active"); 00136 break; 00137 default : 00138 jack_log("bootstrap_register() err = %s", mach_error_string(res)); 00139 break; 00140 } 00141 00142 return false; 00143 } 00144 00145 jack_log("JackMachSemaphore::Allocate name = %s", fName); 00146 return true; 00147 } 00148 00149 // Client side : get the published semaphore from server 00150 bool JackMachSemaphore::ConnectInput(const char* name, const char* server_name) 00151 { 00152 BuildName(name, server_name, fName, sizeof(fName)); 00153 kern_return_t res; 00154 00155 if (fBootPort == 0) { 00156 if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) { 00157 jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res)); 00158 return false; 00159 } 00160 } 00161 00162 if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) { 00163 jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res)); 00164 return false; 00165 } 00166 00167 jack_log("JackMachSemaphore::Connect name = %s ", fName); 00168 return true; 00169 } 00170 00171 bool JackMachSemaphore::Connect(const char* name, const char* server_name) 00172 { 00173 return ConnectInput(name, server_name); 00174 } 00175 00176 bool JackMachSemaphore::ConnectOutput(const char* name, const char* server_name) 00177 { 00178 return ConnectInput(name, server_name); 00179 } 00180 00181 bool JackMachSemaphore::Disconnect() 00182 { 00183 if (fSemaphore > 0) { 00184 jack_log("JackMachSemaphore::Disconnect name = %s", fName); 00185 fSemaphore = 0; 00186 } 00187 // Nothing to do 00188 return true; 00189 } 00190 00191 // Server side : destroy the JackGlobals 00192 void JackMachSemaphore::Destroy() 00193 { 00194 kern_return_t res; 00195 00196 if (fSemaphore > 0) { 00197 jack_log("JackMachSemaphore::Destroy name = %s", fName); 00198 if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) { 00199 jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res)); 00200 } 00201 fSemaphore = 0; 00202 } else { 00203 jack_error("JackMachSemaphore::Destroy semaphore < 0"); 00204 } 00205 } 00206 00207 } // end of namespace 00208