Jack2 1.9.6
|
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 mach_port_t JackMachSemaphore::fBootPort = 0; 00030 00031 void JackMachSemaphore::BuildName(const char* client_name, const char* server_name, char* res) 00032 { 00033 char ext_client_name[JACK_CLIENT_NAME_SIZE + 1]; 00034 JackTools::RewriteName(client_name, ext_client_name); 00035 sprintf(res, "jack_mach_sem.%d_%s_%s", JackTools::GetUID(), server_name, ext_client_name); 00036 } 00037 00038 bool JackMachSemaphore::Signal() 00039 { 00040 if (!fSemaphore) { 00041 jack_error("JackMachSemaphore::Signal name = %s already desallocated!!", fName); 00042 return false; 00043 } 00044 00045 if (fFlush) 00046 return true; 00047 00048 kern_return_t res; 00049 if ((res = semaphore_signal(fSemaphore)) != KERN_SUCCESS) { 00050 jack_error("JackMachSemaphore::Signal name = %s err = %s", fName, mach_error_string(res)); 00051 } 00052 return (res == KERN_SUCCESS); 00053 } 00054 00055 bool JackMachSemaphore::SignalAll() 00056 { 00057 if (!fSemaphore) { 00058 jack_error("JackMachSemaphore::SignalAll name = %s already desallocated!!", fName); 00059 return false; 00060 } 00061 00062 if (fFlush) 00063 return true; 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 desallocated!!", 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 desallocated!!", 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); 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); 00153 kern_return_t res; 00154 00155 // Temporary... A REVOIR 00156 /* 00157 if (fSemaphore > 0) { 00158 jack_log("Already connected name = %s", name); 00159 return true; 00160 } 00161 */ 00162 00163 if (fBootPort == 0) { 00164 if ((res = task_get_bootstrap_port(mach_task_self(), &fBootPort)) != KERN_SUCCESS) { 00165 jack_error("Connect: can't find bootstrap port err = %s", mach_error_string(res)); 00166 return false; 00167 } 00168 } 00169 00170 if ((res = bootstrap_look_up(fBootPort, fName, &fSemaphore)) != KERN_SUCCESS) { 00171 jack_error("Connect: can't find mach semaphore name = %s err = %s", fName, mach_error_string(res)); 00172 return false; 00173 } 00174 00175 jack_log("JackMachSemaphore::Connect name = %s ", fName); 00176 return true; 00177 } 00178 00179 bool JackMachSemaphore::Connect(const char* name, const char* server_name) 00180 { 00181 return ConnectInput(name, server_name); 00182 } 00183 00184 bool JackMachSemaphore::ConnectOutput(const char* name, const char* server_name) 00185 { 00186 return ConnectInput(name, server_name); 00187 } 00188 00189 bool JackMachSemaphore::Disconnect() 00190 { 00191 if (fSemaphore > 0) { 00192 jack_log("JackMachSemaphore::Disconnect name = %s", fName); 00193 fSemaphore = 0; 00194 } 00195 // Nothing to do 00196 return true; 00197 } 00198 00199 // Server side : destroy the JackGlobals 00200 void JackMachSemaphore::Destroy() 00201 { 00202 kern_return_t res; 00203 00204 if (fSemaphore > 0) { 00205 jack_log("JackMachSemaphore::Destroy"); 00206 if ((res = semaphore_destroy(mach_task_self(), fSemaphore)) != KERN_SUCCESS) { 00207 jack_error("JackMachSemaphore::Destroy can't destroy semaphore err = %s", mach_error_string(res)); 00208 } 00209 fSemaphore = 0; 00210 } else { 00211 jack_error("JackMachSemaphore::Destroy semaphore < 0"); 00212 } 00213 } 00214 00215 } // end of namespace 00216