#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
static nat maxTasks;
/* number of tasks currently created */
static nat taskCount;
-static nat tasksAvailable;
-
#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();
/************ 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.,
*/
maxTasks = maxCount;
taskCount = 0;
- tasksAvailable = 0;
}
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;
}
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;
}
#endif
-nat
-getTaskCount ()
-{
- return taskCount;
-}
-
-
#endif /* RTS_SUPPORTS_THREADS */