1 /* -----------------------------------------------------------------------------
3 * (c) The GHC Team 2001-
5 * The task manager subsystem. Tasks execute STG code, with this
6 * module providing the API which the Scheduler uses to control their
7 * creation and destruction.
9 * Two kinds of RTS builds uses 'tasks' - the SMP and the
10 * 'native thread-friendly' builds.
12 * The SMP build lets multiple tasks concurrently execute STG code,
13 * all sharing vital internal RTS data structures in a controlled manner.
15 * The 'threads' build has at any one time only one task executing STG
16 * code, other tasks are either busy executing code outside the RTS
17 * (e.g., a ccall) or waiting for their turn to (again) evaluate some
18 * STG code. A task relinquishes its RTS token when it is asked to
19 * evaluate an external (C) call.
21 * -------------------------------------------------------------------------*/
23 #if defined(RTS_SUPPORTS_THREADS) /* to the end */
25 #include "OSThreads.h"
30 static TaskInfo* taskTable;
31 static nat maxTasks; /* upper bound / the number of tasks created. */
32 static nat taskCount; /* number of tasks currently created */
37 startTaskManager( nat maxCount, void (*taskStart)(void) )
40 static int initialized = 0;
46 /* allocate table holding task metadata */
49 taskTable = stgMallocBytes(maxCount * sizeof(TaskInfo),
50 "startTaskManager:tasks");
52 /* and eagerly create them all. */
53 for (i = 0; i < maxCount; i++) {
63 startTaskManager( nat maxCount, void (*taskStart)(void) )
65 /* In the threaded case, maxCount is used to limit the
66 the creation of worker tasks. Tasks are created lazily, i.e.,
67 when the current task gives up the token on executing
77 startTask ( void (*taskStart)(void) )
82 r = createOSThread(&tid,taskStart);
84 barf("startTask: Can't create new task");
88 taskTable[taskCount].id = tid;
89 taskTable[taskCount].mut_time = 0.0;
90 taskTable[taskCount].mut_etime = 0.0;
91 taskTable[taskCount].gc_time = 0.0;
92 taskTable[taskCount].gc_etime = 0.0;
93 taskTable[taskCount].elapsedtimestart = stat_getElapsedTime();
96 IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Started task: %ld\n",tid););
106 /* Don't want to use pthread_cancel, since we'd have to install
107 * these silly exception handlers (pthread_cleanup_{push,pop}) around
111 /* Cancel all our tasks */
112 for (i = 0; i < RtsFlags.ParFlags.nNodes; i++) {
113 pthread_cancel(taskTable[i].id);
116 /* Wait for all the tasks to terminate */
117 for (i = 0; i < maxCount; i++) {
118 IF_DEBUG(scheduler,fprintf(stderr,"scheduler: waiting for task %ld\n",
120 pthread_join(taskTable[i].id, NULL);
124 /* Send 'em all a SIGHUP. That should shut 'em up. */
125 await_death = maxCount;
126 for (i = 0; i < maxCount; i++) {
127 pthread_kill(taskTable[i].id,SIGTERM);
129 while (await_death > 0) {
150 #endif /* RTS_SUPPORTS_THREADS */