/* Function binds a given TID to any thread of core 0 */ int do_the_bind_thread(pthread_t tid) { int lcpu, rc = 0; lcpu = get_logical_cpu_num(0, 0, 0, bind_th_num); /* Bind to N0P0C0T* */ rc = bind_thread(tid, lcpu, -1); bind_th_num = (bind_th_num + 1) % smt; return rc; }
void HostInternal::driver( const size_t thread_rank ) { // Bind this thread to a unique processing unit // with all members of a gang in the same NUMA region. if ( bind_thread( thread_rank ) ) { HostThread this_thread ; m_thread[ thread_rank ] = & this_thread ; // Initialize thread ranks and fan-in relationships: if ( initialize_thread( thread_rank , this_thread ) ) { // Inform master thread that binding and initialization succeeded. m_master_thread.set( HostThread::ThreadActive ); try { // Work loop: while ( HostThread::ThreadActive == this_thread.m_state ) { // When the work is complete the state will be Inactive or Terminate m_worker->execute_on_thread( this_thread ); // If this_thread is in the Inactive state then wait for activation. this_thread.wait( HostThread::ThreadInactive ); } } catch( const std::exception & x ) { // mfh 29 May 2012: Doesn't calling std::terminate() seem a // little violent? On the other hand, C++ doesn't define how // to transport exceptions between threads (until C++11). // Since this is a worker thread, it would be hard to tell the // master thread what happened. std::cerr << "Thread " << thread_rank << " uncaught exception : " << x.what() << std::endl ; std::terminate(); } catch( ... ) { // mfh 29 May 2012: See note above on std::terminate(). std::cerr << "Thread " << thread_rank << " uncaught exception" << std::endl ; std::terminate(); } } } // Notify master thread that this thread has terminated. m_thread[ thread_rank ] = 0 ; m_master_thread.set( HostThread::ThreadTerminating ); }
bool HostInternal::spawn_threads( const unsigned gang_count , const unsigned worker_count ) { // If the process is bound to a particular node // then only use cores belonging to that node. // Otherwise use all nodes and all their cores. m_gang_count = gang_count ; m_worker_count = worker_count ; m_thread_count = gang_count * worker_count ; m_worker = & m_worker_block ; // Bind the process thread as thread_rank == 0 bool ok_spawn_threads = bind_thread( 0 ); // Spawn threads from last-to-first so that the // fan-in barrier thread relationships can be established. for ( unsigned rank = m_thread_count ; ok_spawn_threads && 0 < --rank ; ) { m_master_thread.set( HostThread::ThreadInactive ); // Spawn thread executing the 'driver' function. ok_spawn_threads = spawn( rank ); if ( ok_spawn_threads ) { // Thread spawned, wait for thread to activate: m_master_thread.wait( HostThread::ThreadInactive ); // Check if the thread initialized and bound correctly: ok_spawn_threads = HostThread::ThreadActive == m_master_thread.m_state ; if ( ok_spawn_threads ) { // Wait for spawned thread to deactivate HostThread * volatile * const threads = m_thread ; threads[ rank ]->wait( HostThread::ThreadActive ); // m_thread[ rank ]->wait( HostThread::ThreadActive ); } } } m_worker = NULL ; // All threads spawned, initialize the master-thread fan-in ok_spawn_threads = ok_spawn_threads && initialize_thread( 0 , m_master_thread ); if ( ! ok_spawn_threads ) { finalize(); } return ok_spawn_threads ; }
PRIVATE L4_msg_tag Irq_sender::sys_attach(L4_msg_tag const &tag, Utcb const *utcb, Syscall_frame * /*f*/, Obj_space *o_space) { L4_snd_item_iter snd_items(utcb, tag.words()); Thread *thread = 0; if (tag.items() == 0) { // detach Reap_list rl; free(_irq_thread, rl.list()); _irq_id = ~0UL; cpu_lock.clear(); rl.del(); cpu_lock.lock(); return commit_result(0); } if (tag.items() && snd_items.next()) { L4_fpage bind_thread(snd_items.get()->d); if (EXPECT_FALSE(!bind_thread.is_objpage())) return commit_error(utcb, L4_error::Overflow); thread = Kobject::dcast<Thread_object*>(o_space->lookup_local(bind_thread.obj_index())); } if (!thread) thread = current_thread(); if (alloc(thread)) { _irq_id = utcb->values[1]; return commit_result(0); } return commit_result(-L4_err::EInval); }
PUBLIC L4_msg_tag Ipc_gate_ctl::kinvoke(L4_obj_ref self, L4_fpage::Rights rights, Syscall_frame *f, Utcb const *in, Utcb *out) { L4_msg_tag tag = f->tag(); if (EXPECT_FALSE(tag.proto() != L4_msg_tag::Label_kobject)) return commit_result(-L4_err::EBadproto); if (EXPECT_FALSE(tag.words() < 1)) return commit_result(-L4_err::EInval); switch (in->values[0]) { case Op_bind: return bind_thread(self, rights, f, in, out); case Op_get_info: return get_infos(self, rights, f, in, out); default: return static_cast<Ipc_gate_obj*>(this)->kobject_invoke(self, rights, f, in, out); } }