submitting patch from enterprise version
[csql.git] / src / storage / Mutex.cxx
blob0bf31b051c3bd3854ac9bd77d930ed23d33b3355
1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 ***************************************************************************/
16 #include <os.h>
17 #include <Mutex.h>
18 #include <Debug.h>
19 #include <NanoTimer.h>
20 #include <Config.h>
21 #include <Process.h>
22 Mutex::Mutex()
24 noOfRead = -1;
25 #if defined(sparc) || defined(i686) || defined (x86_64)
26 lock =0;
27 #else
28 pthread_mutexattr_t attr;
29 pthread_mutexattr_init(&attr);
30 pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
31 pthread_mutex_init(&mutex_, &attr);
32 #endif
35 int Mutex::init()
37 noOfRead = -1;
38 #if defined(sparc) || defined(i686) || defined (x86_64)
39 lock = 0;
40 #else
41 pthread_mutexattr_t attr;
42 pthread_mutexattr_init(&attr);
43 int ret = pthread_mutexattr_setpshared(&attr, PTHREAD_PROCESS_SHARED);
44 printf("pthread_mutexattr_setpshared Returned %d\n", ret);
45 pthread_mutex_init(&mutex_, &attr);
46 pthread_mutexattr_destroy(&attr);
47 #endif
48 return 0;
50 int Mutex::init(char *mname)
52 init();
53 if (strlen(mname) > 19 ) return 0;
54 strcpy(name, mname);
55 return 0;
59 #if defined(sparc) || defined(i686) || defined (x86_64)
60 int TSL(Lock *lock)
63 if (lock == 0) {
64 __asm("mov $1, %eax");
65 __asm("mov 20(%ebp), %edx");
66 __asm("xchg %eax, (%edx)");
67 __asm("test %eax %eax");
68 __asm("jnz .L1000");
69 return 0;
70 } else
72 __asm(".L1000:");
73 return 1;
76 /*Was Working in linux
77 char oldval;
78 __asm__ __volatile__(
79 "xchgb %b0,%1"
80 :"=q" (oldval), "=m" (lock)
81 :"0" (0) : "memory");
83 return oldval > 0;
85 #if defined(LINUX)
86 int* lw;
87 int res;
88 lw = (int*)lock;
89 if (*lock == 1) return 1;
90 /* This assembly compiles only with -O2 option, and not with -g option. Version1
91 __asm__ __volatile__(
92 "movl $1, %%eax; xchgl (%%ecx), %%eax"
93 : "=eax" (res), "=m" (*lw)
94 : "ecx" (lw));
97 /* This assembly takes lot of time for test/performance/DMLTest. Version2
98 __asm__ __volatile__(
99 "movl %1, %0; xchgl %0, %2"
100 : "=r" (res), "=r" (lock)
101 : "r" (lock));
105 // This assembly is Version3. Working fine for now
106 __asm__ __volatile__(
107 "xchgl %0, %1 \n\t"
108 : "=r"(res), "=m"(*lock)
109 : "0"(1), "m"(*lock)
110 : "memory");
112 //fprintf(stderr,"after asm %d ret %d\n", *lock, res);
114 return(res);
116 #elif defined (SOLARIS)
117 Lock res;
118 res = atomic_cas_32(lock, 0, 1);
119 return (res);
120 #endif
122 #endif
124 int Mutex::tryLock(int tryTimes, int waitmsecs,bool share)
126 if (TSL(&lock) == 0)
128 return 0;
130 int tries = 1;
131 int ret = 0;
132 struct timeval timeout;
133 timeout.tv_sec = 0;
134 timeout.tv_usec = waitmsecs;
135 if (tryTimes == 0 && waitmsecs == 0)
137 timeout.tv_sec = Conf::config.getMutexSecs();
138 timeout.tv_usec = Conf::config.getMutexUSecs();
139 tryTimes = Conf::config.getMutexRetries();
141 int cnt=0;
142 while (tries < tryTimes)
144 #if defined(sparc) || defined(i686) || defined (x86_64)
145 if (Conf::config.getNoOfProcessors() >1) {
146 cnt=0;
147 while(true) {
148 if (TSL(&lock) == 0)
150 return 0;
152 cnt++;
153 if (cnt == tryTimes * 100) break;
155 }else {
156 if (TSL(&lock) == 0) return 0;
158 #else
159 ret = pthread_mutex_trylock(&mutex_);
160 if (EBUSY != ret) return 0;
162 #endif
163 os::select(0, 0, 0, 0, &timeout);
164 tries++;
166 if(share && noOfRead != -1) {
167 noOfRead++;
168 return 2;
170 printError(ErrLockTimeOut, "Unable to get the mutex , tried %d times", tries);
171 return 1;
175 int Mutex::getLock(int procSlot, bool procAccount,bool share)
177 int ret=0;
178 #if defined(sparc) || defined(i686) || defined (x86_64)
179 ret = tryLock(0,0,share);
180 //add it to the has_ of the ThreadInfo
181 if (ret ==0 && procAccount) ProcessManager::addMutex(this, procSlot);
182 if(share & noOfRead == -1 && ret == 0 ) noOfRead ++;
183 if(ret == 2) return 0;
184 return ret;
185 #else
186 ret = pthread_mutex_lock(&mutex_);
187 #endif
188 if (ret == 0) return 0;
189 else
190 return 1;
193 int Mutex::releaseLock(int procSlot, bool procAccount,bool share)
195 if (noOfRead > 0 && share){ noOfRead--; return 0;}
196 int ret=0;
197 #if defined(sparc) || defined(i686) || defined (x86_64)
198 /*int *lw = &lock;
199 if (*lw == 0) return 0;
200 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
201 "=m" (*lw) :
202 "ecx" (lw) :
203 "eax");
205 lock = 0;
206 #else
207 ret = pthread_mutex_unlock(&mutex_);
208 #endif
209 if (ret == 0 && procAccount)
211 ProcessManager::removeMutex(this, procSlot);
212 if( noOfRead == 0 && share) noOfRead--;
213 return ret;
215 else
216 return 1;
219 int Mutex::destroy()
221 #if defined(sparc) || defined(i686) || defined (x86_64)
222 #else
223 return pthread_mutex_destroy(&mutex_);
224 #endif
225 return 0;
228 int Mutex::recoverMutex()
230 int ret=0;
231 #if defined(sparc) || defined(i686) || defined (x86_64)
232 /*int *lw = &lock;
233 if (*lw == 0) return 0;
234 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
235 "=m" (*lw) :
236 "ecx" (lw) :
237 "eax");
239 lock = 0;
240 #else
241 ret = pthread_mutex_unlock(&mutex_);
242 #endif
243 return ret;
246 int Mutex::CASL(long *ptr, long oldVal, long newVal)
248 #ifdef SOLARIS
249 #ifdef x86_64 //or sparc64
250 unsigned long res = atomic_cas_64((unsigned long*)ptr,
251 (unsigned long) oldVal, (unsigned long) newVal);
252 if (res == oldVal) return 0; else return 1;
253 #else
254 return CAS((int*)ptr, (int)oldVal, (int)newVal);
255 #endif
256 #endif
257 #ifdef LINUX
258 #ifdef x86_64
259 long result;
260 __asm__ __volatile__ ("lock; cmpxchgq %q2, %1"
261 : "=a" (result), "=m" (*ptr)
262 : "r" (newVal), "m" (*ptr), "0" (oldVal));
263 if (result == oldVal) return 0;
265 struct timeval timeout;
266 timeout.tv_sec=0;
267 timeout.tv_usec=1000;
268 os::select(0,0,0,0, &timeout);
269 __asm__ __volatile__ ("lock; cmpxchgq %q2, %1"
270 : "=a" (result), "=m" (*ptr)
271 : "r" (newVal), "m" (*ptr), "0" (oldVal));
273 //if (result) return 0; else {printf("DEBUG::CAS Fails %d-\n", result); return 1; }
274 if (result == oldVal) return 0; else return 1;
275 #else
276 return CAS((int*)ptr, (int)oldVal, (int)newVal);
277 #endif
278 #endif
281 int Mutex::CAS(int *ptr, int oldVal, int newVal)
283 #ifdef LINUX
284 unsigned char ret;
285 __asm__ __volatile__ (
286 " lock\n"
287 " cmpxchgl %2,%1\n"
288 " sete %0\n"
289 : "=q" (ret), "=m" (*ptr)
290 : "r" (newVal), "m" (*ptr), "a" (oldVal)
291 : "memory");
293 //above assembly returns 0 in case of failure
294 if (ret) return 0;
296 struct timeval timeout;
297 timeout.tv_sec=0;
298 timeout.tv_usec=1000;
299 os::select(0,0,0,0, &timeout);
300 __asm__ __volatile__ (
301 " lock\n"
302 " cmpxchgl %2,%1\n"
303 " sete %0\n"
304 : "=q" (ret), "=m" (*ptr)
305 : "r" (newVal), "m" (*ptr), "a" (oldVal)
306 : "memory");
307 //if (ret) return 0; else {printf("DEBUG::CAS Fails %d-\n", ret); return 1; }
308 if (ret) return 0; else return 1;
309 #else //for solaris
310 unsigned int ret;
311 ret = atomic_cas_32((unsigned int*)ptr, (unsigned int) oldVal,
312 (unsigned int) newVal);
313 if (ret == oldVal) return 0; else return 1;
314 #endif