1 /**
2  * Mutex.cpp
3  * This file is part of the YATE Project http://YATE.null.ro
4  *
5  * Yet Another Telephony Engine - a fully featured software PBX and IVR
6  * Copyright (C) 2004-2014 Null Team
7  *
8  * This software is distributed under multiple licenses;
9  * see the COPYING file in the main directory for licensing
10  * information for this specific distribution.
11  *
12  * This use of this software may be subject to additional restrictions.
13  * See the LEGAL file in the main directory for details.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
18  */
19 
20 #include "yateclass.h"
21 
22 #ifdef _WINDOWS
23 
24 typedef HANDLE HMUTEX;
25 typedef HANDLE HSEMAPHORE;
26 
27 #else
28 
29 #include <pthread.h>
30 #include <semaphore.h>
31 #include <time.h>
32 
33 #ifdef MUTEX_HACK
34 extern "C" {
35 #if (defined(__FreeBSD__)||defined(__DragonFly__)) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__)
36 extern int pthread_mutexattr_settype(pthread_mutexattr_t *__attr, int __kind);
37 #define PTHREAD_MUTEX_RECURSIVE_NP PTHREAD_MUTEX_RECURSIVE
38 #else
39 extern int pthread_mutexattr_settype(pthread_mutexattr_t *__attr, int __kind) __THROW;
40 #endif
41 }
42 #endif
43 
44 typedef pthread_mutex_t HMUTEX;
45 typedef sem_t HSEMAPHORE;
46 
47 #endif /* ! _WINDOWS */
48 
49 #ifdef MUTEX_STATIC_UNSAFE
50 #undef MUTEX_STATIC_UNSAFE
51 #define MUTEX_STATIC_UNSAFE true
52 #else
53 #define MUTEX_STATIC_UNSAFE false
54 #endif
55 
56 namespace TelEngine {
57 
58 class MutexPrivate {
59 public:
60     MutexPrivate(bool recursive, const char* name);
61     ~MutexPrivate();
ref()62     inline void ref()
63 	{ ++m_refcount; }
deref()64     inline void deref()
65 	{ if (!--m_refcount) delete this; }
recursive() const66     inline bool recursive() const
67 	{ return m_recursive; }
name() const68     inline const char* name() const
69 	{ return m_name; }
owner() const70     inline const char* owner() const
71 	{ return m_owner; }
locked() const72     bool locked() const
73     	{ return (m_locked > 0); }
74     bool lock(long maxwait);
75     bool unlock();
76     static volatile int s_count;
77     static volatile int s_locks;
78 private:
79     HMUTEX m_mutex;
80     int m_refcount;
81     volatile unsigned int m_locked;
82     volatile unsigned int m_waiting;
83     bool m_recursive;
84     const char* m_name;
85     const char* m_owner;
86 };
87 
88 class SemaphorePrivate {
89 public:
90     SemaphorePrivate(unsigned int maxcount, const char* name, unsigned int initialCount);
91     ~SemaphorePrivate();
ref()92     inline void ref()
93 	{ ++m_refcount; }
deref()94     inline void deref()
95 	{ if (!--m_refcount) delete this; }
name() const96     inline const char* name() const
97 	{ return m_name; }
locked() const98     bool locked() const
99     	{ return (m_waiting > 0); }
100     bool lock(long maxwait);
101     bool unlock();
102     static volatile int s_count;
103     static volatile int s_locks;
104 private:
105     HSEMAPHORE m_semaphore;
106     int m_refcount;
107     volatile unsigned int m_waiting;
108     unsigned int m_maxcount;
109     const char* m_name;
110 };
111 
112 class GlobalMutex {
113 public:
114     GlobalMutex();
115     static void init();
116     static void lock();
117     static void unlock();
118 private:
119     static bool s_init;
120     static HMUTEX s_mutex;
121 };
122 
123 };
124 
125 using namespace TelEngine;
126 
127 HMUTEX GlobalMutex::s_mutex;
128 static GlobalMutex s_global;
129 static unsigned long s_maxwait = 0;
130 static bool s_unsafe = MUTEX_STATIC_UNSAFE;
131 static bool s_safety = false;
132 
133 volatile int MutexPrivate::s_count = 0;
134 volatile int MutexPrivate::s_locks = 0;
135 volatile int SemaphorePrivate::s_count = 0;
136 volatile int SemaphorePrivate::s_locks = 0;
137 bool GlobalMutex::s_init = true;
138 
139 // WARNING!!!
140 // No debug messages are allowed in mutexes since the debug output itself
141 // is serialized using a mutex!
142 
init()143 void GlobalMutex::init()
144 {
145     if (s_init) {
146 	s_init = false;
147 #ifdef _WINDOWS
148 	s_mutex = ::CreateMutex(NULL,FALSE,NULL);
149 #else
150 	pthread_mutexattr_t attr;
151 	::pthread_mutexattr_init(&attr);
152 	::pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP);
153 	::pthread_mutex_init(&s_mutex,&attr);
154 	::pthread_mutexattr_destroy(&attr);
155 #endif
156     }
157 }
158 
GlobalMutex()159 GlobalMutex::GlobalMutex()
160 {
161     init();
162 }
163 
lock()164 void GlobalMutex::lock()
165 {
166     init();
167     if (s_unsafe)
168 	return;
169 #ifdef _WINDOWS
170     ::WaitForSingleObject(s_mutex,INFINITE);
171 #else
172     ::pthread_mutex_lock(&s_mutex);
173 #endif
174 }
175 
unlock()176 void GlobalMutex::unlock()
177 {
178     if (s_unsafe)
179 	return;
180 #ifdef _WINDOWS
181     ::ReleaseMutex(s_mutex);
182 #else
183     ::pthread_mutex_unlock(&s_mutex);
184 #endif
185 }
186 
187 
MutexPrivate(bool recursive,const char * name)188 MutexPrivate::MutexPrivate(bool recursive, const char* name)
189     : m_refcount(1), m_locked(0), m_waiting(0), m_recursive(recursive),
190       m_name(name), m_owner(0)
191 {
192     GlobalMutex::lock();
193     s_count++;
194 #ifdef _WINDOWS
195     // All mutexes are recursive in Windows
196     m_mutex = ::CreateMutex(NULL,FALSE,NULL);
197 #else
198     if (recursive) {
199 	pthread_mutexattr_t attr;
200 	::pthread_mutexattr_init(&attr);
201 	::pthread_mutexattr_settype(&attr,PTHREAD_MUTEX_RECURSIVE_NP);
202 	::pthread_mutex_init(&m_mutex,&attr);
203 	::pthread_mutexattr_destroy(&attr);
204     }
205     else
206 	::pthread_mutex_init(&m_mutex,0);
207 #endif
208     GlobalMutex::unlock();
209 }
210 
~MutexPrivate()211 MutexPrivate::~MutexPrivate()
212 {
213     bool warn = false;
214     GlobalMutex::lock();
215     if (m_locked) {
216 	warn = true;
217 	m_locked--;
218 	if (s_safety)
219 	    s_locks--;
220 #ifdef _WINDOWS
221 	::ReleaseMutex(m_mutex);
222 #else
223 	::pthread_mutex_unlock(&m_mutex);
224 #endif
225     }
226     s_count--;
227 #ifdef _WINDOWS
228     ::CloseHandle(m_mutex);
229     m_mutex = 0;
230 #else
231     ::pthread_mutex_destroy(&m_mutex);
232 #endif
233     GlobalMutex::unlock();
234     if (m_locked || m_waiting)
235 	Debug(DebugFail,"MutexPrivate '%s' owned by '%s' destroyed with %u locks, %u waiting [%p]",
236 	    m_name,m_owner,m_locked,m_waiting,this);
237     else if (warn)
238 	Debug(DebugCrit,"MutexPrivate '%s' owned by '%s' unlocked in destructor [%p]",
239 	    m_name,m_owner,this);
240 }
241 
lock(long maxwait)242 bool MutexPrivate::lock(long maxwait)
243 {
244     bool rval = false;
245     bool warn = false;
246     if (s_maxwait && (maxwait < 0)) {
247 	maxwait = (long)s_maxwait;
248 	warn = true;
249     }
250     bool safety = s_safety;
251     if (safety)
252 	GlobalMutex::lock();
253     Thread* thr = Thread::current();
254     if (thr)
255 	thr->m_locking = true;
256     if (safety) {
257 	m_waiting++;
258 	GlobalMutex::unlock();
259     }
260 #ifdef _WINDOWS
261     DWORD ms = 0;
262     if (maxwait < 0)
263 	ms = INFINITE;
264     else if (maxwait > 0)
265 	ms = (DWORD)(maxwait / 1000);
266     rval = s_unsafe || (::WaitForSingleObject(m_mutex,ms) == WAIT_OBJECT_0);
267 #else
268     if (s_unsafe)
269 	rval = true;
270     else if (maxwait < 0)
271 	rval = !::pthread_mutex_lock(&m_mutex);
272     else if (!maxwait)
273 	rval = !::pthread_mutex_trylock(&m_mutex);
274     else {
275 	u_int64_t t = Time::now() + maxwait;
276 #ifdef HAVE_TIMEDLOCK
277 	struct timeval tv;
278 	struct timespec ts;
279 	Time::toTimeval(&tv,t);
280 	ts.tv_sec = tv.tv_sec;
281 	ts.tv_nsec = 1000 * tv.tv_usec;
282 	rval = !::pthread_mutex_timedlock(&m_mutex,&ts);
283 #else
284 	bool dead = false;
285 	do {
286 	    if (!dead) {
287 		dead = Thread::check(false);
288 		// give up only if caller asked for a limited wait
289 		if (dead && !warn)
290 		    break;
291 	    }
292 	    rval = !::pthread_mutex_trylock(&m_mutex);
293 	    if (rval)
294 		break;
295 	    Thread::yield();
296 	} while (t > Time::now());
297 #endif // HAVE_TIMEDLOCK
298     }
299 #endif // _WINDOWS
300     if (safety) {
301 	GlobalMutex::lock();
302 	m_waiting--;
303     }
304     if (thr)
305 	thr->m_locking = false;
306     if (rval) {
307 	if (safety)
308 	    s_locks++;
309 	m_locked++;
310 	if (thr) {
311 	    thr->m_locks++;
312 	    m_owner = thr->name();
313 	}
314 	else
315 	    m_owner = 0;
316     }
317     if (safety)
318 	GlobalMutex::unlock();
319     if (warn && !rval)
320 	Debug(DebugFail,"Thread '%s' could not lock mutex '%s' owned by '%s' waited by %u others for %lu usec!",
321 	    Thread::currentName(),m_name,m_owner,m_waiting,maxwait);
322     return rval;
323 }
324 
unlock()325 bool MutexPrivate::unlock()
326 {
327     bool ok = false;
328     // Hope we don't hit a bug related to the debug mutex!
329     bool safety = s_safety;
330     if (safety)
331 	GlobalMutex::lock();
332     if (m_locked) {
333 	Thread* thr = Thread::current();
334 	if (thr)
335 	    thr->m_locks--;
336 	if (!--m_locked) {
337 	    const char* tname = thr ? thr->name() : 0;
338 	    if (tname != m_owner)
339 		Debug(DebugFail,"MutexPrivate '%s' unlocked by '%s' but owned by '%s' [%p]",
340 		    m_name,tname,m_owner,this);
341 	    m_owner = 0;
342 	}
343 	if (safety) {
344 	    int locks = --s_locks;
345 	    if (locks < 0) {
346 		// this is very very bad - abort right now
347 		abortOnBug(true);
348 		s_locks = 0;
349 		Debug(DebugFail,"MutexPrivate::locks() is %d [%p]",locks,this);
350 	    }
351 	}
352 #ifdef _WINDOWS
353 	ok = s_unsafe || ::ReleaseMutex(m_mutex);
354 #else
355 	ok = s_unsafe || !::pthread_mutex_unlock(&m_mutex);
356 #endif
357 	if (!ok)
358 	    Debug(DebugFail,"Failed to unlock mutex '%s' [%p]",m_name,this);
359     }
360     else
361 	Debug(DebugFail,"MutexPrivate::unlock called on unlocked '%s' [%p]",m_name,this);
362     if (safety)
363 	GlobalMutex::unlock();
364     return ok;
365 }
366 
367 
SemaphorePrivate(unsigned int maxcount,const char * name,unsigned int initialCount)368 SemaphorePrivate::SemaphorePrivate(unsigned int maxcount, const char* name,
369     unsigned int initialCount)
370     : m_refcount(1), m_waiting(0), m_maxcount(maxcount),
371       m_name(name)
372 {
373     if (initialCount > m_maxcount)
374 	initialCount = m_maxcount;
375     GlobalMutex::lock();
376     s_count++;
377 #ifdef _WINDOWS
378     m_semaphore = ::CreateSemaphore(NULL,initialCount,maxcount,NULL);
379 #else
380     ::sem_init(&m_semaphore,0,initialCount);
381 #endif
382     GlobalMutex::unlock();
383 }
384 
~SemaphorePrivate()385 SemaphorePrivate::~SemaphorePrivate()
386 {
387     GlobalMutex::lock();
388     s_count--;
389 #ifdef _WINDOWS
390     ::CloseHandle(m_semaphore);
391     m_semaphore = 0;
392 #else
393     ::sem_destroy(&m_semaphore);
394 #endif
395     GlobalMutex::unlock();
396     if (m_waiting)
397 	Debug(DebugFail,"SemaphorePrivate '%s' destroyed with %u locks [%p]",
398 	    m_name,m_waiting,this);
399 }
400 
lock(long maxwait)401 bool SemaphorePrivate::lock(long maxwait)
402 {
403     bool rval = false;
404     bool warn = false;
405     if (s_maxwait && (maxwait < 0)) {
406 	maxwait = (long)s_maxwait;
407 	warn = true;
408     }
409     bool safety = s_safety;
410     if (safety)
411 	GlobalMutex::lock();
412     Thread* thr = Thread::current();
413     if (thr)
414 	thr->m_locking = true;
415     if (safety) {
416 	s_locks++;
417 	m_waiting++;
418 	GlobalMutex::unlock();
419     }
420 #ifdef _WINDOWS
421     DWORD ms = 0;
422     if (maxwait < 0)
423 	ms = INFINITE;
424     else if (maxwait > 0)
425 	ms = (DWORD)(maxwait / 1000);
426     rval = s_unsafe || (::WaitForSingleObject(m_semaphore,ms) == WAIT_OBJECT_0);
427 #else
428     if (s_unsafe)
429 	rval = true;
430     else if (maxwait < 0)
431 	rval = !::sem_wait(&m_semaphore);
432     else if (!maxwait)
433 	rval = !::sem_trywait(&m_semaphore);
434     else {
435 	u_int64_t t = Time::now() + maxwait;
436 #ifdef HAVE_TIMEDWAIT
437 	struct timeval tv;
438 	struct timespec ts;
439 	Time::toTimeval(&tv,t);
440 	ts.tv_sec = tv.tv_sec;
441 	ts.tv_nsec = 1000 * tv.tv_usec;
442 	rval = !::sem_timedwait(&m_semaphore,&ts);
443 #else
444 	bool dead = false;
445 	do {
446 	    if (!dead) {
447 		dead = Thread::check(false);
448 		// give up only if caller asked for a limited wait
449 		if (dead && !warn)
450 		    break;
451 	    }
452 	    rval = !::sem_trywait(&m_semaphore);
453 	    if (rval)
454 		break;
455 	    Thread::yield();
456 	} while (t > Time::now());
457 #endif // HAVE_TIMEDWAIT
458     }
459 #endif // _WINDOWS
460     if (safety) {
461 	GlobalMutex::lock();
462 	int locks = --s_locks;
463 	if (locks < 0) {
464 	    // this is very very bad - abort right now
465 	    abortOnBug(true);
466 	    s_locks = 0;
467 	    Debug(DebugFail,"SemaphorePrivate::locks() is %d [%p]",locks,this);
468 	}
469 	m_waiting--;
470     }
471     if (thr)
472 	thr->m_locking = false;
473     if (safety)
474 	GlobalMutex::unlock();
475     if (warn && !rval)
476 	Debug(DebugFail,"Thread '%s' could not lock semaphore '%s' waited by %u others for %lu usec!",
477 	    Thread::currentName(),m_name,m_waiting,maxwait);
478     return rval;
479 }
480 
unlock()481 bool SemaphorePrivate::unlock()
482 {
483     if (!s_unsafe) {
484 	bool safety = s_safety;
485 	if (safety)
486 	    GlobalMutex::lock();
487 #ifdef _WINDOWS
488 	::ReleaseSemaphore(m_semaphore,1,NULL);
489 #else
490 	int val = 0;
491 	if (!::sem_getvalue(&m_semaphore,&val) && (val < (int)m_maxcount))
492 	    ::sem_post(&m_semaphore);
493 #endif
494 	if (safety)
495 	    GlobalMutex::unlock();
496     }
497     return true;
498 }
499 
500 
~Lockable()501 Lockable::~Lockable()
502 {
503 }
504 
check(long maxwait)505 bool Lockable::check(long maxwait)
506 {
507     bool ret = lock(maxwait);
508     if (ret)
509 	unlock();
510     return ret;
511 }
512 
unlockAll()513 bool Lockable::unlockAll()
514 {
515     while (locked()) {
516 	if (!unlock())
517 	    return false;
518 	Thread::yield();
519     }
520     return true;
521 }
522 
startUsingNow()523 void Lockable::startUsingNow()
524 {
525     s_unsafe = false;
526 }
527 
enableSafety(bool safe)528 void Lockable::enableSafety(bool safe)
529 {
530     s_safety = safe;
531 }
532 
safety()533 bool Lockable::safety()
534 {
535     return s_safety;
536 }
537 
wait(unsigned long maxwait)538 void Lockable::wait(unsigned long maxwait)
539 {
540     s_maxwait = maxwait;
541 }
542 
wait()543 unsigned long Lockable::wait()
544 {
545     return s_maxwait;
546 }
547 
548 
Mutex(bool recursive,const char * name)549 Mutex::Mutex(bool recursive, const char* name)
550     : m_private(0)
551 {
552     if (!name)
553 	name = "?";
554     m_private = new MutexPrivate(recursive,name);
555 }
556 
Mutex(const Mutex & original)557 Mutex::Mutex(const Mutex &original)
558     : Lockable(),
559       m_private(original.privDataCopy())
560 {
561 }
562 
~Mutex()563 Mutex::~Mutex()
564 {
565     MutexPrivate* priv = m_private;
566     m_private = 0;
567     if (priv)
568 	priv->deref();
569 }
570 
operator =(const Mutex & original)571 Mutex& Mutex::operator=(const Mutex& original)
572 {
573     MutexPrivate* priv = m_private;
574     m_private = original.privDataCopy();
575     if (priv)
576 	priv->deref();
577     return *this;
578 }
579 
privDataCopy() const580 MutexPrivate* Mutex::privDataCopy() const
581 {
582     if (m_private)
583 	m_private->ref();
584     return m_private;
585 }
586 
lock(long maxwait)587 bool Mutex::lock(long maxwait)
588 {
589     return m_private && m_private->lock(maxwait);
590 }
591 
unlock()592 bool Mutex::unlock()
593 {
594     return m_private && m_private->unlock();
595 }
596 
recursive() const597 bool Mutex::recursive() const
598 {
599     return m_private && m_private->recursive();
600 }
601 
locked() const602 bool Mutex::locked() const
603 {
604     return m_private && m_private->locked();
605 }
606 
owner() const607 const char* Mutex::owner() const
608 {
609     return m_private ? m_private->owner() : static_cast<const char*>(0);
610 }
611 
count()612 int Mutex::count()
613 {
614     return MutexPrivate::s_count;
615 }
616 
locks()617 int Mutex::locks()
618 {
619     return s_safety ? MutexPrivate::s_locks : -1;
620 }
621 
efficientTimedLock()622 bool Mutex::efficientTimedLock()
623 {
624 #if defined(_WINDOWS) || defined(HAVE_TIMEDLOCK)
625     return true;
626 #else
627     return false;
628 #endif
629 }
630 
631 
MutexPool(unsigned int len,bool recursive,const char * name)632 MutexPool::MutexPool(unsigned int len, bool recursive, const char* name)
633     : m_name(0), m_data(0), m_length(len ? len : 1)
634 {
635     if (TelEngine::null(name))
636 	name = "Pool";
637     m_name = new String[m_length];
638     for (unsigned int i = 0; i < m_length; i++)
639 	m_name[i] << name << "::" << (i + 1);
640     m_data = new Mutex*[m_length];
641     for (unsigned int i = 0; i < m_length; i++)
642 	m_data[i] = new Mutex(recursive,m_name[i]);
643 }
644 
~MutexPool()645 MutexPool::~MutexPool()
646 {
647     if (m_data) {
648 	for (unsigned int i = 0; i < m_length; i++)
649 	    delete m_data[i];
650 	delete[] m_data;
651     }
652     if (m_name)
653 	delete[] m_name;
654 }
655 
656 
Semaphore(unsigned int maxcount,const char * name,unsigned int initialCount)657 Semaphore::Semaphore(unsigned int maxcount, const char* name, unsigned int initialCount)
658     : m_private(0)
659 {
660     if (!name)
661 	name = "?";
662     if (maxcount)
663 	m_private = new SemaphorePrivate(maxcount,name,initialCount);
664 }
665 
Semaphore(const Semaphore & original)666 Semaphore::Semaphore(const Semaphore &original)
667     : Lockable(),
668       m_private(original.privDataCopy())
669 {
670 }
671 
~Semaphore()672 Semaphore::~Semaphore()
673 {
674     SemaphorePrivate* priv = m_private;
675     m_private = 0;
676     if (priv)
677 	priv->deref();
678 }
679 
operator =(const Semaphore & original)680 Semaphore& Semaphore::operator=(const Semaphore& original)
681 {
682     SemaphorePrivate* priv = m_private;
683     m_private = original.privDataCopy();
684     if (priv)
685 	priv->deref();
686     return *this;
687 }
688 
privDataCopy() const689 SemaphorePrivate* Semaphore::privDataCopy() const
690 {
691     if (m_private)
692 	m_private->ref();
693     return m_private;
694 }
695 
lock(long maxwait)696 bool Semaphore::lock(long maxwait)
697 {
698     return m_private && m_private->lock(maxwait);
699 }
700 
unlock()701 bool Semaphore::unlock()
702 {
703     return m_private && m_private->unlock();
704 }
705 
locked() const706 bool Semaphore::locked() const
707 {
708     return m_private && m_private->locked();
709 }
710 
count()711 int Semaphore::count()
712 {
713     return SemaphorePrivate::s_count;
714 }
715 
locks()716 int Semaphore::locks()
717 {
718     return s_safety ? SemaphorePrivate::s_locks : -1;
719 }
720 
efficientTimedLock()721 bool Semaphore::efficientTimedLock()
722 {
723 #if defined(_WINDOWS) || defined(HAVE_TIMEDWAIT)
724     return true;
725 #else
726     return false;
727 #endif
728 }
729 
730 
lock(Mutex * mx1,Mutex * mx2,long maxwait)731 bool Lock2::lock(Mutex* mx1, Mutex* mx2, long maxwait)
732 {
733     // if we got only one mutex it must be mx1
734     if (!mx1) {
735 	mx1 = mx2;
736 	mx2 = 0;
737     }
738     // enforce a fixed locking order - lowest address first
739     else if (mx1 && mx2 && (mx1 > mx2)) {
740 	Mutex* tmp = mx1;
741 	mx1 = mx2;
742 	mx2 = tmp;
743     }
744     drop();
745     if (!mx1)
746 	return false;
747     if (!mx1->lock(maxwait))
748 	return false;
749     if (mx2) {
750 	if (!mx2->lock(maxwait)) {
751 	    mx1->unlock();
752 	    return false;
753 	}
754     }
755     m_mx1 = mx1;
756     m_mx2 = mx2;
757     return true;
758 }
759 
drop()760 void Lock2::drop()
761 {
762     Mutex* mx1 = m_mx1;
763     Mutex* mx2 = m_mx2;
764     m_mx1 = m_mx2 = 0;
765     // unlock in reverse order for performance reason
766     if (mx2)
767 	mx2->unlock();
768     if (mx1)
769 	mx1->unlock();
770 }
771 
772 /* vi: set ts=8 sw=4 sts=4 noet: */
773