summaryrefslogtreecommitdiff
path: root/libraries/ghc-heap/tests/tso_and_stack_closures.hs
blob: a845f844b37d2574b8aa264aae65e74434d317f0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
{-# LANGUAGE NondecreasingIndentation #-}
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE CPP #-}
{-# LANGUAGE ForeignFunctionInterface #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE UnboxedTuples #-}

import Control.Monad (forM_, unless)
import Data.List (find)
import Data.Word
import Foreign
import Foreign.C.Types
import GHC.IO ( IO(..) )
import GHC.Exts
import GHC.Exts.Heap
import qualified  GHC.Exts.Heap.FFIClosures as FFIClosures
import GHC.Word

import TestUtils

main :: IO ()
main = do
    (tso, stack) <- {-# SCC "MyCostCentre" #-} createAndUnpackTSOAndSTACKClosure
    assertEqual (getClosureType tso) TSO
    assertEqual (what_next tso) ThreadRunGHC
    assertEqual (why_blocked tso) NotBlocked
    assertEqual (saved_errno tso) 0
    forM_ (flags tso) $ \flag -> case flag of
        TsoFlagsUnknownValue _ -> error $ "Unknown flag: " ++ show flag
        _ | flag `elem`
            [ TsoLocked
            , TsoBlockx
            , TsoStoppedOnBreakpoint
            , TsoSqueezed
            ] -> error $ "Unexpected flag: " ++ show flag
        _ -> return ()

    assertEqual (getClosureType stack) STACK

#if defined(PROFILING)
    let costCentre = ccs_cc <$> (cccs =<< prof tso)
    case costCentre of
        Nothing -> error $ "No CostCentre found in TSO: " ++ show tso
        Just _ -> case findMyCostCentre (linkedCostCentres costCentre) of
                    Just myCostCentre -> do
                        assertEqual (cc_label myCostCentre) "MyCostCentre"
                        assertEqual (cc_module myCostCentre) "Main"
                        assertEqual (cc_srcloc myCostCentre) (Just "tso_and_stack_closures.hs:24:48-80")
                        assertEqual (cc_is_caf myCostCentre) False
                    Nothing -> error $ "MyCostCentre not found in:\n" ++ unlines (cc_label <$> linkedCostCentres costCentre)
#endif

linkedCostCentres :: Maybe CostCentre -> [CostCentre]
linkedCostCentres Nothing = []
linkedCostCentres (Just cc) = cc : linkedCostCentres (cc_link cc)

findMyCostCentre:: [CostCentre] -> Maybe CostCentre
findMyCostCentre ccs = find (\cc -> cc_label cc == "MyCostCentre") ccs

getClosureType :: GenClosure b -> ClosureType
getClosureType = tipe . info

type StgTso = Any
type StgStack = Any
data MBA a = MBA (MutableByteArray# a)
data BA = BA ByteArray#

foreign import ccall safe "create_tso.h create_and_unpack_tso_and_stack"
    c_create_and_unpack_tso_and_stack
        :: Ptr (Ptr StgTso)
        -> Ptr (Ptr StgInfoTable)
        -> Ptr CInt
        -> Ptr (Ptr Word8)
        -> Ptr CInt
        -> Ptr (Ptr (Ptr Any))
        -> Ptr (Ptr StgStack)
        -> Ptr (Ptr StgInfoTable)
        -> Ptr CInt
        -> Ptr (Ptr Word8)
        -> Ptr CInt
        -> Ptr (Ptr (Ptr Any))
        -> IO ()

createAndUnpackTSOAndSTACKClosure
    :: IO ( GenClosure (Ptr Any)
          , GenClosure (Ptr Any)
          )
createAndUnpackTSOAndSTACKClosure = do

    alloca $ \ptrPtrTso -> do
    alloca $ \ptrPtrTsoInfoTable -> do
    alloca $ \ptrTsoHeapRepSize -> do
    alloca $ \ptrPtrTsoHeapRep -> do
    alloca $ \ptrTsoPointersSize -> do
    alloca $ \ptrPtrPtrTsoPointers -> do

    alloca $ \ptrPtrStack -> do
    alloca $ \ptrPtrStackInfoTable -> do
    alloca $ \ptrStackHeapRepSize -> do
    alloca $ \ptrPtrStackHeapRep -> do
    alloca $ \ptrStackPointersSize -> do
    alloca $ \ptrPtrPtrStackPointers -> do

    c_create_and_unpack_tso_and_stack

        ptrPtrTso
        ptrPtrTsoInfoTable
        ptrTsoHeapRepSize
        ptrPtrTsoHeapRep
        ptrTsoPointersSize
        ptrPtrPtrTsoPointers

        ptrPtrStack
        ptrPtrStackInfoTable
        ptrStackHeapRepSize
        ptrPtrStackHeapRep
        ptrStackPointersSize
        ptrPtrPtrStackPointers

    let fromHeapRep
          ptrPtrClosureInfoTable
          ptrClosureHeapRepSize
          ptrPtrClosureHeapRep
          ptrClosurePointersSize
          ptrPtrPtrClosurePointers = do
            ptrInfoTable :: Ptr StgInfoTable <- peek ptrPtrClosureInfoTable

            heapRepSize :: Int <- fromIntegral <$> peek ptrClosureHeapRepSize
            let I# heapRepSize# = heapRepSize
            ptrHeapRep :: Ptr Word8 <- peek ptrPtrClosureHeapRep
            MBA mutHeapRepBA <- IO $ \s -> let
                (# s', mba# #) = newByteArray# heapRepSize# s
                in (# s', MBA mba# #)
            forM_ [0..heapRepSize-1] $ \i@(I# i#) -> do
                W8# w <- peekElemOff ptrHeapRep i
                IO (\s -> (# writeWord8Array# mutHeapRepBA i# w s, () #))
            BA heapRep <- IO $ \s -> let
                (# s', ba# #) = unsafeFreezeByteArray# mutHeapRepBA s
                in (# s', BA ba# #)

            pointersSize :: Int <- fromIntegral <$> peek ptrClosurePointersSize
            ptrPtrPointers :: Ptr (Ptr Any) <- peek ptrPtrPtrClosurePointers
            ptrPtrPointers :: [Ptr Any] <- sequence
                [ peekElemOff ptrPtrPointers i
                | i <- [0..pointersSize-1]
                ]

            getClosureDataFromHeapRep
                heapRep
                ptrInfoTable
                ptrPtrPointers

    tso <- fromHeapRep
        ptrPtrTsoInfoTable
        ptrTsoHeapRepSize
        ptrPtrTsoHeapRep
        ptrTsoPointersSize
        ptrPtrPtrTsoPointers

    stack <- fromHeapRep
        ptrPtrStackInfoTable
        ptrStackHeapRepSize
        ptrPtrStackHeapRep
        ptrStackPointersSize
        ptrPtrPtrStackPointers

    return (tso, stack)