From owner-freebsd-current Fri Nov 24 11: 3:29 2000 Delivered-To: freebsd-current@freebsd.org Received: from ozz.freebsd.org.ru (ozz.etrust.ru [194.84.67.11]) by hub.freebsd.org (Postfix) with ESMTP id 47FAC37B4C5; Fri, 24 Nov 2000 11:03:08 -0800 (PST) Received: (from osa@localhost) by ozz.freebsd.org.ru (8.11.1/8.11.1) id eAOJ34L01054; Fri, 24 Nov 2000 22:03:04 +0300 (MSK) (envelope-from osa) Date: Fri, 24 Nov 2000 22:03:04 +0300 From: Sergey Osokin To: freebsd-current@FreeBSD.org Cc: freebsd-stable@FreeBSD.org Subject: stranges in threads implementation... possible bug? Message-ID: <20001124220303.A1027@freebsd.org.ru> Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline User-Agent: Mutt/1.2.5i Sender: owner-freebsd-current@FreeBSD.ORG Precedence: bulk X-Loop: FreeBSD.ORG Hello! My friend find some stranges in FreeBSD threads implementation... Here is a "special" code: ===================================== #include #include #include #include #include #include #define Debug(x) printf x extern "C" { typedef void *(*_THR_C_FUNC)(void *args); } typedef void *(*_THR_FUNC)(void *args); /*-----------------------------------------------------------------*/ class Mutex { public: Mutex() { assert(::pthread_mutex_init(&this->lock_, 0) == 0); } ~Mutex (void) { assert(::pthread_mutex_destroy(&this->lock_)==0); } int acquire (void) { return ::pthread_mutex_lock(&this->lock_); } int release (void) { return ::pthread_mutex_unlock (&this->lock_); } pthread_mutex_t lock_; }; /*-----------------------------------------------------------------*/ class Condition { public: Condition (Mutex &m); ~Condition (void); int wait (void); void signal (void); protected: pthread_cond_t cond_; Mutex &mutex_; }; Condition::Condition (Mutex &m) : mutex_ (m) { assert (pthread_cond_init(&this->cond_, 0) == 0); } Condition::~Condition (void) { while(::pthread_cond_destroy(&this->cond_) == -1 && errno == EBUSY) { assert(::pthread_cond_broadcast(&this->cond_) == 0); #ifdef __linux__ ::sched_yield (); #else ::pthread_yield(); #endif } } int Condition::wait (void) { return ::pthread_cond_wait(&this->cond_, &this->mutex_.lock_); } void Condition::signal (void) { assert(::pthread_cond_signal(&this->cond_) == 0); } /*-----------------------------------------------------------------*/ class Guard { public: Guard (Mutex &l); ~Guard (void); private: Mutex *lock_; }; Guard::Guard (Mutex &l) : lock_ (&l) { this->lock_->acquire (); } Guard::~Guard (void) { this->lock_->release (); } /*-----------------------------------------------------------------*/ class _Base_Thread_Adapter { public: _Base_Thread_Adapter (_THR_FUNC user_func, void *arg); void *invoke (void); _THR_C_FUNC entry_point (void) { return entry_point_; } private: _THR_FUNC user_func_; void *arg_; _THR_C_FUNC entry_point_; }; extern "C" void * _thread_adapter (void *args) { _Base_Thread_Adapter *thread_args = (_Base_Thread_Adapter*)args; void *status = thread_args->invoke (); return status; } _Base_Thread_Adapter::_Base_Thread_Adapter (_THR_FUNC user_func, void *arg) : user_func_ (user_func), arg_ (arg), entry_point_ (_thread_adapter) { } void * _Base_Thread_Adapter::invoke (void) { void *(*func)(void *) = this->user_func_; void *arg = this->arg_; delete this; return func(arg); } /*-----------------------------------------------------------------*/ class SS { public: void spawn(); static void run(); static void *WThread( void *data ); }; /*---------------------------------------------------------------------*/ static Mutex CMutex; static Condition Cond(CMutex); static Mutex m1; /*---------------------------------------------------------------------*/ #define REL(m,n) assert(m.release() != -1) #define ACQ(m,n) assert(m.acquire() != -1) /*---------------------------------------------------------------------*/ void * SS::WThread( void *data ) { Cond.signal(); Debug(("run thread...\n")); SS::run(); Debug(("thread ended\n")); return NULL; } /*---------------------------------------------------------------------*/ int thr_create (_THR_FUNC func, void *args) { _Base_Thread_Adapter *thread_args; thread_args = new _Base_Thread_Adapter(func, args); pthread_attr_t attr; if (::pthread_attr_init (&attr) != 0) return -1; ::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); pthread_t thr_id; assert( ::pthread_create (&thr_id, &attr, thread_args->entry_point(), thread_args) == 0 ); ::pthread_attr_destroy (&attr); } /*---------------------------------------------------------------------*/ void SS::spawn() { #ifdef BAD int rc; Guard guard(m1); // !!! #else Guard guard(m1); // !!! int rc; #endif pthread_attr_t attr; if (::pthread_attr_init (&attr) != 0) return; ::pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); thr_create(SS::WThread, (void *)0); ::pthread_attr_destroy (&attr); ACQ(CMutex, "CMutex"); rc = Cond.wait(); if( rc == -1 ) Debug(("Cond wait failed: %s\n", strerror(errno))); REL(CMutex, "CMutex"); } /*---------------------------------------------------------------------*/ void SS::run() { string s; // !!! string s1; // !!! sleep(1); } /*=====================================================================*/ static void sp_call(SS *ss) { string s; // !!! ss->spawn(); } /*------------------------------------------------------------------*/ int main(int argc, char **argv) { SS ss; sp_call(&ss); sleep(2); Debug(("Exitting...\n")); sleep(3); return 0; } ===================================== and here is is a makefile (use gmake for build): ===================================== Goal: bad good bad: tt.cpp $(CXX) -DBAD tt.cpp -pthread -g -o bad good: tt.cpp $(CXX) tt.cpp -pthread -g -o good ===================================== After build code, try run ./good and ./bad: ===================================== $ ./good run thread... thread ended Exitting... $ ./bad run thread... zsh: segmentation fault (core dumped) ./bad $ ===================================== Thats stranges work in FreeBSD 4.2-STABLE #0: Wed Nov 22 19:25:46 MSK 2000 and FreeBSD 5.0-CURRENT #0: Wed Nov 22 01:23:44 MSK 2000 Any idea? Make send-pr? Sergey Osokin, osa@freebsd.org.ru To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-current" in the body of the message