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);
118 #elif defined (WINNT)
119 printf("WINDOWS TSL not yet implemented\n");
124 int Mutex::tryShareLock(int tryTimes
, int waitmsecs
,bool share
, bool upgrade
)
127 int oldValue
= (int)lock
;
128 if (oldValue
>= 0 && share
){
129 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
130 }else if ((oldValue
== 1 && upgrade
) || ( !share
&& oldValue
== 0) ){
131 ret
= CAS((int*)&lock
, oldValue
, -1);
133 if (0 == ret
) return 0;
135 struct timeval timeout
;
137 timeout
.tv_usec
= waitmsecs
;
138 if (tryTimes
== 0 && waitmsecs
== 0)
140 timeout
.tv_sec
= Conf::config
.getMutexSecs();
141 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
142 tryTimes
= Conf::config
.getMutexRetries();
145 while (tries
< tryTimes
)
147 #if defined(sparc) || defined(i686) || defined (x86_64)
148 if (Conf::config
.getNoOfProcessors() >1) {
151 oldValue
= (int)lock
;
152 if (oldValue
>= 0 && share
) {
153 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
154 }else if ((oldValue
== 1 && upgrade
) || (!share
&& oldValue
== 0) ) {
155 ret
= CAS((int*)&lock
, oldValue
, -1);
158 if(0 == ret
) return 0;
160 if (cnt
== tryTimes
* 100) break;
163 oldValue
= (int)lock
;
164 if (oldValue
>= 0 && share
) {
165 ret
= CAS((int*)&lock
, oldValue
, oldValue
+1);
166 }else if ((oldValue
== 1 && upgrade
) || (!share
&& oldValue
== 0) ){
167 ret
= CAS((int*)&lock
, oldValue
, -1);
172 ret
= pthread_mutex_trylock(&mutex_
);
173 if (EBUSY
!= ret
) return 0;
176 os::select(0, 0, 0, 0, &timeout
);
179 //printError(ErrLockTimeOut, "Unable to get the mutex %s, tried %d times", name,tries);
183 int Mutex::tryLock(int tryTimes
, int waitmsecs
)
191 struct timeval timeout
;
193 timeout
.tv_usec
= waitmsecs
;
194 if (tryTimes
== 0 && waitmsecs
== 0)
196 timeout
.tv_sec
= Conf::config
.getMutexSecs();
197 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
198 tryTimes
= Conf::config
.getMutexRetries();
201 while (tries
< tryTimes
)
203 #if defined(sparc) || defined(i686) || defined (x86_64)
204 if (Conf::config
.getNoOfProcessors() >1) {
212 if (cnt
== tryTimes
* 100) break;
215 if (TSL(&lock
) == 0) return 0;
218 ret
= pthread_mutex_trylock(&mutex_
);
219 if (EBUSY
!= ret
) return 0;
222 os::select(0, 0, 0, 0, &timeout
);
225 //printError(ErrLockTimeOut, "Unable to get the mutex %s, val:%d tried %d times", name, lock, tries);
229 int Mutex::getLock(int procSlot
, bool procAccount
)
232 #if defined(sparc) || defined(i686) || defined (x86_64)
234 //add it to the has_ of the ThreadInfo
235 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
239 ret
= pthread_mutex_lock(&mutex_
);
241 if (ret
== 0) return 0;
246 int Mutex::releaseLock(int procSlot
, bool procAccount
)
249 #if defined(sparc) || defined(i686) || defined (x86_64)
251 if (*lw == 0) return 0;
252 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
258 //TEMP::PRABA:TODO::CHANGE IT TO CAS
260 ret
= pthread_mutex_unlock(&mutex_
);
262 if (ret
== 0 && procAccount
)
264 ProcessManager::removeMutex(this, procSlot
);
271 int Mutex::getShareLock(int procSlot
, bool procAccount
)
274 #if defined(sparc) || defined(i686) || defined (x86_64)
275 ret
= tryShareLock(0,0,true,false);
276 //add it to the has_ of the ThreadInfo
277 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
280 ret
= pthread_mutex_lock(&mutex_
);
282 if (ret
== 0) return 0;
287 int Mutex::getExclusiveLock(int procSlot
, bool procAccount
, bool upgrade
)
290 #if defined(sparc) || defined(i686) || defined (x86_64)
291 ret
= tryShareLock(0,0,false,upgrade
);
292 //add it to the has_ of the ThreadInfo
293 if (ret
==0 && procAccount
) ProcessManager::addMutex(this, procSlot
);
296 ret
= pthread_mutex_lock(&mutex_
);
298 if (ret
== 0) return 0;
303 int Mutex::releaseShareLock(int procSlot
, bool procAccount
)
306 #if defined(sparc) || defined(i686) || defined (x86_64)
307 int oldValue
= (int)lock
;
310 ret
= CAS((int*)&lock
, oldValue
, oldValue
-1 );
312 if( oldValue
== 1 || oldValue
== -1 )
314 ret
= CAS((int*)&lock
, oldValue
, 0 );
319 struct timeval timeout
;
320 timeout
.tv_sec
= Conf::config
.getMutexSecs();
321 timeout
.tv_usec
= Conf::config
.getMutexUSecs();
322 int tryTimes
= Conf::config
.getMutexRetries();
323 while (tries
< tryTimes
)
325 oldValue
= (int)lock
;
327 ret
= CAS((int*)&lock
, oldValue
, (*(int*)&lock
)-1 );
330 if( oldValue
== 1 || oldValue
== -1 )
332 ret
= CAS((int*)&lock
, oldValue
, 0 );
339 ret
= pthread_mutex_unlock(&mutex_
);
341 if (ret
== 0 && procAccount
)
343 ProcessManager::removeMutex(this, procSlot
);
352 #if defined(sparc) || defined(i686) || defined (x86_64)
354 return pthread_mutex_destroy(&mutex_
);
359 int Mutex::recoverMutex()
362 #if defined(sparc) || defined(i686) || defined (x86_64)
364 if (*lw == 0) return 0;
365 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
372 ret
= pthread_mutex_unlock(&mutex_
);
377 int Mutex::CASGen(void *ptr
, InUse oldVal
, InUse newVal
)
379 #if defined(__sparcv9)
380 CASL((InUse
*) ptr
, oldVal
, newVal
);
383 CAS((InUse
*) ptr
, oldVal
, newVal
);
388 int Mutex::CASL(long *ptr
, long oldVal
, long newVal
)
391 #if defined(__sparcv9) || defined(x86_64) || defined (__x86_64)
392 unsigned long res
= atomic_cas_64((unsigned long*)ptr
,
393 (unsigned long) oldVal
, (unsigned long) newVal
);
394 if (res
== oldVal
) return 0; else return 1;
396 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
399 #if defined(LINUX) || defined (FreeBSD)
402 __asm__
__volatile__ ("lock; cmpxchgq %q2, %1"
403 : "=a" (result
), "=m" (*ptr
)
404 : "r" (newVal
), "m" (*ptr
), "0" (oldVal
));
405 if (result
== oldVal
) return 0;
407 struct timeval timeout
;
409 timeout
.tv_usec
=1000;
410 os::select(0,0,0,0, &timeout
);
411 __asm__
__volatile__ ("lock; cmpxchgq %q2, %1"
412 : "=a" (result
), "=m" (*ptr
)
413 : "r" (newVal
), "m" (*ptr
), "0" (oldVal
));
415 //if (result) return 0; else {printf("DEBUG::CAS Fails %d-\n", result); return 1; }
416 if (result
== oldVal
) return 0; else return 1;
418 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
422 //TODO:: 64 bit support not done.simply routed to CAS
423 //printf("WINDOWS CASL routed to CAS\n");
424 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
427 int Mutex::CAS(int *ptr
, int oldVal
, int newVal
)
429 #if defined(LINUX) || defined (FreeBSD)
431 __asm__
__volatile__ (
435 : "=q" (ret
), "=m" (*ptr
)
436 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
439 //above assembly returns 0 in case of failure
442 struct timeval timeout
;
444 timeout
.tv_usec
=1000;
445 os::select(0,0,0,0, &timeout
);
446 __asm__
__volatile__ (
450 : "=q" (ret
), "=m" (*ptr
)
451 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
453 //if (ret) return 0; else {printf("DEBUG::CAS Fails %d-\n", ret); return 1; }
454 if (ret
) return 0; else return 1;
455 #elif defined SOLARIS //for solaris
457 ret
= atomic_cas_32((unsigned int*)ptr
, (unsigned int) oldVal
,
458 (unsigned int) newVal
);
459 if (ret
== oldVal
) return 0; else return 1;
461 printf("WINDOWS Mutex::CAS not implemented\n");