[project @ 2002-02-04 20:24:14 by sof]
authorsof <unknown>
Mon, 4 Feb 2002 20:24:14 +0000 (20:24 +0000)
committersof <unknown>
Mon, 4 Feb 2002 20:24:14 +0000 (20:24 +0000)
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 [new file with mode: 0644]
ghc/rts/Task.h [new file with mode: 0644]

diff --git a/ghc/rts/Task.c b/ghc/rts/Task.c
new file mode 100644 (file)
index 0000000..80e5f69
--- /dev/null
@@ -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 (file)
index 0000000..a2d0ca7
--- /dev/null
@@ -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__ */