Commit 80c55dc7 authored by sof's avatar sof
Browse files

[project @ 2002-02-06 01:26:14 by sof]

- in the threaded case, keep track of the number of
  tasks/threads that are currently waiting to enter
  the RTS.
- taskStart():
     + only start up a new thread/task if there aren't
       any already waiting to gain RTS access.
     + honour thread/task limits (if any).
parent 7f906dc8
......@@ -10,11 +10,12 @@
* '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.
*
......@@ -27,9 +28,23 @@
#include "Stats.h"
#include "RtsFlags.h"
/* 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;
static nat maxTasks; /* upper bound / the number of tasks created. */
static nat taskCount; /* number of tasks currently created */
#endif
/* upper bound / the number of tasks created. */
static nat maxTasks;
/* number of tasks currently created */
static nat taskCount;
static nat tasksAvailable;
#if defined(SMP)
......@@ -58,20 +73,6 @@ startTaskManager( nat maxCount, void (*taskStart)(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) )
......@@ -84,20 +85,17 @@ 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 ()
{
......@@ -132,7 +130,100 @@ stopTaskManager ()
return;
}
#else
/************ THREADS version *****************/
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;
tasksAvailable = 0;
}
void
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););
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++;
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++;
return;
}
void
stopTaskManager ()
{
......@@ -140,6 +231,7 @@ stopTaskManager ()
}
#endif
nat
getTaskCount ()
{
......
......@@ -29,6 +29,11 @@ extern TaskInfo *taskIds;
extern void startTaskManager ( nat maxTasks, void (*taskStart)(void) );
extern void stopTaskManager ( void );
#if defined(THREADED_RTS)
extern void taskNotAvailable ( void );
extern void taskAvailable ( void );
#endif
extern void startTask ( void (*taskStart)(void) );
extern nat getTaskCount( void );
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment