if(val && d_waitstatus==Answer)
*val=d_waitval;
d_tid=w.tid;
+ if((char*)&w < d_threads[d_tid].highestStackSeen) {
+ d_threads[d_tid].highestStackSeen = (char*)&w;
+ }
key=d_eventkey;
return d_waitstatus;
}
template<class Key, class Val>void MTasker<Key,Val>::yield()
{
d_runQueue.push(d_tid);
- if(swapcontext(d_threads[d_tid] ,&d_kernel) < 0) { // give control to the kernel
+ if(swapcontext(d_threads[d_tid].context ,&d_kernel) < 0) { // give control to the kernel
perror("swapcontext in yield");
exit(EXIT_FAILURE);
}
makecontext (uc, (void (*)(void))threadWrapper, 6, thispair.first, thispair.second, start, d_maxtid, valpair.first, valpair.second);
- d_threads[d_maxtid]=uc;
+ d_threads[d_maxtid].context = uc;
d_runQueue.push(d_maxtid++); // will run at next schedule invocation
}
{
if(!d_runQueue.empty()) {
d_tid=d_runQueue.front();
- if(swapcontext(&d_kernel, d_threads[d_tid])) {
+ if(swapcontext(&d_kernel, d_threads[d_tid].context)) {
perror("swapcontext in schedule");
exit(EXIT_FAILURE);
}
return true;
}
if(!d_zombiesQueue.empty()) {
- delete[] (char *)d_threads[d_zombiesQueue.front()]->uc_stack.ss_sp;
- delete d_threads[d_zombiesQueue.front()];
+ delete[] (char *)d_threads[d_zombiesQueue.front()].context->uc_stack.ss_sp;
+ delete d_threads[d_zombiesQueue.front()].context;
d_threads.erase(d_zombiesQueue.front());
d_zombiesQueue.pop();
return true;
}
}
-
template<class Key, class Val>void MTasker<Key,Val>::threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2)
{
void* val = joinPtr(val1, val2);
MTasker* self = (MTasker*) joinPtr(self1, self2);
+ self->d_threads[self->d_tid].startOfStack = self->d_threads[self->d_tid].highestStackSeen = (char*)&val;
(*tf)(val);
self->d_zombiesQueue.push(tid);
{
return d_tid;
}
+
+
+//! Returns the maximum stack usage so far of this MThread
+template<class Key, class Val>unsigned int MTasker<Key,Val>::getMaxStackUsage()
+{
+ return d_threads[d_tid].startOfStack - d_threads[d_tid].highestStackSeen;
+}
std::queue<int> d_runQueue;
std::queue<int> d_zombiesQueue;
+ struct ThreadInfo
+ {
+ ucontext_t* context;
+ char* startOfStack;
+ char* highestStackSeen;
+ };
- typedef std::map<int, ucontext_t*> mthreads_t;
+ typedef std::map<int, ThreadInfo> mthreads_t;
mthreads_t d_threads;
int d_tid;
int d_maxtid;
EventKey key;
ucontext_t *context;
struct timeval ttd;
- int tid;
+ int tid;
};
typedef multi_index_container<
bool noProcesses();
unsigned int numProcesses();
int getTid();
+ unsigned int getMaxStackUsage();
private:
static void threadWrapper(uint32_t self1, uint32_t self2, tfunc_t *tf, int tid, uint32_t val1, uint32_t val2);
addGetStat("over-capacity-drops", &g_stats.overCapacityDrops);
addGetStat("no-packet-error", &g_stats.noPacketError);
addGetStat("dlg-only-drops", &SyncRes::s_nodelegated);
+ addGetStat("max-mthread-stack", &g_stats.maxMThreadStackUsage);
addGetStat("negcache-entries", boost::bind(getNegCacheSize));
addGetStat("throttle-entries", boost::bind(getThrottleSize));