[project @ 2003-12-16 13:19:01 by simonmar]
[ghc-hetmet.git] / ghc / rts / Task.c
index 19ae799..6579abc 100644 (file)
@@ -27,6 +27,7 @@
 #include "Task.h"
 #include "Stats.h"
 #include "RtsFlags.h"
+#include "Schedule.h"
 
 /* There's not all that much code that is shared between the
  * SMP and threads version of the 'task manager.' A sign
@@ -44,8 +45,6 @@ static TaskInfo* taskTable;
 static nat maxTasks;  
 /* number of tasks currently created */
 static nat taskCount; 
-static nat tasksAvailable;
-
 
 #if defined(SMP)
 void
@@ -100,6 +99,7 @@ void
 stopTaskManager ()
 {
   nat i;
+  OSThreadId tid = osThreadId();
 
   /* Don't want to use pthread_cancel, since we'd have to install
    * these silly exception handlers (pthread_cleanup_{push,pop}) around
@@ -120,9 +120,12 @@ stopTaskManager ()
 #endif
 
   /* Send 'em all a SIGHUP.  That should shut 'em up. */
-  await_death = maxCount;
+  await_death = maxCount - 1;
   for (i = 0; i < maxCount; i++) {
-    pthread_kill(taskTable[i].id,SIGTERM);
+    /* don't cancel the thread running this piece of code. */
+    if ( taskTable[i].id != tid ) {
+      pthread_kill(taskTable[i].id,SIGTERM);
+    }
   }
   while (await_death > 0) {
     sched_yield();
@@ -131,11 +134,18 @@ stopTaskManager ()
   return;
 }
 
+void
+resetTaskManagerAfterFork ()
+{
+       barf("resetTaskManagerAfterFork not implemented for SMP");
+}
+
 #else
 /************ THREADS version *****************/
 
 void
-startTaskManager( nat maxCount, void (*taskStart)(void) )
+startTaskManager( nat maxCount,
+                 void (*taskStart)(void) STG_UNUSED )
 {
   /* In the threaded case, maxCount is used to limit the
      the creation of worker tasks. Tasks are created lazily, i.e.,
@@ -144,7 +154,6 @@ startTaskManager( nat maxCount, void (*taskStart)(void) )
   */
   maxTasks = maxCount;
   taskCount = 0;
-  tasksAvailable = 0;
 }
 
 void
@@ -153,12 +162,15 @@ startTask ( void (*taskStart)(void) )
   int r;
   OSThreadId tid;
   
-  /* Locks assumed: rts_mutex */
-  
-  /* If there are threads known to be waiting to do
-     useful work, no need to create a new task. */
-  if (tasksAvailable > 0) {
-    IF_DEBUG(scheduler,fprintf(stderr,"scheduler: startTask: %d tasks available, not creating new one.\n",tasksAvailable););
+  /* If more than one worker thread is known to be blocked waiting
+     on thread_ready_cond, don't create a new one.
+  */
+  if ( rts_n_waiting_tasks > 0) {
+    IF_DEBUG(scheduler,fprintf(stderr,
+                              "scheduler: startTask: %d tasks waiting, not creating new one.\n", 
+                              rts_n_waiting_tasks););
+    // the task will run as soon as a capability is available,
+    // so there's no need to wake it.
     return;
   }
 
@@ -174,51 +186,8 @@ startTask ( void (*taskStart)(void) )
     barf("startTask: Can't create new task");
   }
   taskCount++;
-  tasksAvailable++;
-
-  IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Started task (%d): %ld\n", taskCount, tid););
-  return;
-}
-
-/*
- *   When the RTS thread ends up performing a call-out, 
- *   we need to know whether there'll be other tasks/threads
- *   to take over RTS responsibilities. The 'tasksAvailable'
- *   variable holds the number of threads that are _blocked
- *   waiting to enter the RTS_ (or soon will be). Equipped
- *   with that count, startTask() is able to make an informed
- *   decision on whether or not to create a new thread.
- * 
- *   Two functions control increments / decrements of
- *   'tasksAvailable':
- *   
- *      - taskNotAvailable() : called whenever a task/thread
- *        has acquired the RTS lock, i.e., always called by
- *        a thread that holds the rts_mutex lock.
- *
- *      - taskAvailable():     called whenever a task/thread
- *        is about to try to grab the RTS lock. The task manager
- *        and scheduler will only call this whenever it is 
- *        in possession of the rts_mutex lock, i.e.,
- *             - when a new task is created in startTask().
- *             - when the scheduler gives up the RTS token to
- *               let threads waiting to return from an external
- *               call continue.
- * 
- */
-void
-taskNotAvailable()
-{
-  if (tasksAvailable > 0) {
-    tasksAvailable--;
-  }
-  return;
-}
 
-void
-taskAvailable()
-{
-  tasksAvailable++;
+  IF_DEBUG(scheduler,fprintf(stderr,"scheduler: startTask: new task %ld (total_count: %d; waiting: %d)\n", tid, taskCount, rts_n_waiting_tasks););
   return;
 }
 
@@ -229,14 +198,14 @@ stopTaskManager ()
 {
 
 }
-#endif
 
-
-nat
-getTaskCount ()
+void
+resetTaskManagerAfterFork ( void )
 {
-  return taskCount;
+       rts_n_waiting_tasks = 0;
+       taskCount = 0;
 }
+#endif
 
 
 #endif /* RTS_SUPPORTS_THREADS */