Date: Fri, 24 Nov 2000 22:03:04 +0300 From: Sergey Osokin <osa@freebsd.org.ru> To: freebsd-current@FreeBSD.org Cc: freebsd-stable@FreeBSD.org Subject: stranges in threads implementation... possible bug? Message-ID: <20001124220303.A1027@freebsd.org.ru>
next in thread | raw e-mail | index | archive | help
Hello!
My friend find some stranges in FreeBSD threads implementation...
Here is a "special" code:
=====================================
#include <stdio.h>
#include <assert.h>
#include <string>
#include <pthread.h>
#include <unistd.h>
#include <errno.h>
#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-stable" in the body of the message
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20001124220303.A1027>
