From e53c9fc74a3c847801e82394d6be6633b981ad76 Mon Sep 17 00:00:00 2001 From: sof Date: Mon, 4 Feb 2002 20:24:14 +0000 Subject: [PATCH] [project @ 2002-02-04 20:24:14 by sof] Factor out the task handling into separate 'module'. [Tasks represent native threads that execute STG code, with this module providing the API which the Scheduler uses to control their creation and destruction.] --- ghc/rts/Task.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ghc/rts/Task.h | 36 ++++++++++++++ 2 files changed, 186 insertions(+) create mode 100644 ghc/rts/Task.c create mode 100644 ghc/rts/Task.h diff --git a/ghc/rts/Task.c b/ghc/rts/Task.c new file mode 100644 index 0000000..80e5f69 --- /dev/null +++ b/ghc/rts/Task.c @@ -0,0 +1,150 @@ +/* ----------------------------------------------------------------------------- + * + * (c) The GHC Team 2001- + * + * The task manager subsystem. Tasks execute STG code, with this + * module providing the API which the Scheduler uses to control their + * creation and destruction. + * + * Two kinds of RTS builds uses 'tasks' - the SMP and the + * 'native thread-friendly' builds. + * + * The SMP build lets multiple tasks concurrently execute STG code, + * all sharing vital internal RTS data structures in a controlled manner. + * + * The 'threads' build has at any one time only one task executing STG + * code, other tasks are either busy executing code outside the RTS + * (e.g., a ccall) or waiting for their turn to (again) evaluate some + * STG code. A task relinquishes its RTS token when it is asked to + * evaluate an external (C) call. + * + * -------------------------------------------------------------------------*/ +#include "Rts.h" +#if defined(RTS_SUPPORTS_THREADS) /* to the end */ +#include "RtsUtils.h" +#include "OSThreads.h" +#include "Task.h" +#include "Stats.h" +#include "RtsFlags.h" + +static TaskInfo* taskTable; +static nat maxTasks; /* upper bound / the number of tasks created. */ +static nat taskCount; /* number of tasks currently created */ + + +#if defined(SMP) +void +startTaskManager( nat maxCount, void (*taskStart)(void) ) +{ + nat i; + static int initialized = 0; + + if (!initialized) { + + taskCount = 0; + maxTasks = maxCount; + /* allocate table holding task metadata */ + + if (maxCount > 0) { + taskTable = stgMallocBytes(maxCount * sizeof(TaskInfo), + "startTaskManager:tasks"); + + /* and eagerly create them all. */ + for (i = 0; i < maxCount; i++) { + startTask(taskStart); + taskCount++; + } + } + initialized = 1; + } +} +#else +void +startTaskManager( nat maxCount, void (*taskStart)(void) ) +{ + /* In the threaded case, maxCount is used to limit the + the creation of worker tasks. Tasks are created lazily, i.e., + when the current task gives up the token on executing + STG code. + */ + maxTasks = maxCount; + taskCount = 0; +} + +#endif + +void +startTask ( void (*taskStart)(void) ) +{ + int r; + OSThreadId tid; + + r = createOSThread(&tid,taskStart); + if (r != 0) { + barf("startTask: Can't create new task"); + } + +#if defined(SMP) + taskTable[taskCount].id = tid; + taskTable[taskCount].mut_time = 0.0; + taskTable[taskCount].mut_etime = 0.0; + taskTable[taskCount].gc_time = 0.0; + taskTable[taskCount].gc_etime = 0.0; + taskTable[taskCount].elapsedtimestart = stat_getElapsedTime(); +#endif + + IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Started task: %ld\n",tid);); + return; +} + +#if defined(SMP) +void +stopTaskManager () +{ + nat i; + + /* Don't want to use pthread_cancel, since we'd have to install + * these silly exception handlers (pthread_cleanup_{push,pop}) around + * all our locks. + */ +#if 0 + /* Cancel all our tasks */ + for (i = 0; i < RtsFlags.ParFlags.nNodes; i++) { + pthread_cancel(taskTable[i].id); + } + + /* Wait for all the tasks to terminate */ + for (i = 0; i < maxCount; i++) { + IF_DEBUG(scheduler,fprintf(stderr,"scheduler: waiting for task %ld\n", + taskTable[i].id)); + pthread_join(taskTable[i].id, NULL); + } +#endif + + /* Send 'em all a SIGHUP. That should shut 'em up. */ + await_death = maxCount; + for (i = 0; i < maxCount; i++) { + pthread_kill(taskTable[i].id,SIGTERM); + } + while (await_death > 0) { + sched_yield(); + } + + return; +} +#else +void +stopTaskManager () +{ + +} +#endif + +nat +getTaskCount () +{ + return taskCount; +} + + +#endif /* RTS_SUPPORTS_THREADS */ diff --git a/ghc/rts/Task.h b/ghc/rts/Task.h new file mode 100644 index 0000000..a2d0ca7 --- /dev/null +++ b/ghc/rts/Task.h @@ -0,0 +1,36 @@ +/* ----------------------------------------------------------------------------- + * + * (c) The GHC Team 2001- + * + * Types + prototypes for functions in Task.cn + * (RTS subsystem for handling OS tasks). + * + * -------------------------------------------------------------------------*/ +#ifndef __TASK_H__ +#define __TASK_H__ +#if defined(RTS_SUPPORTS_THREADS) /* to the end */ + +/* + * Tasks evaluate STG code; the TaskInfo structure collects together + * misc metadata about a task. + * + */ +typedef struct _TaskInfo { + OSThreadId id; + double elapsedtimestart; + double mut_time; + double mut_etime; + double gc_time; + double gc_etime; +} TaskInfo; + +extern TaskInfo *taskIds; + +extern void startTaskManager ( nat maxTasks, void (*taskStart)(void) ); +extern void stopTaskManager ( void ); + +extern void startTask ( void (*taskStart)(void) ); +extern nat getTaskCount( void ); + +#endif /* RTS_SUPPORTS_THREADS */ +#endif /* __TASK_H__ */ -- 1.7.10.4