X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=rts%2FTask.c;h=e77a030f39ba565eb89a0c8132ede83e6e923612;hb=9c23f06f3eb925dca063d5102b0ced4a9afe795e;hp=a9461c952776eb8dcb01643c1da2cc00fb31f392;hpb=2007d2138cf17efe6a1701510dbafdfc30e8926c;p=ghc-hetmet.git diff --git a/rts/Task.c b/rts/Task.c index a9461c9..e77a030 100644 --- a/rts/Task.c +++ b/rts/Task.c @@ -24,7 +24,7 @@ #endif // Task lists and global counters. -// Locks required: sched_mutex. +// Locks required: all_tasks_mutex. Task *all_tasks = NULL; static nat taskCount; static int tasksInitialized = 0; @@ -33,6 +33,10 @@ static void freeTask (Task *task); static Task * allocTask (void); static Task * newTask (rtsBool); +#if defined(THREADED_RTS) +static Mutex all_tasks_mutex; +#endif + /* ----------------------------------------------------------------------------- * Remembering the current thread's Task * -------------------------------------------------------------------------- */ @@ -59,9 +63,12 @@ initTaskManager (void) if (!tasksInitialized) { taskCount = 0; tasksInitialized = 1; -#if defined(THREADED_RTS) && !defined(MYTASK_USE_TLV) +#if defined(THREADED_RTS) +#if !defined(MYTASK_USE_TLV) newThreadLocalKey(¤tTaskKey); #endif + initMutex(&all_tasks_mutex); +#endif } } @@ -71,7 +78,7 @@ freeTaskManager (void) Task *task, *next; nat tasksRunning = 0; - ASSERT_LOCK_HELD(&sched_mutex); + ACQUIRE_LOCK(&all_tasks_mutex); for (task = all_tasks; task != NULL; task = next) { next = task->all_link; @@ -86,7 +93,11 @@ freeTaskManager (void) tasksRunning); all_tasks = NULL; + + RELEASE_LOCK(&all_tasks_mutex); + #if defined(THREADED_RTS) && !defined(MYTASK_USE_TLV) + closeMutex(&all_tasks_mutex); freeThreadLocalKey(¤tTaskKey); #endif @@ -177,14 +188,14 @@ newTask (rtsBool worker) task->next = NULL; - ACQUIRE_LOCK(&sched_mutex); + ACQUIRE_LOCK(&all_tasks_mutex); task->all_link = all_tasks; all_tasks = task; taskCount++; - RELEASE_LOCK(&sched_mutex); + RELEASE_LOCK(&all_tasks_mutex); return task; } @@ -259,8 +270,6 @@ newBoundTask (void) void boundTaskExiting (Task *task) { - task->stopped = rtsTrue; - #if defined(THREADED_RTS) ASSERT(osThreadId() == task->id); #endif @@ -268,6 +277,14 @@ boundTaskExiting (Task *task) endInCall(task); + // Set task->stopped, but only if this is the last call (#4850). + // Remember that we might have a worker Task that makes a foreign + // call and then a callback, so it can transform into a bound + // Task for the duration of the callback. + if (task->incall == NULL) { + task->stopped = rtsTrue; + } + debugTrace(DEBUG_sched, "task exiting"); } @@ -284,7 +301,7 @@ discardTasksExcept (Task *keep) Task *task, *next; // Wipe the task list, except the current Task. - ACQUIRE_LOCK(&sched_mutex); + ACQUIRE_LOCK(&all_tasks_mutex); for (task = all_tasks; task != NULL; task=next) { next = task->all_link; if (task != keep) { @@ -294,32 +311,37 @@ discardTasksExcept (Task *keep) } all_tasks = keep; keep->all_link = NULL; - RELEASE_LOCK(&sched_mutex); + RELEASE_LOCK(&all_tasks_mutex); } void taskTimeStamp (Task *task USED_IF_THREADS) { #if defined(THREADED_RTS) - Ticks currentElapsedTime, currentUserTime, elapsedGCTime; + Ticks currentElapsedTime, currentUserTime; currentUserTime = getThreadCPUTime(); currentElapsedTime = getProcessElapsedTime(); - // XXX this is wrong; we want elapsed GC time since the - // Task started. - elapsedGCTime = stat_getElapsedGCTime(); - - task->mut_time = + task->mut_time = currentUserTime - task->muttimestart - task->gc_time; task->mut_etime = - currentElapsedTime - task->elapsedtimestart - elapsedGCTime; + currentElapsedTime - task->elapsedtimestart - task->gc_etime; + if (task->gc_time < 0) { task->gc_time = 0; } + if (task->gc_etime < 0) { task->gc_etime = 0; } if (task->mut_time < 0) { task->mut_time = 0; } if (task->mut_etime < 0) { task->mut_etime = 0; } #endif } +void +taskDoneGC (Task *task, Ticks cpu_time, Ticks elapsed_time) +{ + task->gc_time += cpu_time; + task->gc_etime += elapsed_time; +} + #if defined(THREADED_RTS) void @@ -337,6 +359,19 @@ workerTaskStop (Task *task) #endif +#ifdef DEBUG + +static void *taskId(Task *task) +{ +#ifdef THREADED_RTS + return (void *)task->id; +#else + return (void *)task; +#endif +} + +#endif + #if defined(THREADED_RTS) static void OSThreadProcAttr @@ -398,19 +433,19 @@ startWorkerTask (Capability *cap) RELEASE_LOCK(&task->lock); } +void +interruptWorkerTask (Task *task) +{ + ASSERT(osThreadId() != task->id); // seppuku not allowed + ASSERT(task->incall->suspended_tso); // use this only for FFI calls + interruptOSThread(task->id); + debugTrace(DEBUG_sched, "interrupted worker task %p", taskId(task)); +} + #endif /* THREADED_RTS */ #ifdef DEBUG -static void *taskId(Task *task) -{ -#ifdef THREADED_RTS - return (void *)task->id; -#else - return (void *)task; -#endif -} - void printAllTasks(void); void