[project @ 2002-02-12 15:34:25 by sof]
[ghc-hetmet.git] / ghc / rts / Capability.c
1 /* ---------------------------------------------------------------------------
2  *
3  * (c) The GHC Team, 2001
4  *
5  * Capabilities
6  *
7  * The notion of a capability is used when operating in multi-threaded
8  * environments (which the SMP and Threads builds of the RTS do), to
9  * hold all the state an OS thread/task needs to run Haskell code:
10  * its STG registers, a pointer to its  TSO, a nursery etc. During
11  * STG execution, a pointer to the capabilitity is kept in a 
12  * register (BaseReg).
13  *
14  * Only in an SMP build will there be multiple capabilities, the threaded
15  * RTS and other non-threaded builds, there is one global capability,
16  * namely MainRegTable.
17  *
18  * 
19  * --------------------------------------------------------------------------*/
20 #include "PosixSource.h"
21 #include "Rts.h"
22 #include "RtsUtils.h"
23 #include "Capability.h"
24
25 #if !defined(SMP)
26 Capability MainCapability;     /* for non-SMP, we have one global capability */
27 #endif
28
29 nat rts_n_free_capabilities;
30
31 static
32 void
33 initCapability( Capability *cap )
34 {
35     cap->f.stgChk0         = (F_)__stg_chk_0;
36     cap->f.stgChk1         = (F_)__stg_chk_1;
37     cap->f.stgGCEnter1     = (F_)__stg_gc_enter_1;
38     cap->f.stgUpdatePAP    = (F_)__stg_update_PAP;
39 }
40
41 #ifdef SMP
42 static void initCapabilities_(nat n);
43 #endif
44
45 /* 
46  */
47 void
48 initCapabilities()
49 {
50 #if defined(SMP)
51   initCapabilities_(RtsFlags.ParFlags.nNodes);
52 #else
53   initCapability(&MainCapability);
54 #endif
55
56   return;
57 }
58
59 /* Free capability list.
60  * Locks required: sched_mutex.
61  */
62 #if defined(SMP)
63 static Capability *free_capabilities; /* Available capabilities for running threads */
64 #endif
65
66 void grabCapability(Capability** cap)
67 {
68 #if !defined(SMP)
69   rts_n_free_capabilities = 0;
70   *cap = &MainCapability;
71 #else
72   *cap = free_capabilities;
73   free_capabilities = (*cap)->link;
74   rts_n_free_capabilities--;
75 #endif
76 }
77
78 void releaseCapability(Capability* cap)
79 {
80 #if defined(SMP)
81   cap->link = free_capabilities;
82   free_capabilities = cap;
83   rts_n_free_capabilities++;
84 #endif
85   rts_n_free_capabilities = 1;
86   return;
87 }
88
89 #if defined(SMP)
90 /* Allocate 'n' capabilities */
91 static void
92 initCapabilities_(nat n)
93 {
94   nat i;
95   Capability *cap, *prev;
96   cap  = NULL;
97   prev = NULL;
98   for (i = 0; i < n; i++) {
99     cap = stgMallocBytes(sizeof(Capability), "initCapabilities");
100     initCapability(cap);
101     cap->link = prev;
102     prev = cap;
103   }
104   free_capabilities = cap;
105   rts_n_free_capabilities = n;
106   IF_DEBUG(scheduler,fprintf(stderr,"scheduler: Allocated %d capabilities\n", n_free_capabilities););
107 }
108 #endif /* SMP */
109