static void thread_unblock_mutex(ThreadId tid, struct mutex *mx, const Char *action) { struct thread *th = thread_get(tid); if (th == NULL) { /* should an unknown thread doing something make it spring to life? */ thread_report(tid, THE_NotExist, "giving up on mutex"); return; } switch(th->state) { case TS_MutexBlocked: /* OK */ break; case TS_Alive: case TS_Running: thread_report(tid, THE_NotBlocked, action); break; case TS_CVBlocked: case TS_JoinBlocked: thread_report(tid, THE_Blocked, action); break; case TS_Dead: case TS_Zombie: thread_report(tid, THE_NotAlive, action); break; } do_thread_run(th); }
static void thread_block_mutex(ThreadId tid, struct mutex *mx) { struct thread *th = thread_get(tid); if (th == NULL) { /* should an unknown thread doing something make it spring to life? */ thread_report(tid, THE_NotExist, "blocking on mutex"); return; } switch(th->state) { case TS_Dead: case TS_Zombie: thread_report(th->tid, THE_NotAlive, "blocking on mutex"); break; case TS_MutexBlocked: case TS_CVBlocked: case TS_JoinBlocked: thread_report(th->tid, THE_Blocked, "blocking on mutex"); break; case TS_Alive: case TS_Running: /* OK */ break; } do_thread_block_mutex(th, mx); }
/* Finish unlocking a Mutex. The mutex can validly be in one of three states: - Unlocking - Locked, owned by someone else (someone else got it in the meantime) - Free (someone else completed a lock-unlock cycle) */ void VG_(tm_mutex_unlock)(ThreadId tid, Addr mutexp) { struct mutex *mx; struct thread *th; mx = mutex_check_initialized(tid, mutexp, "unlocking mutex"); th = thread_get(tid); if (th == NULL) thread_report(tid, THE_NotExist, "unlocking mutex"); else { switch(th->state) { case TS_Alive: case TS_Running: /* OK */ break; case TS_Dead: case TS_Zombie: thread_report(tid, THE_NotAlive, "unlocking mutex"); break; case TS_JoinBlocked: case TS_CVBlocked: case TS_MutexBlocked: thread_report(tid, THE_Blocked, "unlocking mutex"); do_thread_run(th); break; } } switch(mx->state) { case MX_Locked: /* Someone else might have taken ownership in the meantime */ if (mx->owner == tid) mutex_report(tid, mutexp, MXE_Locked, "unlocking"); break; case MX_Free: /* OK - nothing to do */ break; case MX_Unlocking: /* OK - we need to complete the unlock */ VG_TRACK( post_mutex_unlock, tid, (void *)mutexp ); mutex_setstate(tid, mx, MX_Free); break; case MX_Init: case MX_Dead: vg_assert(0); } }
/* Try unlocking a lock. This will move it into a state where it can either be unlocked, or change ownership to another thread. If unlock fails, it will remain locked. */ void VG_(tm_mutex_tryunlock)(ThreadId tid, Addr mutexp) { struct thread *th; struct mutex *mx; mx = mutex_check_initialized(tid, mutexp, "try-unlocking"); th = thread_get(tid); if (th == NULL) thread_report(tid, THE_NotExist, "try-unlocking mutex"); else { switch(th->state) { case TS_Alive: case TS_Running: /* OK */ break; case TS_Dead: case TS_Zombie: thread_report(tid, THE_NotAlive, "try-unlocking mutex"); break; case TS_JoinBlocked: case TS_CVBlocked: case TS_MutexBlocked: thread_report(tid, THE_Blocked, "try-unlocking mutex"); do_thread_run(th); break; } } switch(mx->state) { case MX_Locked: if (mx->owner != tid) mutex_report(tid, mutexp, MXE_NotOwner, "try-unlocking"); break; case MX_Free: mutex_report(tid, mutexp, MXE_NotLocked, "try-unlocking"); break; case MX_Unlocking: mutex_report(tid, mutexp, MXE_NotLocked, "try-unlocking"); break; case MX_Init: case MX_Dead: vg_assert(0); } mutex_setstate(tid, mx, MX_Unlocking); }
void VG_(tm_thread_detach)(ThreadId tid) { struct thread *th = thread_get(tid); if (th == NULL) thread_report(tid, THE_NotExist, "detaching"); else { if (th->detached) thread_report(tid, THE_Detached, "detaching"); else { /* XXX look for waiters */ th->detached = True; } } }
/* A thread is terminating itself - fails if tid has already terminated - if detached, tid becomes invalid for all further operations - if not detached, the thread remains in a Zombie state until someone joins on it */ void VG_(tm_thread_exit)(ThreadId tid) { struct thread *th = thread_get(tid); if (th == NULL) thread_report(tid, THE_NotExist, "exiting"); else { struct thread *joiner; switch(th->state) { case TS_Dead: case TS_Zombie: /* already exited once */ thread_report(tid, THE_NotAlive, "exiting"); break; case TS_MutexBlocked: case TS_CVBlocked: case TS_JoinBlocked: thread_report(tid, THE_Blocked, "exiting"); break; case TS_Alive: case TS_Running: /* OK */ break; } /* ugly - walk all threads to find people joining with us */ /* In pthreads its an error to have multiple joiners, but that seems a bit specific to implement here; there should a way for the thread library binding to handle this. */ VG_(OSet_ResetIter)(threadSet); while ((joiner = VG_(OSet_Next)(threadSet)) != NULL) { if (joiner->state == TS_JoinBlocked && joiner->th_blocked == th) { /* found someone - wake them up */ do_thread_run(joiner); /* we're dead */ do_thread_dead(th); } } if (th->state != TS_Dead) do_thread_block_zombie(th); } }
/* Thread creation */ void VG_(tm_thread_create)(ThreadId creator, ThreadId tid, Bool detached) { struct thread *th = thread_get(tid); if (debug_thread) VG_(printf)("thread %d creates %d %s\n", creator, tid, detached ? "detached" : ""); if (th != NULL) { if (th->state != TS_Dead) thread_report(tid, THE_Rebirth, "creating"); } else { th = VG_(OSet_AllocNode)(threadSet, sizeof(struct thread)); th->tid = tid; VG_(OSet_Insert)(threadSet, th); } th->creator = creator; th->detached = detached; th->mx_blocked = NULL; th->cv_blocked = NULL; th->th_blocked = NULL; thread_setstate(th, TS_Alive); do_thread_run(th); }
void threadProcess( std::string iFileDir, std::string oFileDir, FIFO<int>& module_list, int threadID) { while(1) { // get next module for process or exit if done. int module_number; try { module_number = module_list.pop(); std:: stringstream report; report << "Stating module " << module_number; thread_report(report.str(),threadID); }catch(std::string i) { thread_report("Terminating",threadID); return; } std::array<FIFO<std::string>,12> asicData; //stores the data from the asic asicData[asicID][SPP] FIFO<std::string> side1, side2; for(int i(0); i < 12; i++) { std::stringstream filename; filename << iFileDir << "/timesync" << module_number*12 + i << ".txt"; std::ifstream iFile(filename.str()); std::string tempIn; while(iFile >> tempIn) { if (atoi(tempIn.c_str()) == 0) continue; asicData[i].store(tempIn); } } bool complete = false; bool next_bcid = true; int bcid = 0; while(!complete) { for (int i(0); i < 12; i++) if(!asicData[i].is_empty()){ if(get_bcid(asicData[i].peek()) == bcid){ if (i < 3 || i >= 9) side1.store(asicData[i].pop()); else side2.store(asicData[i].pop()); next_bcid = false; } } complete = true; for (auto& asic : asicData) if (!asic.is_empty()) complete = false; if (next_bcid) if (++bcid >= 512) bcid = 0; next_bcid = true; } std::stringstream outFileName1; outFileName1 << oFileDir << "/module_" << module_number << "_"; std::stringstream outFileName2; outFileName2 << outFileName1.str(); //shits and giggles outFileName1 << 1 << ".txt"; outFileName2 << 2 << ".txt"; std::ofstream oFile1(outFileName1.str()); std::ofstream oFile2(outFileName2.str()); thread_report("Writing to file",threadID); while(!side1.is_empty()) oFile1 << side1.pop() << '\n'; while(!side2.is_empty()) oFile2 << side2.pop() << '\n'; } }
/* One thread blocks until another has terminated - fails if joinee is detached - fails if joinee doesn't exist - once the join completes, joinee is dead */ void VG_(tm_thread_join)(ThreadId joinerid, ThreadId joineeid) { struct thread *joiner = thread_get(joinerid); struct thread *joinee = thread_get(joineeid); /* First, check the joinee thread's state */ if (joinee == NULL) thread_report(joineeid, THE_NotExist, "joining as joinee"); else { switch(joinee->state) { case TS_Alive: /* really shouldn't see them in this state... */ case TS_Running: case TS_Zombie: case TS_MutexBlocked: case TS_CVBlocked: case TS_JoinBlocked: /* OK */ break; case TS_Dead: thread_report(joineeid, THE_NotAlive, "joining as joinee"); break; } } /* now the joiner... */ if (joiner == NULL) thread_report(joineeid, THE_NotExist, "joining as joiner"); else { switch(joiner->state) { case TS_Alive: /* ? */ case TS_Running: /* OK */ break; case TS_Zombie: /* back from the dead */ case TS_Dead: thread_report(joineeid, THE_NotAlive, "joining as joiner"); break; case TS_MutexBlocked: case TS_CVBlocked: case TS_JoinBlocked: thread_report(joineeid, THE_Blocked, "joining as joiner"); break; } if (joinee->detached) thread_report(joineeid, THE_Detached, "joining as joiner"); else { /* block if the joinee hasn't exited yet */ if (joinee) { switch(joinee->state) { case TS_Dead: break; default: if (joinee->state == TS_Zombie) do_thread_dead(joinee); else do_thread_block_join(joiner, joinee); } } } } }