void pong_thread_t::run() { int i; int self = id; { CRITICAL_SECTION(cs, game.theBall); for(i=0; i<PongTimes; ++i){ while(game.whoseShot != self){ DO_PTHREAD(pthread_cond_wait(&game.paddle[self], &game.theBall)); } game.whoseShot = 1-self; DO_PTHREAD(pthread_cond_signal(&game.paddle[1-self])); } } // OUT.form("pong(%#lx) id=%d done\n", (long)this, id); note.done(); if (DumpInThreads) { OUT << *this << endl; FLUSHOUT; } }
static inline void sem_post(sthread_core_t::sem_t *sem) { DO_PTHREAD(pthread_mutex_lock(&sem->lock)); sem->count++; if (sem->count > 0) DO_PTHREAD(pthread_cond_signal(&sem->wake)); DO_PTHREAD(pthread_mutex_unlock(&sem->lock)); }
static inline void sem_wait(sthread_core_t::sem_t *sem) { DO_PTHREAD(pthread_mutex_lock(&sem->lock)); while (sem->count <= 0) DO_PTHREAD(pthread_cond_wait(&sem->wake, &sem->lock)); sem->count--; DO_PTHREAD(pthread_mutex_unlock(&sem->lock)); }
sthread_t::sthread_t(priority_t pr, const char *nm, unsigned stack_size) : sthread_named_base_t(nm), user(0), id(_next_id++), // make it match the gdb threads #. Origin 1 _start_terminate_lock(new pthread_mutex_t), _start_cond(new pthread_cond_t), _sleeping(false), _forked(false), _terminated(false), _unblock_flag(false), _core(0), _status(t_virgin), _priority(pr), _rce(stOK) { if(!_start_terminate_lock || !_start_cond ) W_FATAL(fcOUTOFMEMORY); DO_PTHREAD(pthread_cond_init(_start_cond, NULL)); DO_PTHREAD(pthread_mutex_init(_start_terminate_lock, NULL)); _core = new sthread_core_t; if (!_core) W_FATAL(fcOUTOFMEMORY); _core->sthread = (void *)this; // not necessary, but might // be useful for debugging /* * Set a valid priority level */ if (_priority > max_priority) _priority = max_priority; else if (_priority <= min_priority) _priority = min_priority; /* * Initialize the core. */ DO_PTHREAD(pthread_mutex_init(&_wait_lock, NULL)); DO_PTHREAD(pthread_cond_init(&_wait_cond, NULL)); /* * stash the procedure (sthread_t::_start) * and arg (this) * in the core structure, along with * status info. * and if this is not the _main_thread (running in * the system thread, i.e., in an already-running pthread) * then create a pthread for it and give it a starting function // TODO: should probably merge sthread_core_pthread.cpp in here */ if (sthread_core_init(_core, __start, this, stack_size) == -1) { cerr << "sthread_t: cannot initialize thread core" << endl; W_FATAL(stINTERNAL); } }
void bf_prefetch_thread_t::_init(int i) { FUNC(bf_prefetch_thread_t::init); DBGTHRD("initializing "); _info = new struct frame_info[i]; // deleted in ~bf_prefetch_thread_t DO_PTHREAD(pthread_cond_init(&_activate, NULL)); DO_PTHREAD(pthread_mutex_init(&_prefetch_mutex, NULL)); }
static int sem_init(sthread_core_t::sem_t *sem, int, int count) { /* XXX could bitch if shared was true, but it is just for local compatability */ sem->count = count; DO_PTHREAD(pthread_mutex_init(&sem->lock, NULL)); DO_PTHREAD(pthread_cond_init(&sem->wake, NULL)); return 0; }
void wait_for_t::wait() { CRITICAL_SECTION(cs, _lock); while (have < expected) { DO_PTHREAD(pthread_cond_wait(&_done, &_lock)); } }
w_rc_t sthread_t::fork() { { sthread_init_t::do_init(); CRITICAL_SECTION(cs, _start_terminate_lock); /* can only fork a new thread */ if (_forked) return RC(stOS); /* Add us to the list of threads, unless we are the main thread */ if(this != _main_thread) { CRITICAL_SECTION(cs, _class_list_lock); _class_list->append(this); } _forked = true; if(this == _main_thread) { // happens at global constructor time CRITICAL_SECTION(cs_thread, _wait_lock); _status = t_running; } else { // happens after main() called DO_PTHREAD( pthread_cond_signal(_start_cond) ); } } return RCOK; }
void wait_for_t::done() { CRITICAL_SECTION(cs, _lock); have++; if (have >= expected) { DO_PTHREAD(pthread_cond_signal(&_done)); } }
void occ_rwlock::acquire_write() { // only one writer allowed in at a time... CRITICAL_SECTION(cs, _read_write_mutex); while(*&_active_count & WRITER) { DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex)); } // any lurking writers are waiting on the cond var int count = atomic_add_32_nv(&_active_count, WRITER); w_assert1(count & WRITER); // drain readers while(count != WRITER) { DO_PTHREAD(pthread_cond_wait(&_write_cond, &_read_write_mutex)); count = *&_active_count; } }
NORET bf_prefetch_thread_t:: ~bf_prefetch_thread_t() { FUNC(bf_prefetch_thread_t::~bf_prefetch_thread_t); if(_info) { CRITICAL_SECTION(cs, _prefetch_mutex); int j; for(j=0; j<_n; j++) { new_state(j, pf_destructor); } cs.exit(); delete[] _info; _info = 0; } DO_PTHREAD(pthread_mutex_destroy(&_prefetch_mutex)); DO_PTHREAD(pthread_cond_destroy(&_activate)); }
sthread_t::~sthread_t() { /* fprintf(stderr, "sthread_t %s destructed, this %p core %p pthread %p\n", name(), this, _core, (void *)myself()); fflush(stderr); */ { CRITICAL_SECTION(cs, _wait_lock); /* Valid states for destroying a thread are ... 1) It was never started 2) It ended. 3) There is some braindamage in that that blocked threads can be deleted. This is sick and wrong, and it can cause race conditions. It is enabled for compatibility, and hopefully the warning messages will tell you if something is wrong. */ w_assert1(_status == t_virgin || _status == t_defunct || _status == t_blocked ); if (_link.member_of()) { W_FORM2(cerr,("sthread_t(%#lx): \"%s\": destroying a thread on a list!", (long)this, name())); } } sthread_core_exit(_core, _terminated); delete _core; _core = 0; DO_PTHREAD(pthread_cond_destroy(_start_cond)); delete _start_cond; _start_cond = 0; DO_PTHREAD(pthread_mutex_destroy(_start_terminate_lock)); delete _start_terminate_lock; _start_terminate_lock = 0; // clean up for valgrind }
void occ_rwlock::acquire_read() { int count = atomic_add_32_nv(&_active_count, READER); while(count & WRITER) { // block count = atomic_add_32_nv(&_active_count, -READER); { CRITICAL_SECTION(cs, _read_write_mutex); // nasty race: we could have fooled a writer into sleeping... if(count == WRITER) DO_PTHREAD(pthread_cond_signal(&_write_cond)); while(*&_active_count & WRITER) { DO_PTHREAD(pthread_cond_wait(&_read_cond, &_read_write_mutex)); } } count = atomic_add_32_nv(&_active_count, READER); } membar_enter(); }
w_rc_t bf_prefetch_thread_t::request( const lpid_t& pid, latch_mode_t mode ) { FUNC(bf_prefetch_thread_t::request); w_assert3(mode != LATCH_NL); // MUST latch the page CRITICAL_SECTION(cs, _prefetch_mutex); if(get_error()) { w_rc_t rc(_fix_error.delegate()); return rc; } int i = _f; bf_prefetch_thread_t::frame_info &inf = _info[i]; DBGTHRD(<<"request! i=" << i << " pid " << pid << " mode " << int(mode) << " old status " << int(inf._status) ); w_assert3(inf._status == pf_init); // There should always be one available -- at least // when used with scan TODO -- make more general INC_TSTAT(bf_prefetch_requests); /* Assert that we haven't got a frame read from disk * and never used (fetched) */ inf._pid = pid; inf._mode = mode; new_state(i, pf_request); w_assert3(inf._status == pf_requested); cs.exit(); DBGTHRD(<< "released mutex; signalling..."); DO_PTHREAD(pthread_cond_signal(&_activate)); DBGTHRD(<< "returning from request"); return _fix_error; }
void bf_prefetch_thread_t::retire() { FUNC(bf_prefetch_thread_t::retire); { CRITICAL_SECTION(cs, _prefetch_mutex); _retire = true; } // end critical section w_assert3( me() != this ); w_rc_t e; for (;;) { /* keep hosing the thread until it dies */ /* XXX This is bogus. telling it to shutdown and waiting should be enough. */ DO_PTHREAD(pthread_cond_signal(&_activate)); e = join(1000); if (!e.is_error()) break; else if (e.err_num() != smthread_t::stTIMEOUT) W_COERCE(e); } }
static void sem_destroy(sthread_core_t::sem_t *sem) { DO_PTHREAD(pthread_mutex_destroy(&sem->lock)); DO_PTHREAD(pthread_cond_destroy(&sem->wake)); }
wait_for_t(int expecting) : expected(expecting), have(0) { DO_PTHREAD(pthread_mutex_init(&_lock, NULL)); DO_PTHREAD(pthread_cond_init(&_done, NULL)); }
ping_pong_t() : whoseShot(0), ping(0), pong(0) { DO_PTHREAD(pthread_mutex_init(&theBall, NULL)); DO_PTHREAD(pthread_cond_init(&paddle[0], NULL)); DO_PTHREAD(pthread_cond_init(&paddle[1], NULL)); }