* '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.
+ * all sharing vital internal RTS data structures in a controlled manner
+ * (see details elsewhere...ToDo: fill in ref!)
*
* 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
+ * (e.g., a C call) 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 "Task.h"
#include "Stats.h"
#include "RtsFlags.h"
+#include "Schedule.h"
-static TaskInfo* taskTable;
-static nat maxTasks; /* upper bound / the number of tasks created. */
-static nat taskCount; /* number of tasks currently created */
+/* There's not all that much code that is shared between the
+ * SMP and threads version of the 'task manager.' A sign
+ * that the code ought to be structured differently..(Maybe ToDo).
+ */
+/*
+ * The following Task Manager-local variables are assumed to be
+ * accessed with the RTS lock in hand.
+ */
+#if defined(SMP)
+static TaskInfo* taskTable;
+#endif
+/* upper bound / the number of tasks created. */
+static nat maxTasks;
+/* number of tasks currently created */
+static nat taskCount;
#if defined(SMP)
void
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) )
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;
+ 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
#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();
return;
}
+
#else
+/************ THREADS version *****************/
+
void
-stopTaskManager ()
+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.,
+ when the current task gives up the token on executing
+ STG code.
+ */
+ maxTasks = maxCount;
+ taskCount = 0;
+}
+
+void
+startTask ( void (*taskStart)(void) )
{
+ int r;
+ OSThreadId tid;
+
+ /* 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;
+ }
+ /* If the task limit has been reached, just return. */
+ if (maxTasks > 0 && taskCount == maxTasks) {
+ IF_DEBUG(scheduler,fprintf(stderr,"scheduler: startTask: task limit (%d) reached, not creating new one.\n",maxTasks));
+ return;
+ }
+
+
+ r = createOSThread(&tid,taskStart);
+ if (r != 0) {
+ barf("startTask: Can't create new task");
+ }
+ taskCount++;
+
+ IF_DEBUG(scheduler,fprintf(stderr,"scheduler: startTask: new task %ld (total_count: %d; waiting: %d)\n", tid, taskCount, rts_n_waiting_tasks););
+ return;
}
-#endif
-nat
-getTaskCount ()
+
+
+void
+stopTaskManager ()
{
- return taskCount;
+
}
+#endif
#endif /* RTS_SUPPORTS_THREADS */