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>
25 #if defined(sparc) || defined(i686) || defined (x86_64)
28 pthread_mutexattr_t attr
;
29 pthread_mutexattr_init(&attr
);
30 pthread_mutexattr_setpshared(&attr
, PTHREAD_PROCESS_SHARED
);
31 pthread_mutex_init(&mutex_
, &attr
);
38 #if defined(sparc) || defined(i686) || defined (x86_64)
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
);
50 int Mutex::init(char *mname
)
53 if (strlen(mname
) > 19 ) return 0;
59 #if defined(sparc) || defined(i686) || defined (x86_64)
64 __asm("mov $1, %eax");
65 __asm("mov 20(%ebp), %edx");
66 __asm("xchg %eax, (%edx)");
67 __asm("test %eax %eax");
76 /*Was Working in linux
80 :"=q" (oldval), "=m" (lock)
89 if (*lock
== 1) return 1;
90 /* This assembly compiles only with -O2 option, and not with -g option. Version1
92 "movl $1, %%eax; xchgl (%%ecx), %%eax"
93 : "=eax" (res), "=m" (*lw)
97 /* This assembly takes lot of time for test/performance/DMLTest. Version2
99 "movl %1, %0; xchgl %0, %2"
100 : "=r" (res), "=r" (lock)
105 // This assembly is Version3. Working fine for now
106 __asm__
__volatile__(
108 : "=r"(res
), "=m"(*lock
)
112 //fprintf(stderr,"after asm %d ret %d\n", *lock, res);
116 #elif defined (SOLARIS)
118 res
= atomic_cas_32(lock
, 0, 1);
124 int Mutex::tryLock(int tryTimes
, int waitmsecs
,bool share
)
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) {
153 if (cnt
== tryTimes
* 100) break;
156 if (TSL(&lock
) == 0) return 0;
159 ret
= pthread_mutex_trylock(&mutex_
);
160 if (EBUSY
!= ret
) return 0;
163 os::select(0, 0, 0, 0, &timeout
);
166 if(share
&& noOfRead
!= -1) {
170 printError(ErrLockTimeOut
, "Unable to get the mutex , tried %d times", tries
);
175 int Mutex::getLock(int procSlot
, bool procAccount
,bool share
)
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;
186 ret
= pthread_mutex_lock(&mutex_
);
188 if (ret
== 0) return 0;
193 int Mutex::releaseLock(int procSlot
, bool procAccount
,bool share
)
195 if (noOfRead
> 0 && share
){ noOfRead
--; return 0;}
197 #if defined(sparc) || defined(i686) || defined (x86_64)
199 if (*lw == 0) return 0;
200 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
207 ret
= pthread_mutex_unlock(&mutex_
);
209 if (ret
== 0 && procAccount
)
211 ProcessManager::removeMutex(this, procSlot
);
212 if( noOfRead
== 0 && share
) noOfRead
--;
221 #if defined(sparc) || defined(i686) || defined (x86_64)
223 return pthread_mutex_destroy(&mutex_
);
228 int Mutex::recoverMutex()
231 #if defined(sparc) || defined(i686) || defined (x86_64)
233 if (*lw == 0) return 0;
234 __asm__ __volatile__("movl $0, %%eax; xchgl (%%ecx), %%eax" :
241 ret
= pthread_mutex_unlock(&mutex_
);
246 int Mutex::CASL(long *ptr
, long oldVal
, long newVal
)
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;
254 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
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
;
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;
276 return CAS((int*)ptr
, (int)oldVal
, (int)newVal
);
281 int Mutex::CAS(int *ptr
, int oldVal
, int newVal
)
285 __asm__
__volatile__ (
289 : "=q" (ret
), "=m" (*ptr
)
290 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
293 //above assembly returns 0 in case of failure
296 struct timeval timeout
;
298 timeout
.tv_usec
=1000;
299 os::select(0,0,0,0, &timeout
);
300 __asm__
__volatile__ (
304 : "=q" (ret
), "=m" (*ptr
)
305 : "r" (newVal
), "m" (*ptr
), "a" (oldVal
)
307 //if (ret) return 0; else {printf("DEBUG::CAS Fails %d-\n", ret); return 1; }
308 if (ret
) return 0; else return 1;
311 ret
= atomic_cas_32((unsigned int*)ptr
, (unsigned int) oldVal
,
312 (unsigned int) newVal
);
313 if (ret
== oldVal
) return 0; else return 1;