1 /***************************************************************************
2 * Copyright (C) 2007 by www.databasecache.com *
3 * Contact: praba_tuty@databasecache.com *
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. *
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. *
15 ***************************************************************************/
19 #include <NanoTimer.h>
24 #if defined(sparc) || defined(i686) || defined (x86_64)
27 pthread_mutexattr_t attr
;
28 pthread_mutexattr_init(&attr
);
29 pthread_mutexattr_setpshared(&attr
, PTHREAD_PROCESS_SHARED
);
30 pthread_mutex_init(&mutex_
, &attr
);
36 #if defined(sparc) || defined(i686) || defined (x86_64)
39 pthread_mutexattr_t attr
;
40 pthread_mutexattr_init(&attr
);
41 int ret
= pthread_mutexattr_setpshared(&attr
, PTHREAD_PROCESS_SHARED
);
42 printf("pthread_mutexattr_setpshared Returned %d\n", ret
);
43 pthread_mutex_init(&mutex_
, &attr
);
44 pthread_mutexattr_destroy(&attr
);
48 int Mutex::init(char *mname
)
51 if (strlen(mname
) > 19 ) return 0;
57 #if defined(sparc) || defined(i686) || defined (x86_64)
62 __asm("mov $1, %eax");
63 __asm("mov 20(%ebp), %edx");
64 __asm("xchg %eax, (%edx)");
65 __asm("test %eax %eax");
74 /*Was Working in linux
78 :"=q" (oldval), "=m" (lock)
83 #if defined(LINUX) || defined (FreeBSD)
87 if (*lock
== 1) return 1;
88 /* This assembly compiles only with -O2 option, and not with -g option. Version1
90 "movl $1, %%eax; xchgl (%%ecx), %%eax"
91 : "=eax" (res), "=m" (*lw)
95 /* This assembly takes lot of time for test/performance/DMLTest. Version2
97 "movl %1, %0; xchgl %0, %2"
98 : "=r" (res), "=r" (lock)
103 // This assembly is Version3. Working fine for now
104 __asm__
__volatile__(
106 : "=r"(res
), "=m"(*lock
)
110 //fprintf(stderr,"after asm %d ret %d\n", *lock, res);
114 #elif defined (SOLARIS)
116 res
= atomic_cas_32((unsigned*)lock
, 0, 1);
121 int Mutex::tryShareLock(int tryTimes
, int waitmsecs
,bool share
, bool isDelete
)
124 int oldValue
= (int)lock
;
125 if (oldValue
>= 0 && share
){
126 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
127 }else if ((oldValue
== 1 && isDelete
) || ( !share
&& oldValue
== 0) ){
128 ret
= CAS((int*)&lock
, oldValue
, -1);
130 if (0 == ret
) return 0;
132 struct timeval timeout
;
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();
142 while (tries
< tryTimes
)
144 #if defined(sparc) || defined(i686) || defined (x86_64)
145 if (Conf::config
.getNoOfProcessors() >1) {
148 oldValue
= (int)lock
;
149 if (oldValue
>= 0 && share
) {
150 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
151 }else if ((oldValue
== 1 && isDelete
) || (!share
&& oldValue
== 0) ) {
152 ret
= CAS((int*)&lock
, oldValue
, -1);
155 if(0 == ret
) return 0;
157 if (cnt
== tryTimes
* 100) break;
160 oldValue
= (int)lock
;
161 if (oldValue
>= 0 && share
) {
162 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
163 }else if ((oldValue
== 1 && isDelete
) || (!share
&& oldValue
== 0) ){
164 ret
= CAS((int*)&lock
, oldValue
, -1);
169 ret
= pthread_mutex_trylock(&mutex_
);
170 if (EBUSY
!= ret
) return 0;
173 os::select(0, 0, 0, 0, &timeout
);
176 printError(ErrLockTimeOut
, "Unable to get the mutex %s, tried %d times", name
,tries
);
180 int Mutex::tryLock(int tryTimes
, int waitmsecs
)
188 struct timeval timeout
;
190 timeout
.tv_usec
= waitmsecs
;
191 if (tryTimes
== 0 && waitmsecs
== 0)
193 timeout
.tv_sec
= Conf::config
.getMutexSecs();
194 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
195 tryTimes
= Conf::config
.getMutexRetries();
198 while (tries
< tryTimes
)
200 #if defined(sparc) || defined(i686) || defined (x86_64)
201 if (Conf::config
.getNoOfProcessors() >1) {
209 if (cnt
== tryTimes
* 100) break;
212 if (TSL(&lock
) == 0) return 0;
215 ret
= pthread_mutex_trylock(&mutex_
);
216 if (EBUSY
!= ret
) return 0;
219 os::select(0, 0, 0, 0, &timeout
);
222 printError(ErrLockTimeOut
, "Unable to get the mutex %s, val:%d tried %d times", name
, lock
, tries
);
226 int Mutex::getLock(int procSlot
, bool procAccount
)
229 #if defined(sparc) || defined(i686) || defined (x86_64)
231 //add it to the has_ of the ThreadInfo
232 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
236 ret
= pthread_mutex_lock(&mutex_
);
238 if (ret
== 0) return 0;
243 int Mutex::releaseLock(int procSlot
, bool procAccount
)
246 #if defined(sparc) || defined(i686) || defined (x86_64)
248 if (*lw == 0) return 0;
249 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
255 //TEMP::PRABA:TODO::CHANGE IT TO CAS
257 ret
= pthread_mutex_unlock(&mutex_
);
259 if (ret
== 0 && procAccount
)
261 ProcessManager::removeMutex(this, procSlot
);
268 int Mutex::getShareLock(int procSlot
, bool procAccount
)
271 #if defined(sparc) || defined(i686) || defined (x86_64)
272 ret
= tryShareLock(0,0,true,false);
273 //add it to the has_ of the ThreadInfo
274 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
277 ret
= pthread_mutex_lock(&mutex_
);
279 if (ret
== 0) return 0;
284 int Mutex::getExclusiveLock(int procSlot
, bool procAccount
, bool isDelete
)
287 #if defined(sparc) || defined(i686) || defined (x86_64)
288 ret
= tryShareLock(0,0,false,isDelete
);
289 //add it to the has_ of the ThreadInfo
290 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
293 ret
= pthread_mutex_lock(&mutex_
);
295 if (ret
== 0) return 0;
300 int Mutex::releaseShareLock(int procSlot
, bool procAccount
)
303 #if defined(sparc) || defined(i686) || defined (x86_64)
304 int oldValue
= (int)lock
;
307 ret
= CAS((int*)&lock
, oldValue
, oldValue
-1 );
309 if( oldValue
== 1 || oldValue
== -1 )
311 ret
= CAS((int*)&lock
, oldValue
, 0 );
316 struct timeval timeout
;
317 timeout
.tv_sec
= Conf::config
.getMutexSecs();
318 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
319 int tryTimes
= Conf::config
.getMutexRetries();
320 while (tries
< tryTimes
)
322 oldValue
= (int)lock
;
324 ret
= CAS((int*)&lock
, oldValue
, (*(int*)&lock
)-1 );
327 if( oldValue
== 1 || oldValue
== -1 )
329 ret
= CAS((int*)&lock
, oldValue
, 0 );
336 ret
= pthread_mutex_unlock(&mutex_
);
338 if (ret
== 0 && procAccount
)
340 ProcessManager::removeMutex(this, procSlot
);
349 #if defined(sparc) || defined(i686) || defined (x86_64)
351 return pthread_mutex_destroy(&mutex_
);
356 int Mutex::recoverMutex()
359 #if defined(sparc) || defined(i686) || defined (x86_64)
361 if (*lw == 0) return 0;
362 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
369 ret
= pthread_mutex_unlock(&mutex_
);
374 int Mutex::CASL(long *ptr
, long oldVal
, long newVal
)
377 #if defined(__sparcv9) || defined(x86_64) || defined (__x86_64)
378 unsigned long res
= atomic_cas_64((unsigned long*)ptr
,
379 (unsigned long) oldVal
, (unsigned long) newVal
);
380 if (res
== oldVal
) return 0; else return 1;
382 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
385 #if defined (LINUX) || defined(FreeBSD)
388 __asm__
__volatile__ ("lock; cmpxchgq %q2, %1"
389 : "=a" (result
), "=m" (*ptr
)
390 : "r" (newVal
), "m" (*ptr
), "0" (oldVal
));
391 if (result
== oldVal
) return 0;
393 struct timeval timeout
;
395 timeout
.tv_usec
=1000;
396 os::select(0,0,0,0, &timeout
);
397 __asm__
__volatile__ ("lock; cmpxchgq %q2, %1"
398 : "=a" (result
), "=m" (*ptr
)
399 : "r" (newVal
), "m" (*ptr
), "0" (oldVal
));
401 //if (result) return 0; else {printf("DEBUG::CAS Fails %d-\n", result); return 1; }
402 if (result
== oldVal
) return 0; else return 1;
404 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
409 int Mutex::CAS(int *ptr
, int oldVal
, int newVal
)
411 #if defined(LINUX) || defined(FreeBSD)
413 __asm__
__volatile__ (
417 : "=q" (ret
), "=m" (*ptr
)
418 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
421 //above assembly returns 0 in case of failure
424 struct timeval timeout
;
426 timeout
.tv_usec
=1000;
427 os::select(0,0,0,0, &timeout
);
428 __asm__
__volatile__ (
432 : "=q" (ret
), "=m" (*ptr
)
433 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
435 //if (ret) return 0; else {printf("DEBUG::CAS Fails %d-\n", ret); return 1; }
436 if (ret
) return 0; else return 1;
439 ret
= atomic_cas_32((unsigned int*)ptr
, (unsigned int) oldVal
,
440 (unsigned int) newVal
);
441 if (ret
== oldVal
) return 0; else return 1;