From a15cf65c44d5c224169c32ef5495b68c758134b7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=B6rg=20Frings-F=C3=BCrst?= Date: Sun, 18 May 2014 16:08:14 +0200 Subject: Imported Upstream version 3.3.0.2 --- libcult/cult/sched/condition.cxx | 49 +++++++++ libcult/cult/sched/condition.hxx | 42 ++++++++ libcult/cult/sched/exception.hxx | 30 ++++++ libcult/cult/sched/lock.cxx | 13 +++ libcult/cult/sched/lock.hxx | 58 +++++++++++ libcult/cult/sched/mutex.cxx | 54 ++++++++++ libcult/cult/sched/mutex.hxx | 41 ++++++++ libcult/cult/sched/spin.cxx | 28 ++++++ libcult/cult/sched/spin.hxx | 41 ++++++++ libcult/cult/sched/spin.ixx | 43 ++++++++ libcult/cult/sched/thread.cxx | 211 +++++++++++++++++++++++++++++++++++++++ libcult/cult/sched/thread.hxx | 86 ++++++++++++++++ 12 files changed, 696 insertions(+) create mode 100644 libcult/cult/sched/condition.cxx create mode 100644 libcult/cult/sched/condition.hxx create mode 100644 libcult/cult/sched/exception.hxx create mode 100644 libcult/cult/sched/lock.cxx create mode 100644 libcult/cult/sched/lock.hxx create mode 100644 libcult/cult/sched/mutex.cxx create mode 100644 libcult/cult/sched/mutex.hxx create mode 100644 libcult/cult/sched/spin.cxx create mode 100644 libcult/cult/sched/spin.hxx create mode 100644 libcult/cult/sched/spin.ixx create mode 100644 libcult/cult/sched/thread.cxx create mode 100644 libcult/cult/sched/thread.hxx (limited to 'libcult/cult/sched') diff --git a/libcult/cult/sched/condition.cxx b/libcult/cult/sched/condition.cxx new file mode 100644 index 0000000..5f547c8 --- /dev/null +++ b/libcult/cult/sched/condition.cxx @@ -0,0 +1,49 @@ +// file : cult/sched/condition.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Condition:: + ~Condition () + { + if (Int e = pthread_cond_destroy (&cond_)) + throw Implementation (e); + } + + Condition:: + Condition (Mutex& mutex) + : mutex_ (mutex) + { + if (Int e = pthread_cond_init (&cond_, 0)) + throw Implementation (e); + } + + Void Condition:: + signal () + { + if (Int e = pthread_cond_signal (&cond_)) + throw Implementation (e); + } + + Void Condition:: + broadcast () + { + if (Int e = pthread_cond_broadcast (&cond_)) + throw Implementation (e); + } + + Void Condition:: + wait () + { + if (Int e = pthread_cond_wait (&cond_, &mutex_.mutex_)) + throw Implementation (e); + } + } +} diff --git a/libcult/cult/sched/condition.hxx b/libcult/cult/sched/condition.hxx new file mode 100644 index 0000000..b1a0f30 --- /dev/null +++ b/libcult/cult/sched/condition.hxx @@ -0,0 +1,42 @@ +// file : cult/sched/condition.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_CONDITION_HXX +#define CULT_SCHED_CONDITION_HXX + +#include + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Condition: public NonCopyable + { + public: + ~Condition (); + + Condition (Mutex& mutex); + + Void + signal (); + + Void + broadcast (); + + Void + wait (); + + private: + Mutex& mutex_; + pthread_cond_t cond_; + }; + } +} + +#endif // CULT_SCHED_CONDITION_HXX diff --git a/libcult/cult/sched/exception.hxx b/libcult/cult/sched/exception.hxx new file mode 100644 index 0000000..3fa6e5f --- /dev/null +++ b/libcult/cult/sched/exception.hxx @@ -0,0 +1,30 @@ +// file : cult/sched/exception.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_EXCEPTION_HXX +#define CULT_SCHED_EXCEPTION_HXX + +#include + +#include +#include + +namespace Cult +{ + namespace Sched + { + struct Exception: virtual EH::Exception {}; + + struct Implementation: virtual Exception, virtual OS::Exception + { + Implementation (Int code) throw () + : OS::Exception (code) + { + } + }; + } +} + +#endif // CULT_SCHED_EXCEPTION_HXX diff --git a/libcult/cult/sched/lock.cxx b/libcult/cult/sched/lock.cxx new file mode 100644 index 0000000..853d9b0 --- /dev/null +++ b/libcult/cult/sched/lock.cxx @@ -0,0 +1,13 @@ +// file : cult/sched/lock.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace Sched + { + } +} diff --git a/libcult/cult/sched/lock.hxx b/libcult/cult/sched/lock.hxx new file mode 100644 index 0000000..1ecf3fb --- /dev/null +++ b/libcult/cult/sched/lock.hxx @@ -0,0 +1,58 @@ +// file : cult/sched/lock.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_LOCK_HXX +#define CULT_SCHED_LOCK_HXX + +#include + +namespace Cult +{ + namespace Sched + { + class Lock: public NonCopyable + { + public: + ~Lock () + { + unlock (); + } + + template + Lock (X& x) + : x_ (reinterpret_cast(&x)), + unlock_ (&unlock), + locked_ (true) + { + x.lock (); + } + + Void + unlock () + { + if (locked_) + { + unlock_ (x_); + locked_ = false; + } + } + + private: + template + static Void + unlock (Void* p) + { + reinterpret_cast (p)->unlock (); + } + + private: + Void* x_; + Void (*unlock_) (Void*); + Boolean locked_; + }; + } +} + +#endif // CULT_SCHED_LOCK_HXX diff --git a/libcult/cult/sched/mutex.cxx b/libcult/cult/sched/mutex.cxx new file mode 100644 index 0000000..9667a67 --- /dev/null +++ b/libcult/cult/sched/mutex.cxx @@ -0,0 +1,54 @@ +// file : cult/sched/mutex.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Mutex:: + ~Mutex () + { + if (Int e = pthread_mutex_destroy (&mutex_)) + throw Implementation (e); + } + + Mutex:: + Mutex () + { + if (Int e = pthread_mutex_init (&mutex_, 0)) + throw Implementation (e); + } + + Void Mutex:: + lock () + { + if (Int e = pthread_mutex_lock (&mutex_)) + throw Implementation (e); + } + + Boolean Mutex:: + try_lock () + { + Int e (pthread_mutex_trylock (&mutex_)); + + switch (e) + { + case 0: return true; + case EBUSY: return false; + default: throw Implementation (e); + } + } + + Void Mutex:: + unlock () + { + if (Int e = pthread_mutex_unlock (&mutex_)) + throw Implementation (e); + } + } +} diff --git a/libcult/cult/sched/mutex.hxx b/libcult/cult/sched/mutex.hxx new file mode 100644 index 0000000..0c6daee --- /dev/null +++ b/libcult/cult/sched/mutex.hxx @@ -0,0 +1,41 @@ +// file : cult/sched/mutex.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_MUTEX_HXX +#define CULT_SCHED_MUTEX_HXX + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Mutex: public NonCopyable + { + public: + ~Mutex (); + + Mutex (); + + Void + lock (); + + Boolean + try_lock (); + + Void + unlock (); + + private: + friend class Condition; + + pthread_mutex_t mutex_; + }; + } +} + +#endif // CULT_SCHED_MUTEX_HXX diff --git a/libcult/cult/sched/spin.cxx b/libcult/cult/sched/spin.cxx new file mode 100644 index 0000000..54df7ce --- /dev/null +++ b/libcult/cult/sched/spin.cxx @@ -0,0 +1,28 @@ +// file : cult/sched/spin.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include + +namespace Cult +{ + namespace Sched + { + Spin:: + ~Spin () + { + if (Int e = pthread_spin_destroy (&spin_)) + throw Implementation (e); + } + + Spin:: + Spin () + { + if (Int e = pthread_spin_init (&spin_, PTHREAD_PROCESS_PRIVATE)) + throw Implementation (e); + } + } +} + diff --git a/libcult/cult/sched/spin.hxx b/libcult/cult/sched/spin.hxx new file mode 100644 index 0000000..c32e836 --- /dev/null +++ b/libcult/cult/sched/spin.hxx @@ -0,0 +1,41 @@ +// file : cult/sched/spin.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_SPIN_HXX +#define CULT_SCHED_SPIN_HXX + +#include + +#include + +namespace Cult +{ + namespace Sched + { + class Spin: public NonCopyable + { + public: + ~Spin (); + + Spin (); + + Void + lock (); + + Boolean + try_lock (); + + Void + unlock (); + + private: + pthread_spinlock_t spin_; + }; + } +} + +#include + +#endif // CULT_SCHED_SPIN_HXX diff --git a/libcult/cult/sched/spin.ixx b/libcult/cult/sched/spin.ixx new file mode 100644 index 0000000..2accdde --- /dev/null +++ b/libcult/cult/sched/spin.ixx @@ -0,0 +1,43 @@ +// file : cult/sched/spin.ixx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include + +namespace Cult +{ + namespace Sched + { + inline + Void Spin:: + lock () + { + if (Int e = pthread_spin_lock (&spin_)) + throw Implementation (e); + } + + inline + Boolean Spin:: + try_lock () + { + Int e (pthread_spin_trylock (&spin_)); + + switch (e) + { + case 0: return true; + case EBUSY: return false; + default: throw Implementation (e); + } + } + + inline + Void Spin:: + unlock () + { + if (Int e = pthread_spin_unlock (&spin_)) + throw Implementation (e); + } + } +} + diff --git a/libcult/cult/sched/thread.cxx b/libcult/cult/sched/thread.cxx new file mode 100644 index 0000000..89368b6 --- /dev/null +++ b/libcult/cult/sched/thread.cxx @@ -0,0 +1,211 @@ +// file : cult/sched/thread.cxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#include +#include +#include + +#include // MM::inc_ref + +#include + +namespace Cult +{ + namespace Sched + { + namespace + { + Trace::Stream tout ("Cult::Sched::Thread", 7); + } + + namespace Bits + { + typedef Void* (*Routine) (Void*); + + struct StartData + { + StartData (Shptr const& thread, Routine routine, void* arg) + : thread_ (thread), routine_ (routine), arg_ (arg) + { + } + + ~StartData () + { + tout << 8 << "start data is being destroyed."; + } + + Shptr thread_; + Routine routine_; + Void* arg_; + }; + + static pthread_key_t key; + static pthread_once_t key_once = PTHREAD_ONCE_INIT; + + extern "C" Void + cult_thread_dtor (Void* p) + { + // Exception in this function will result in the call + // to std::terminate(). + // + + tout << "cult_thread_dtor is being executed."; + + Shptr self (reinterpret_cast (p)); + } + + extern "C" Void + cult_thread_make_key () + { + if (Int e = pthread_key_create (&key, &cult_thread_dtor)) + throw Implementation (e); + } + + extern "C" Void* + cult_thread_trampoline (Void* arg) + { + // Any failure in this function will result in the call + // to std::terminate(). + // + + Routine routine; + + { + Shptr data (reinterpret_cast (arg)); + + Thread* p (data->thread_.get ()); + + if (Int e = pthread_setspecific (key, p)) + throw Implementation (e); + else + MM::inc_ref (p); + + routine = data->routine_; + arg = data->arg_; + } + + return routine (arg); + } + } + + Thread:: + Thread (Void* (*routine) (Void*), Void* arg) + : detached_ (false) + { + using Bits::StartData; + + tout << "thread is being constructed."; + + pthread_once (&Bits::key_once, &Bits::cult_thread_make_key); + + Shptr self (MM::inc_ref (this)); + + Shptr data (new StartData (self, routine, arg)); + + if (Int e = pthread_create (&id_, + 0, + &Bits::cult_thread_trampoline, + data.get ())) + { + throw Implementation (e); + } + else + { + // If pthread_create did not fail then thread_trampoline + // will release the data. + // + data.release (); + } + } + + Thread:: + Thread () + : id_ (pthread_self ()), detached_ (false) //@@ We can't be sure + // the it is detached. + { + tout << "thread is being adopted."; + + pthread_once (&Bits::key_once, &Bits::cult_thread_make_key); + + if (pthread_getspecific (Bits::key) != 0) + throw Adopted (); + + Shptr self (MM::inc_ref (this)); + + if(Int e = pthread_setspecific (Bits::key, this)) + { + throw Implementation (e); + } + else + { + // TSD slot has the reference now. + // + self.release (); + } + } + + Void* Thread:: + join () + { + Lock lock (mutex_); + + if (detached_) + throw Joined (); + + Void* r; + + if (Int e = pthread_join (id_, &r)) + throw Implementation (e); + + detached_ = true; + + return r; + } + + Void Thread:: + cancel () + { + if (Int e = pthread_cancel (id_)) + throw Implementation (e); + } + + Void Thread:: + exit (Void* ret) + { + pthread_exit (ret); + } + + Shptr Thread:: + self () + { + Thread* p (reinterpret_cast (pthread_getspecific (Bits::key))); + + if (p != 0) + return Shptr (MM::inc_ref (p)); + else + throw Foreign (); + } + + Void Thread:: + test_cancel () + { + pthread_testcancel (); + } + + Thread:: + ~Thread () + { + tout << "thread is being destroyed."; + + Lock lock (mutex_); + + if (!detached_) + { + if (Int e = pthread_detach (id_)) + throw Implementation (e); + } + } + } +} diff --git a/libcult/cult/sched/thread.hxx b/libcult/cult/sched/thread.hxx new file mode 100644 index 0000000..49d6225 --- /dev/null +++ b/libcult/cult/sched/thread.hxx @@ -0,0 +1,86 @@ +// file : cult/sched/thread.hxx +// author : Boris Kolpackov +// copyright : Copyright (c) 2005-2010 Boris Kolpackov +// license : GNU GPL v2 + exceptions; see accompanying LICENSE file + +#ifndef CULT_SCHED_THREAD_HXX +#define CULT_SCHED_THREAD_HXX + +#include +#include + +#include +#include + +#include + +#include + +namespace Cult +{ + namespace Sched + { + // Instantiating an automatic variable of type Thread results + // in undefined behavior (read core dump). + // + class Thread: public MM::ServiceAwareObject + { + public: + struct Exception: virtual Sched::Exception {}; + + public: + virtual + ~Thread (); + + Thread (Void* (*StartRoutine) (Void*), Void* arg = 0); + + // Adopt an existing thread. Adoption of a detached thread + // results in undefined behavior. Adoption of an already + // adopted thread results in Adopted exception. + // + + struct Adopted: virtual Exception {}; + + Thread (); + + public: + // Joining an already joined thread results in Joined exception. + // + + struct Joined: virtual Exception {}; + + //@@ Need to work out the cancelled case. + // + Void* + join (); + + Void + cancel (); + + public: + static Void + exit (Void* ret); + + // self() may not be called in TSD destructors. Call to self() from + // a foreign thread (i.e., one that is neither native nor adopted) + // results in Foreign exception. + // + + struct Foreign: virtual Exception {}; + + static Shptr + self (); + + static Void + test_cancel (); + + private: + pthread_t id_; + + Boolean detached_; + Mutex mutex_; + }; + } +} + +#endif // CULT_SCHED_THREAD_HXX -- cgit v1.2.3