Capability.c 2.46 KB
Newer Older
sof's avatar
sof committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* ---------------------------------------------------------------------------
 *
 * (c) The GHC Team, 2001
 *
 * Capabilities
 *
 * The notion of a capability is used when operating in multi-threaded
 * environments (which the SMP and Threads builds of the RTS do), to
 * hold all the state an OS thread/task needs to run Haskell code:
 * its STG registers, a pointer to its  TSO, a nursery etc. During
 * STG execution, a pointer to the capabilitity is kept in a 
 * register (BaseReg).
 *
 * Only in an SMP build will there be multiple capabilities, the threaded
 * RTS and other non-threaded builds, there is one global capability,
 * namely MainRegTable.
 *
 * 
 * --------------------------------------------------------------------------*/
#include "PosixSource.h"
#include "Rts.h"
#include "RtsUtils.h"
#include "Capability.h"

sof's avatar
sof committed
25 26 27
#if !defined(SMP)
Capability MainCapability;     /* for non-SMP, we have one global capability */
#endif
sof's avatar
sof committed
28

sof's avatar
sof committed
29 30
nat rts_n_free_capabilities;

sof's avatar
sof committed
31
static
sof's avatar
sof committed
32 33 34 35 36 37 38 39 40
void
initCapability( Capability *cap )
{
    cap->f.stgChk0         = (F_)__stg_chk_0;
    cap->f.stgChk1         = (F_)__stg_chk_1;
    cap->f.stgGCEnter1     = (F_)__stg_gc_enter_1;
    cap->f.stgUpdatePAP    = (F_)__stg_update_PAP;
}

sof's avatar
sof committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
#ifdef SMP
static void initCapabilities_(nat n);
#endif

/* 
 */
void
initCapabilities()
{
#if defined(SMP)
  initCapabilities_(RtsFlags.ParFlags.nNodes);
#else
  initCapability(&MainCapability);
#endif

  return;
}

sof's avatar
sof committed
59 60 61 62 63
/* Free capability list.
 * Locks required: sched_mutex.
 */
#if defined(SMP)
static Capability *free_capabilities; /* Available capabilities for running threads */
sof's avatar
sof committed
64
#endif
sof's avatar
sof committed
65 66 67

void grabCapability(Capability** cap)
{
sof's avatar
sof committed
68
#if !defined(SMP)
sof's avatar
sof committed
69
  rts_n_free_capabilities = 0;
sof's avatar
sof committed
70 71
  *cap = &MainCapability;
#else
sof's avatar
sof committed
72 73 74
  *cap = free_capabilities;
  free_capabilities = (*cap)->link;
  rts_n_free_capabilities--;
sof's avatar
sof committed
75
#endif
sof's avatar
sof committed
76 77
}

sof's avatar
sof committed
78
void releaseCapability(Capability* cap)
sof's avatar
sof committed
79
{
sof's avatar
sof committed
80
#if defined(SMP)
sof's avatar
sof committed
81 82
  cap->link = free_capabilities;
  free_capabilities = cap;
sof's avatar
sof committed
83
  rts_n_free_capabilities++;
sof's avatar
sof committed
84
#endif
sof's avatar
sof committed
85
  rts_n_free_capabilities = 1;
sof's avatar
sof committed
86 87 88
  return;
}

sof's avatar
sof committed
89
#if defined(SMP)
sof's avatar
sof committed
90
/* Allocate 'n' capabilities */
sof's avatar
sof committed
91 92
static void
initCapabilities_(nat n)
sof's avatar
sof committed
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
{
  nat i;
  Capability *cap, *prev;
  cap  = NULL;
  prev = NULL;
  for (i = 0; i < n; i++) {
    cap = stgMallocBytes(sizeof(Capability), "initCapabilities");
    initCapability(cap);
    cap->link = prev;
    prev = cap;
  }
  free_capabilities = cap;
  rts_n_free_capabilities = n;
  IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Allocated %d capabilities\n", n_free_capabilities););
}
#endif /* SMP */