]> git.saurik.com Git - apple/security.git/blobdiff - cdsa/cdsa_utilities/threading.cpp
Security-177.tar.gz
[apple/security.git] / cdsa / cdsa_utilities / threading.cpp
index d187a8e369e457b9fd0105af2dede826080735c2..e1827f70a6d3fc086729ece97a302df97504b0f7 100644 (file)
 // Since we are planning to generate "stub" out of line code for threading methods,
 // we must force THREAD_NDEBUG to off while compiling our header. Trust me.
 //
 // Since we are planning to generate "stub" out of line code for threading methods,
 // we must force THREAD_NDEBUG to off while compiling our header. Trust me.
 //
-#if !defined(THREAD_CLEAN_NDEBUG)
-# define THREAD_MAKE_STUBS
-#endif
 #include <Security/threading.h>
 #include <Security/threading.h>
+#include <Security/globalizer.h>
+#include <Security/memutils.h>
 
 
 //
 
 
 //
@@ -46,10 +45,7 @@ ThreadStoreSlot::~ThreadStoreSlot()
 {
     //@@@ if we wanted to dispose of pending task objects, we'd have
     //@@@ to keep a set of them and delete them explicitly here
 {
     //@@@ if we wanted to dispose of pending task objects, we'd have
     //@@@ to keep a set of them and delete them explicitly here
-#if BUG_2998157
-       // @@@ bug 2998157 does not clear slots on delete or allocate. Leak them for now
     pthread_key_delete(mKey);
     pthread_key_delete(mKey);
-#endif //BUG_2998157
 }
 
 #endif
 }
 
 #endif
@@ -60,18 +56,16 @@ ThreadStoreSlot::~ThreadStoreSlot()
 //
 #if _USE_THREADS == _USE_PTHREADS
 
 //
 #if _USE_THREADS == _USE_PTHREADS
 
-#if !defined(THREAD_CLEAN_NDEBUG)
-
 bool Mutex::debugHasInitialized;
 bool Mutex::loggingMutexi;
 
 bool Mutex::debugHasInitialized;
 bool Mutex::loggingMutexi;
 
-Mutex::Mutex(bool log)
+inline void Mutex::init(Type type, bool log)
 {
 #if !defined(THREAD_NDEBUG)
        // this debug-setup code isn't interlocked, but it's idempotent
        // (don't worry, be happy)
        if (!debugHasInitialized) {
 {
 #if !defined(THREAD_NDEBUG)
        // this debug-setup code isn't interlocked, but it's idempotent
        // (don't worry, be happy)
        if (!debugHasInitialized) {
-               loggingMutexi = Debug::debugging("mutex");
+               loggingMutexi = Debug::debugging("mutex") || Debug::debugging("mutex-c");
                debugHasInitialized = true;
        }
        debugLog = log && loggingMutexi;
                debugHasInitialized = true;
        }
        debugLog = log && loggingMutexi;
@@ -79,14 +73,46 @@ Mutex::Mutex(bool log)
 #else
     debugLog = false;
 #endif //THREAD_NDEBUG    
 #else
     debugLog = false;
 #endif //THREAD_NDEBUG    
+}
+
+struct Recursive : public pthread_mutexattr_t {
+       Recursive()
+       {
+               pthread_mutexattr_init(this);
+               pthread_mutexattr_settype(this, PTHREAD_MUTEX_RECURSIVE);
+       }
+};
+
+
+Mutex::Mutex(bool log)
+{
+       init(normal, log);
        check(pthread_mutex_init(&me, NULL));
 }
 
        check(pthread_mutex_init(&me, NULL));
 }
 
+Mutex::Mutex(Type type, bool log)
+{
+       init(type, log);
+       switch (type) {
+       case normal:
+        check(pthread_mutex_init(&me, NULL));
+               break;
+       case recursive:
+               static ModuleNexus<Recursive> recursive;
+               check(pthread_mutex_init(&me, &recursive()));
+       };
+ }
+
 Mutex::~Mutex()
 {
 #if !defined(THREAD_NDEBUG)
 Mutex::~Mutex()
 {
 #if !defined(THREAD_NDEBUG)
-       if (debugLog && (useCount > 100 || contentionCount > 0))
-               debug("mutex", "%p destroyed after %ld/%ld locks/contentions", this, useCount, contentionCount);
+       if (debugLog) {
+               if (contentionCount > 0)
+                       secdebug("mutex-c", "%p destroyed after %ld/%ld locks/contentions",
+                                        this, useCount, contentionCount);
+               else if (useCount > 100)
+                       secdebug("mutex", "%p destroyed after %ld locks", this, useCount);
+       }
 #endif //THREAD_NDEBUG
        check(pthread_mutex_destroy(&me));
 }
 #endif //THREAD_NDEBUG
        check(pthread_mutex_destroy(&me));
 }
@@ -101,16 +127,16 @@ void Mutex::lock()
                        break;
                case EBUSY:
                        if (debugLog)
                        break;
                case EBUSY:
                        if (debugLog)
-                               debug("mutex", "%p contended (%ld of %ld)", this, ++contentionCount, useCount);
+                               secdebug("mutex-c", "%p contended (%ld of %ld)", this, ++contentionCount, useCount);
                        check(pthread_mutex_lock(&me));
                        break;
                default:
                        UnixError::throwMe(err);
                }
                if (useCount % 100 == 0)
                        check(pthread_mutex_lock(&me));
                        break;
                default:
                        UnixError::throwMe(err);
                }
                if (useCount % 100 == 0)
-                       debug("mutex", "%p locked %ld", this, useCount);
+                       secdebug("mutex", "%p locked %ld", this, useCount);
                else
                else
-                       debug("mutex", "%p locked", this);
+                       secdebug("mutex", "%p locked", this);
         return;
     }
 #endif //THREAD_NDEBUG
         return;
     }
 #endif //THREAD_NDEBUG
@@ -125,7 +151,7 @@ bool Mutex::tryLock()
                        UnixError::throwMe(err);
 #if !defined(THREAD_NDEBUG)
                if (debugLog)
                        UnixError::throwMe(err);
 #if !defined(THREAD_NDEBUG)
                if (debugLog)
-                       debug("mutex", "%p trylock contended (%ld of %ld)",
+                       secdebug("mutex-c", "%p trylock contended (%ld of %ld)",
                                this, ++contentionCount, useCount);
 #endif //THREAD_NDEBUG
                return false;
                                this, ++contentionCount, useCount);
 #endif //THREAD_NDEBUG
                return false;
@@ -133,9 +159,9 @@ bool Mutex::tryLock()
 #if !defined(THREAD_NDEBUG)
        if (debugLog)
                if (useCount % 100 == 0)
 #if !defined(THREAD_NDEBUG)
        if (debugLog)
                if (useCount % 100 == 0)
-                       debug("mutex", "%p locked %ld", this, useCount);
+                       secdebug("mutex", "%p locked %ld", this, useCount);
                else
                else
-                       debug("mutex", "%p locked", this);
+                       secdebug("mutex", "%p locked", this);
 #endif //THREAD_NDEBUG
        return true;
 }
 #endif //THREAD_NDEBUG
        return true;
 }
@@ -144,12 +170,11 @@ void Mutex::unlock()
 {
 #if !defined(MUTEX_NDEBUG)
        if (debugLog)
 {
 #if !defined(MUTEX_NDEBUG)
        if (debugLog)
-               debug("mutex", "%p unlocked", this);
+               secdebug("mutex", "%p unlocked", this);
 #endif //MUTEX_NDEBUG
        check(pthread_mutex_unlock(&me));
 }
 
 #endif //MUTEX_NDEBUG
        check(pthread_mutex_unlock(&me));
 }
 
-#endif //!THREAD_CLEAN_NDEBUG
 #endif //PTHREADS
 
 
 #endif //PTHREADS
 
 
@@ -164,7 +189,7 @@ void CountingMutex::enter()
 {
     lock();
     mCount++;
 {
     lock();
     mCount++;
-    debug("mutex", "%p up to %d", this, mCount);
+    secdebug("mutex", "%p up to %d", this, mCount);
     unlock();
 }
 
     unlock();
 }
 
@@ -173,7 +198,7 @@ bool CountingMutex::tryEnter()
     if (!tryLock())
         return false;
     mCount++;
     if (!tryLock())
         return false;
     mCount++;
-    debug("mutex", "%p up to %d (was try)", this, mCount);
+    secdebug("mutex", "%p up to %d (was try)", this, mCount);
     unlock();
     return true;
 }
     unlock();
     return true;
 }
@@ -183,14 +208,14 @@ void CountingMutex::exit()
     lock();
     assert(mCount > 0);
     mCount--;
     lock();
     assert(mCount > 0);
     mCount--;
-    debug("mutex", "%p down to %d", this, mCount);
+    secdebug("mutex", "%p down to %d", this, mCount);
     unlock();
 }
 
 void CountingMutex::finishEnter()
 {
     mCount++;
     unlock();
 }
 
 void CountingMutex::finishEnter()
 {
     mCount++;
-    debug("mutex", "%p finish up to %d", this, mCount);
+    secdebug("mutex", "%p finish up to %d", this, mCount);
     unlock();
 }
 
     unlock();
 }
 
@@ -198,7 +223,7 @@ void CountingMutex::finishExit()
 {
     assert(mCount > 0);
     mCount--; 
 {
     assert(mCount > 0);
     mCount--; 
-    debug("mutex", "%p finish down to %d", this, mCount);
+    secdebug("mutex", "%p finish down to %d", this, mCount);
     unlock();
 }
 
     unlock();
 }
 
@@ -217,7 +242,7 @@ void Thread::run()
 {
     if (int err = pthread_create(&self.mIdent, NULL, runner, this))
         UnixError::throwMe(err);
 {
     if (int err = pthread_create(&self.mIdent, NULL, runner, this))
         UnixError::throwMe(err);
-       debug("thread", "%p created", self.mIdent);
+       secdebug("thread", "%p created", self.mIdent);
 }
 
 void *Thread::runner(void *arg)
 }
 
 void *Thread::runner(void *arg)
@@ -225,9 +250,9 @@ void *Thread::runner(void *arg)
     Thread *me = static_cast<Thread *>(arg);
     if (int err = pthread_detach(me->self.mIdent))
         UnixError::throwMe(err);
     Thread *me = static_cast<Thread *>(arg);
     if (int err = pthread_detach(me->self.mIdent))
         UnixError::throwMe(err);
-       debug("thread", "%p starting", me->self.mIdent);
+       secdebug("thread", "%p starting", me->self.mIdent);
     me->action();
     me->action();
-       debug("thread", "%p terminating", me->self.mIdent);
+       secdebug("thread", "%p terminating", me->self.mIdent);
     delete me;
     return NULL;
 }
     delete me;
     return NULL;
 }
@@ -237,21 +262,21 @@ void Thread::yield()
        sched_yield();
 }
 
        sched_yield();
 }
 
-#if !defined(NDEBUG)
-
-#include <Security/memutils.h>
 
 
+//
+// Make a more-or-less unique string representation of a thread id.
+// This is meant FOR DEBUGGING ONLY. Don't use this in production code.
+//
 void Thread::Identity::getIdString(char id[idLength])
 {
        pthread_t current = pthread_self();
        // We're not supposed to know what a pthread_t is. Just print the first few bytes...
        // (On MacOS X, it's a pointer to a pthread_t internal structure, so this works fine.)
 void Thread::Identity::getIdString(char id[idLength])
 {
        pthread_t current = pthread_self();
        // We're not supposed to know what a pthread_t is. Just print the first few bytes...
        // (On MacOS X, it's a pointer to a pthread_t internal structure, so this works fine.)
-       void *p;
-       memcpy(&p, &current, sizeof(p));
-       snprintf(id, idLength, "%lx", long(p));
+       long ids;
+       memcpy(&ids, &current, sizeof(ids));
+       snprintf(id, idLength, "%lx", ids);
 }
 
 }
 
-#endif // NDEBUG
 
 #endif // PTHREADS
 
 
 #endif // PTHREADS