---
metadata:
  - name: generator
    content: Diplodoc Platform v5.50.6
alternate:
  - https://perforator.tech/docs/en/reference/language-support/python/threadstate.md
---
> **Documentation Index:** Fetch the complete configuration index at https://perforator.tech/docs/en/llms.txt

# Python Current Thread State Collection

Each native thread is mapped to one `PyThreadState` structure which contains information about the corresponding Python thread.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 410.49609375 277.068359375" width="820.9921875" height="554.13671875"><!--svg-source:excalidraw--><metadata/><defs></defs><rect x="0" y="0" width="410.49609375" height="277.068359375" fill="#ffffff"/><g stroke-linecap="round" transform="translate(12.99609375 10) rotate(0 55.31640625 51.216796875)"><path d="M110.63 51.22 C110.63 53.45, 110.47 55.69, 110.16 57.9 C109.85 60.11, 109.37 62.32, 108.75 64.47 C108.13 66.63, 107.34 68.76, 106.42 70.82 C105.5 72.88, 104.43 74.9, 103.22 76.83 C102.02 78.76, 100.67 80.63, 99.2 82.4 C97.74 84.16, 96.13 85.86, 94.43 87.43 C92.73 89.01, 90.9 90.49, 88.99 91.85 C87.08 93.21, 85.06 94.46, 82.97 95.57 C80.89 96.69, 78.71 97.68, 76.49 98.53 C74.26 99.39, 71.96 100.11, 69.63 100.69 C67.31 101.27, 64.92 101.7, 62.54 102 C60.15 102.29, 57.72 102.43, 55.32 102.43 C52.91 102.43, 50.48 102.29, 48.1 102 C45.71 101.7, 43.32 101.27, 41 100.69 C38.67 100.11, 36.37 99.39, 34.15 98.53 C31.92 97.68, 29.74 96.69, 27.66 95.57 C25.57 94.46, 23.55 93.21, 21.64 91.85 C19.73 90.49, 17.9 89.01, 16.2 87.43 C14.5 85.86, 12.9 84.16, 11.43 82.4 C9.97 80.63, 8.61 78.76, 7.41 76.83 C6.21 74.9, 5.13 72.88, 4.21 70.82 C3.29 68.76, 2.51 66.63, 1.88 64.47 C1.26 62.32, 0.79 60.11, 0.47 57.9 C0.16 55.69, 0 53.45, 0 51.22 C0 48.99, 0.16 46.74, 0.47 44.53 C0.79 42.32, 1.26 40.11, 1.88 37.96 C2.51 35.81, 3.29 33.68, 4.21 31.62 C5.13 29.56, 6.21 27.54, 7.41 25.61 C8.61 23.68, 9.97 21.81, 11.43 20.04 C12.9 18.27, 14.5 16.58, 16.2 15 C17.9 13.43, 19.73 11.94, 21.64 10.58 C23.55 9.23, 25.57 7.98, 27.66 6.86 C29.74 5.75, 31.92 4.75, 34.15 3.9 C36.37 3.05, 38.67 2.32, 41 1.75 C43.32 1.17, 45.71 0.73, 48.1 0.44 C50.48 0.15, 52.91 0, 55.32 0 C57.72 0, 60.15 0.15, 62.54 0.44 C64.92 0.73, 67.31 1.17, 69.63 1.75 C71.96 2.32, 74.26 3.05, 76.49 3.9 C78.71 4.75, 80.89 5.75, 82.97 6.86 C85.06 7.98, 87.08 9.23, 88.99 10.58 C90.9 11.94, 92.73 13.43, 94.43 15 C96.13 16.58, 97.74 18.27, 99.2 20.04 C100.67 21.81, 102.02 23.68, 103.22 25.61 C104.43 27.54, 105.5 29.56, 106.42 31.62 C107.34 33.68, 108.13 35.81, 108.75 37.96 C109.37 40.11, 109.85 42.32, 110.16 44.53 C110.47 46.74, 110.55 50.1, 110.63 51.22 C110.71 52.33, 110.71 50.1, 110.63 51.22" stroke="none" stroke-width="0" fill="#a5d8ff"/><path d="M110.63 51.22 C110.63 53.45, 110.47 55.69, 110.16 57.9 C109.85 60.11, 109.37 62.32, 108.75 64.47 C108.13 66.63, 107.34 68.76, 106.42 70.82 C105.5 72.88, 104.43 74.9, 103.22 76.83 C102.02 78.76, 100.67 80.63, 99.2 82.4 C97.74 84.16, 96.13 85.86, 94.43 87.43 C92.73 89.01, 90.9 90.49, 88.99 91.85 C87.08 93.21, 85.06 94.46, 82.97 95.57 C80.89 96.69, 78.71 97.68, 76.49 98.53 C74.26 99.39, 71.96 100.11, 69.63 100.69 C67.31 101.27, 64.92 101.7, 62.54 102 C60.15 102.29, 57.72 102.43, 55.32 102.43 C52.91 102.43, 50.48 102.29, 48.1 102 C45.71 101.7, 43.32 101.27, 41 100.69 C38.67 100.11, 36.37 99.39, 34.15 98.53 C31.92 97.68, 29.74 96.69, 27.66 95.57 C25.57 94.46, 23.55 93.21, 21.64 91.85 C19.73 90.49, 17.9 89.01, 16.2 87.43 C14.5 85.86, 12.9 84.16, 11.43 82.4 C9.97 80.63, 8.61 78.76, 7.41 76.83 C6.21 74.9, 5.13 72.88, 4.21 70.82 C3.29 68.76, 2.51 66.63, 1.88 64.47 C1.26 62.32, 0.79 60.11, 0.47 57.9 C0.16 55.69, 0 53.45, 0 51.22 C0 48.99, 0.16 46.74, 0.47 44.53 C0.79 42.32, 1.26 40.11, 1.88 37.96 C2.51 35.81, 3.29 33.68, 4.21 31.62 C5.13 29.56, 6.21 27.54, 7.41 25.61 C8.61 23.68, 9.97 21.81, 11.43 20.04 C12.9 18.27, 14.5 16.58, 16.2 15 C17.9 13.43, 19.73 11.94, 21.64 10.58 C23.55 9.23, 25.57 7.98, 27.66 6.86 C29.74 5.75, 31.92 4.75, 34.15 3.9 C36.37 3.05, 38.67 2.32, 41 1.75 C43.32 1.17, 45.71 0.73, 48.1 0.44 C50.48 0.15, 52.91 0, 55.32 0 C57.72 0, 60.15 0.15, 62.54 0.44 C64.92 0.73, 67.31 1.17, 69.63 1.75 C71.96 2.32, 74.26 3.05, 76.49 3.9 C78.71 4.75, 80.89 5.75, 82.97 6.86 C85.06 7.98, 87.08 9.23, 88.99 10.58 C90.9 11.94, 92.73 13.43, 94.43 15 C96.13 16.58, 97.74 18.27, 99.2 20.04 C100.67 21.81, 102.02 23.68, 103.22 25.61 C104.43 27.54, 105.5 29.56, 106.42 31.62 C107.34 33.68, 108.13 35.81, 108.75 37.96 C109.37 40.11, 109.85 42.32, 110.16 44.53 C110.47 46.74, 110.55 50.1, 110.63 51.22 C110.71 52.33, 110.71 50.1, 110.63 51.22" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(28.2734375 51.15234375) rotate(0 40.84797668457031 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">OS thread</text></g><g stroke-linecap="round" transform="translate(297.62109375 13.4921875) rotate(0 50.1171875 45.751953125)"><path d="M22.88 0 C40.05 0, 57.22 0, 77.36 0 C92.61 0, 100.23 7.63, 100.23 22.88 C100.23 34.13, 100.23 45.38, 100.23 68.63 C100.23 83.88, 92.61 91.5, 77.36 91.5 C60.66 91.5, 43.95 91.5, 22.88 91.5 C7.63 91.5, 0 83.88, 0 68.63 C0 59.33, 0 50.03, 0 22.88 C0 7.63, 7.63 0, 22.88 0" stroke="none" stroke-width="0" fill="#ffec99"/><path d="M22.88 0 C38.63 0, 54.37 0, 77.36 0 M77.36 0 C92.61 0, 100.23 7.63, 100.23 22.88 M100.23 22.88 C100.23 36.98, 100.23 51.09, 100.23 68.63 M100.23 68.63 C100.23 83.88, 92.61 91.5, 77.36 91.5 M77.36 91.5 C59.49 91.5, 41.63 91.5, 22.88 91.5 M22.88 91.5 C7.63 91.5, 0 83.88, 0 68.63 M0 68.63 C0 56.93, 0 45.24, 0 22.88 M0 22.88 C0 7.63, 7.63 0, 22.88 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(302.7421875 53.10546875) rotate(0 44.634033061342734 7.30078125)"><text x="0" y="10.291181249999994" font-family="Virgil, Segoe UI Emoji" font-size="11.681249999999993px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g stroke-linecap="round"><g transform="translate(294.80859375 59.8671875) rotate(0 -84.71556542379608 0.41796875)"><path d="M0 0 C-41.29 0.2, -82.57 0.41, -169.43 0.84 M0 0 C-41.18 0.2, -82.36 0.41, -169.43 0.84" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(294.80859375 59.8671875) rotate(0 -84.71556542379608 0.41796875)"><path d="M-145.98 -7.83 C-151.7 -5.72, -157.41 -3.61, -169.43 0.84 M-145.98 -7.83 C-151.68 -5.72, -157.38 -3.62, -169.43 0.84" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(294.80859375 59.8671875) rotate(0 -84.71556542379608 0.41796875)"><path d="M-145.9 9.27 C-151.63 7.22, -157.37 5.16, -169.43 0.84 M-145.9 9.27 C-151.62 7.22, -157.34 5.17, -169.43 0.84" stroke="#1e1e1e" stroke-width="2" fill="none"/></g></g><mask/><g stroke-linecap="round" transform="translate(10 164.634765625) rotate(0 55.31640625 51.216796875)"><path d="M110.63 51.22 C110.63 53.45, 110.47 55.69, 110.16 57.9 C109.85 60.11, 109.37 62.32, 108.75 64.47 C108.13 66.63, 107.34 68.76, 106.42 70.82 C105.5 72.88, 104.43 74.9, 103.22 76.83 C102.02 78.76, 100.67 80.63, 99.2 82.4 C97.74 84.16, 96.13 85.86, 94.43 87.43 C92.73 89.01, 90.9 90.49, 88.99 91.85 C87.08 93.21, 85.06 94.46, 82.97 95.57 C80.89 96.69, 78.71 97.68, 76.49 98.53 C74.26 99.39, 71.96 100.11, 69.63 100.69 C67.31 101.27, 64.92 101.7, 62.54 102 C60.15 102.29, 57.72 102.43, 55.32 102.43 C52.91 102.43, 50.48 102.29, 48.1 102 C45.71 101.7, 43.32 101.27, 41 100.69 C38.67 100.11, 36.37 99.39, 34.15 98.53 C31.92 97.68, 29.74 96.69, 27.66 95.57 C25.57 94.46, 23.55 93.21, 21.64 91.85 C19.73 90.49, 17.9 89.01, 16.2 87.43 C14.5 85.86, 12.9 84.16, 11.43 82.4 C9.97 80.63, 8.61 78.76, 7.41 76.83 C6.21 74.9, 5.13 72.88, 4.21 70.82 C3.29 68.76, 2.51 66.63, 1.88 64.47 C1.26 62.32, 0.79 60.11, 0.47 57.9 C0.16 55.69, 0 53.45, 0 51.22 C0 48.99, 0.16 46.74, 0.47 44.53 C0.79 42.32, 1.26 40.11, 1.88 37.96 C2.51 35.81, 3.29 33.68, 4.21 31.62 C5.13 29.56, 6.21 27.54, 7.41 25.61 C8.61 23.68, 9.97 21.81, 11.43 20.04 C12.9 18.27, 14.5 16.58, 16.2 15 C17.9 13.43, 19.73 11.94, 21.64 10.58 C23.55 9.23, 25.57 7.98, 27.66 6.86 C29.74 5.75, 31.92 4.75, 34.15 3.9 C36.37 3.05, 38.67 2.32, 41 1.75 C43.32 1.17, 45.71 0.73, 48.1 0.44 C50.48 0.15, 52.91 0, 55.32 0 C57.72 0, 60.15 0.15, 62.54 0.44 C64.92 0.73, 67.31 1.17, 69.63 1.75 C71.96 2.32, 74.26 3.05, 76.49 3.9 C78.71 4.75, 80.89 5.75, 82.97 6.86 C85.06 7.98, 87.08 9.23, 88.99 10.58 C90.9 11.94, 92.73 13.43, 94.43 15 C96.13 16.58, 97.74 18.27, 99.2 20.04 C100.67 21.81, 102.02 23.68, 103.22 25.61 C104.43 27.54, 105.5 29.56, 106.42 31.62 C107.34 33.68, 108.13 35.81, 108.75 37.96 C109.37 40.11, 109.85 42.32, 110.16 44.53 C110.47 46.74, 110.55 50.1, 110.63 51.22 C110.71 52.33, 110.71 50.1, 110.63 51.22" stroke="none" stroke-width="0" fill="#a5d8ff"/><path d="M110.63 51.22 C110.63 53.45, 110.47 55.69, 110.16 57.9 C109.85 60.11, 109.37 62.32, 108.75 64.47 C108.13 66.63, 107.34 68.76, 106.42 70.82 C105.5 72.88, 104.43 74.9, 103.22 76.83 C102.02 78.76, 100.67 80.63, 99.2 82.4 C97.74 84.16, 96.13 85.86, 94.43 87.43 C92.73 89.01, 90.9 90.49, 88.99 91.85 C87.08 93.21, 85.06 94.46, 82.97 95.57 C80.89 96.69, 78.71 97.68, 76.49 98.53 C74.26 99.39, 71.96 100.11, 69.63 100.69 C67.31 101.27, 64.92 101.7, 62.54 102 C60.15 102.29, 57.72 102.43, 55.32 102.43 C52.91 102.43, 50.48 102.29, 48.1 102 C45.71 101.7, 43.32 101.27, 41 100.69 C38.67 100.11, 36.37 99.39, 34.15 98.53 C31.92 97.68, 29.74 96.69, 27.66 95.57 C25.57 94.46, 23.55 93.21, 21.64 91.85 C19.73 90.49, 17.9 89.01, 16.2 87.43 C14.5 85.86, 12.9 84.16, 11.43 82.4 C9.97 80.63, 8.61 78.76, 7.41 76.83 C6.21 74.9, 5.13 72.88, 4.21 70.82 C3.29 68.76, 2.51 66.63, 1.88 64.47 C1.26 62.32, 0.79 60.11, 0.47 57.9 C0.16 55.69, 0 53.45, 0 51.22 C0 48.99, 0.16 46.74, 0.47 44.53 C0.79 42.32, 1.26 40.11, 1.88 37.96 C2.51 35.81, 3.29 33.68, 4.21 31.62 C5.13 29.56, 6.21 27.54, 7.41 25.61 C8.61 23.68, 9.97 21.81, 11.43 20.04 C12.9 18.27, 14.5 16.58, 16.2 15 C17.9 13.43, 19.73 11.94, 21.64 10.58 C23.55 9.23, 25.57 7.98, 27.66 6.86 C29.74 5.75, 31.92 4.75, 34.15 3.9 C36.37 3.05, 38.67 2.32, 41 1.75 C43.32 1.17, 45.71 0.73, 48.1 0.44 C50.48 0.15, 52.91 0, 55.32 0 C57.72 0, 60.15 0.15, 62.54 0.44 C64.92 0.73, 67.31 1.17, 69.63 1.75 C71.96 2.32, 74.26 3.05, 76.49 3.9 C78.71 4.75, 80.89 5.75, 82.97 6.86 C85.06 7.98, 87.08 9.23, 88.99 10.58 C90.9 11.94, 92.73 13.43, 94.43 15 C96.13 16.58, 97.74 18.27, 99.2 20.04 C100.67 21.81, 102.02 23.68, 103.22 25.61 C104.43 27.54, 105.5 29.56, 106.42 31.62 C107.34 33.68, 108.13 35.81, 108.75 37.96 C109.37 40.11, 109.85 42.32, 110.16 44.53 C110.47 46.74, 110.55 50.1, 110.63 51.22 C110.71 52.33, 110.71 50.1, 110.63 51.22" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(25.519210815429688 208.1640625) rotate(0 40.84797668457031 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">OS thread</text></g><g stroke-linecap="round" transform="translate(300.26171875 169.544921875) rotate(0 50.1171875 45.751953125)"><path d="M22.88 0 C44.14 0, 65.41 0, 77.36 0 C92.61 0, 100.23 7.63, 100.23 22.88 C100.23 35.28, 100.23 47.69, 100.23 68.63 C100.23 83.88, 92.61 91.5, 77.36 91.5 C66.22 91.5, 55.09 91.5, 22.88 91.5 C7.63 91.5, 0 83.88, 0 68.63 C0 52.78, 0 36.94, 0 22.88 C0 7.63, 7.63 0, 22.88 0" stroke="none" stroke-width="0" fill="#ffec99"/><path d="M22.88 0 C41.44 0, 60.01 0, 77.36 0 M77.36 0 C92.61 0, 100.23 7.63, 100.23 22.88 M100.23 22.88 C100.23 40.06, 100.23 57.25, 100.23 68.63 M100.23 68.63 C100.23 83.88, 92.61 91.5, 77.36 91.5 M77.36 91.5 C62.66 91.5, 47.96 91.5, 22.88 91.5 M22.88 91.5 C7.63 91.5, 0 83.88, 0 68.63 M0 68.63 C0 55.55, 0 42.47, 0 22.88 M0 22.88 C0 7.63, 7.63 0, 22.88 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(309.03784193865727 209.578125) rotate(0 44.634033061342734 7.30078125)"><text x="0" y="10.291181249999994" font-family="Virgil, Segoe UI Emoji" font-size="11.681249999999993px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g stroke-linecap="round"><g transform="translate(296.1484375 215.87890625) rotate(0 -88.11328125 0.25390625)"><path d="M0 0 C-60.31 0.17, -120.63 0.35, -176.23 0.51 M0 0 C-61.13 0.18, -122.26 0.35, -176.23 0.51" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(296.1484375 215.87890625) rotate(0 -88.11328125 0.25390625)"><path d="M-152.76 -8.11 C-160.79 -5.16, -168.82 -2.21, -176.23 0.51 M-152.76 -8.11 C-160.9 -5.12, -169.04 -2.13, -176.23 0.51" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(296.1484375 215.87890625) rotate(0 -88.11328125 0.25390625)"><path d="M-152.71 8.99 C-160.76 6.09, -168.81 3.18, -176.23 0.51 M-152.71 8.99 C-160.87 6.05, -169.03 3.11, -176.23 0.51" stroke="#1e1e1e" stroke-width="2" fill="none"/></g></g><mask/></svg>

Perforator utilizes multiple ways to obtain current `*PyThreadState` in eBPF context - reading from Thread Local Storage (TLS) or Thread Specific Storage (TSS) and extracting from global variables - such as `_PyRuntime` or others. The combination of these approaches and caching helps to improve the accuracy of the `*PyThreadState` collection.

## Reading `*PyThreadState` from TLS

In Python 3.12+, a pointer to current thread's `PyThreadState` is stored in a Thread Local Storage variable called `_PyThreadState_Current`.

In an eBPF program, the pointer to Thread Control Block (TCB) can be retrieved by reading `thread.fsbase` from the `task_struct` structure. This structure can be obtained with the `bpf_get_current_task()` helper. The Thread Local Image will be to the left of the pointer stored in `thread.fsbase`.

The exact offset of thread local variable `_PyThreadState_Current` in Thread Local Image is unknown yet. Therefore, the disassembler is used to find the offset of `_PyThreadState_Current`.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 823.41015625 204.9765625" width="1646.8203125" height="409.953125"><!--svg-source:excalidraw--><metadata/><defs></defs><rect x="0" y="0" width="823.41015625" height="204.9765625" fill="#ffffff"/><g stroke-linecap="round" transform="translate(354.80859375 37.64453125) rotate(0 229.30078125 33.841796875)"><path d="M16.92 0 C183.74 0, 350.56 0, 441.68 0 M16.92 0 C103.54 0, 190.16 0, 441.68 0 M441.68 0 C452.96 0, 458.6 5.64, 458.6 16.92 M441.68 0 C452.96 0, 458.6 5.64, 458.6 16.92 M458.6 16.92 C458.6 24.04, 458.6 31.16, 458.6 50.76 M458.6 16.92 C458.6 25.83, 458.6 34.74, 458.6 50.76 M458.6 50.76 C458.6 62.04, 452.96 67.68, 441.68 67.68 M458.6 50.76 C458.6 62.04, 452.96 67.68, 441.68 67.68 M441.68 67.68 C315.72 67.68, 189.76 67.68, 16.92 67.68 M441.68 67.68 C312.83 67.68, 183.98 67.68, 16.92 67.68 M16.92 67.68 C5.64 67.68, 0 62.04, 0 50.76 M16.92 67.68 C5.64 67.68, 0 62.04, 0 50.76 M0 50.76 C0 38.47, 0 26.18, 0 16.92 M0 50.76 C0 40.23, 0 29.7, 0 16.92 M0 16.92 C0 5.64, 5.64 0, 16.92 0 M0 16.92 C0 5.64, 5.64 0, 16.92 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(446.08203125 60.42578125) rotate(0 145.42987915873528 12.5)"><text x="0" y="17.619999999999997" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">User space thread structure</text></g><g stroke-linecap="round"><g transform="translate(393.08955612805914 159.4140625) rotate(0 -15.427590564029572 -25.373046875)"><path d="M0 0 C-10.36 -17.03, -20.71 -34.06, -30.86 -50.75 M0 0 C-12.3 -20.22, -24.59 -40.44, -30.86 -50.75" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(393.08955612805914 159.4140625) rotate(0 -15.427590564029572 -25.373046875)"><path d="M-11.34 -35.12 C-17.89 -40.36, -24.44 -45.61, -30.86 -50.75 M-11.34 -35.12 C-19.12 -41.34, -26.89 -47.57, -30.86 -50.75" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(393.08955612805914 159.4140625) rotate(0 -15.427590564029572 -25.373046875)"><path d="M-25.96 -26.23 C-27.6 -34.46, -29.24 -42.69, -30.86 -50.75 M-25.96 -26.23 C-27.91 -36, -29.86 -45.77, -30.86 -50.75" stroke="#1e1e1e" stroke-width="2" fill="none"/></g></g><mask/><g transform="translate(252.19565543517467 174.9765625) rotate(0 159.0478414297104 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">bpf_get_current_task()-&gt;thread.fsbase</text></g><g stroke-linecap="round" transform="translate(29.4375 40.26171875) rotate(0 161.173828125 31.1796875)"><path d="M15.59 0 C89.32 0, 163.05 0, 306.76 0 M306.76 0 C317.15 0, 322.35 5.2, 322.35 15.59 M322.35 15.59 C322.35 26.47, 322.35 37.34, 322.35 46.77 M322.35 46.77 C322.35 57.16, 317.15 62.36, 306.76 62.36 M306.76 62.36 C233.52 62.36, 160.27 62.36, 15.59 62.36 M15.59 62.36 C5.2 62.36, 0 57.16, 0 46.77 M0 46.77 C0 35.15, 0 23.53, 0 15.59 M0 15.59 C0 5.2, 5.2 0, 15.59 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(90.28515625 10) rotate(0 100.61993741989136 12.5)"><text x="0" y="17.619999999999997" font-family="Virgil, Segoe UI Emoji" font-size="20px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">Thread Local Image</text></g><g stroke-linecap="round" transform="translate(103.68359375 39.8359375) rotate(0 29.548828125 30.205078125)"><path d="M14.77 0 C20.82 0, 26.87 0, 44.32 0 M44.32 0 C54.17 0, 59.1 4.92, 59.1 14.77 M59.1 14.77 C59.1 21.01, 59.1 27.24, 59.1 45.64 M59.1 45.64 C59.1 55.49, 54.17 60.41, 44.32 60.41 M44.32 60.41 C36.95 60.41, 29.59 60.41, 14.77 60.41 M14.77 60.41 C4.92 60.41, 0 55.49, 0 45.64 M0 45.64 C0 34.89, 0 24.15, 0 14.77 M0 14.77 C0 4.92, 4.92 0, 14.77 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="1.5 8"/></g><g stroke-linecap="round"><g transform="translate(113.52734375 147.2109375) rotate(0 -0.392578125 -19.509765625)"><path d="M0 0 C-0.27 -13.49, -0.54 -26.98, -0.79 -39.02 M0 0 C-0.18 -8.84, -0.36 -17.68, -0.79 -39.02" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(113.52734375 147.2109375) rotate(0 -0.392578125 -19.509765625)"><path d="M6.26 -20.82 C3.82 -27.11, 1.39 -33.4, -0.79 -39.02 M6.26 -20.82 C4.66 -24.94, 3.07 -29.07, -0.79 -39.02" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(113.52734375 147.2109375) rotate(0 -0.392578125 -19.509765625)"><path d="M-7.09 -20.55 C-4.91 -26.94, -2.73 -33.32, -0.79 -39.02 M-7.09 -20.55 C-5.66 -24.74, -4.23 -28.92, -0.79 -39.02" stroke="#1e1e1e" stroke-width="2" fill="none"/></g></g><mask/><g transform="translate(10 157.07421875) rotate(0 103.16793060302734 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">_PyThreadState_Current</text></g></svg>

### Parsing offset of `_PyThreadState_Current` in Thread Local Image

`_PyThreadState_GetCurrent` is a simple getter function which returns the pointer from `_PyThreadState_Current` thread local variable and looks somewhat like this:

**Optimized build**:

```
000000000028a0b0 <_PyThreadState_GetCurrent@@Base>:
  28a0b0:       f3 0f 1e fa             endbr64
  28a0b4:       64 48 8b 04 25 f8 ff    mov    %fs:0xfffffffffffffff8,%rax
  28a0bb:       ff ff
  28a0bd:       c3                      ret
  28a0be:       66 90                   xchg   %ax,%ax
```

**Debug build**:

```
0000000001dad910 <_PyThreadState_GetCurrent>:
 1dad910:       55                      push   %rbp
 1dad911:       48 89 e5                mov    %rsp,%rbp
 1dad914:       48 8d 3d 15 6e 65 00    lea    0x656e15(%rip),%rdi        # 2404730 <_PyRuntime>
 1dad91b:       e8 10 00 00 00          callq  1dad930 <current_fast_get>
 1dad920:       5d                      pop    %rbp
...
...
...
0000000001db7c50 <current_fast_get>:
 1db7c50:       55                      push   %rbp
 1db7c51:       48 89 e5                mov    %rsp,%rbp
 1db7c54:       48 89 7d f8             mov    %rdi,-0x8(%rbp)
 1db7c58:       64 48 8b 04 25 00 00    mov    %fs:0x0,%rax
 1db7c5f:       00 00
 1db7c61:       48 8d 80 f8 ff ff ff    lea    -0x8(%rax),%rax
 1db7c68:       48 8b 00                mov    (%rax),%rax
 1db7c6b:       5d                      pop    %rbp
 1db7c6c:       c3                      retq
```

Looking at these functions, the offset relative to `%fs` register which is used to access `_PyThreadState_Current` variable in userspace can be extracted for later use in the eBPF program.

## Reading `*PyThreadState` from TSS

Before CPython 3.12 libpthread thread specific storage was used to store current `*PyThreadState`. There is a global variable (`autoTLSkey` or `PyRuntime->autoTSSkey`) which stores a key to TSS for the value of current thread state. BPF code implements logic of TSS variable lookup similar to libpthread to obtain the data. 

The address of TSS key can be retrieved by parsing `PyGILState_Ensure` function.

Dissassembling `pthread_getspecific` allows to retrieve the following data from the libpthread binary:

```
struct TPthreadKeyDataInfo {
    ui64 Size = 0;
    ui64 ValueOffset = 0;
    ui64 SeqOffset = 0;
};

struct TAccessTSSInfo {
    TPthreadKeyDataInfo PthreadKeyData;
    ui64 FirstSpecificBlockOffset = 0;
    ui64 SpecificArrayOffset = 0;
    ui64 StructPthreadPointerOffset = 0;
    ui64 KeySecondLevelSize = 0;  // PTHREAD_KEY_2NDLEVEL_SIZE
    ui64 KeyFirstLevelSize = 0;   // PTHREAD_KEY_1STLEVEL_SIZE
    ui64 KeysMax = 0;             // PTHREAD_KEYS_MAX
};
```
The pthread TSS is organized as a 2-level array of `struct pthread_key_data`. First array of `PTHREAD_KEY_1STLEVEL_SIZE` size contains pointers to the chunks of `struct pthread_key_data` of `PTHREAD_KEY_2NDLEVEL_SIZE` size. First chunk of 2nd level is preallocated in `struct pthread`. The maximum total number of thread key-value pairs `PTHREAD_KEYS_MAX`.

The key is an index in 2-level array. `i / PTHREAD_KEY_2NDLEVEL_SIZE` is index for top-level array, `i % PTHREAD_KEY_2NDLEVEL_SIZE` is index for the bottom-level array.

The pointer to the top-level array can be obtained through `struct pthread` by reading `current_task->thread.fsbase`.

<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1237.330729166666 703.6284722222222" width="2474.661458333332" height="1407.2569444444443"><!--svg-source:excalidraw--><metadata/><defs></defs><rect x="0" y="0" width="1237.330729166666" height="703.6284722222222" fill="#ffffff"/><g stroke-linecap="round" transform="translate(400.76866319444434 299.3307291666666) rotate(0 215.298828125 34.556640625)"><path d="M17.28 0 C145.73 0, 274.19 0, 413.32 0 M17.28 0 C115.14 0, 213.01 0, 413.32 0 M413.32 0 C424.84 0, 430.6 5.76, 430.6 17.28 M413.32 0 C424.84 0, 430.6 5.76, 430.6 17.28 M430.6 17.28 C430.6 26.09, 430.6 34.91, 430.6 51.83 M430.6 17.28 C430.6 28.53, 430.6 39.79, 430.6 51.83 M430.6 51.83 C430.6 63.35, 424.84 69.11, 413.32 69.11 M430.6 51.83 C430.6 63.35, 424.84 69.11, 413.32 69.11 M413.32 69.11 C307.22 69.11, 201.12 69.11, 17.28 69.11 M413.32 69.11 C282.37 69.11, 151.43 69.11, 17.28 69.11 M17.28 69.11 C5.76 69.11, 0 63.35, 0 51.83 M17.28 69.11 C5.76 69.11, 0 63.35, 0 51.83 M0 51.83 C0 38.26, 0 24.68, 0 17.28 M0 51.83 C0 38.27, 0 24.71, 0 17.28 M0 17.28 C0 5.76, 5.76 0, 17.28 0 M0 17.28 C0 5.76, 5.76 0, 17.28 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g stroke-linecap="round" transform="translate(67.37152777777737 506.5052083333332) rotate(0 106.2890625 36.392578125)"><path d="M18.2 0 C71.1 0, 124.01 0, 194.38 0 M18.2 0 C78.85 0, 139.5 0, 194.38 0 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M212.58 18.2 C212.58 27.4, 212.58 36.61, 212.58 54.59 M212.58 18.2 C212.58 27.13, 212.58 36.06, 212.58 54.59 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M194.38 72.79 C130.75 72.79, 67.12 72.79, 18.2 72.79 M194.38 72.79 C127.99 72.79, 61.6 72.79, 18.2 72.79 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M0 54.59 C0 46.99, 0 39.4, 0 18.2 M0 54.59 C0 42.73, 0 30.87, 0 18.2 M0 18.2 C0 6.07, 6.07 0, 18.2 0 M0 18.2 C0 6.07, 6.07 0, 18.2 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g stroke-linecap="round" transform="translate(375.8168402777774 505.5501302083332) rotate(0 106.2890625 36.392578125)"><path d="M18.2 0 C62.4 0, 106.61 0, 194.38 0 M18.2 0 C67.14 0, 116.07 0, 194.38 0 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M212.58 18.2 C212.58 28.37, 212.58 38.55, 212.58 54.59 M212.58 18.2 C212.58 25.99, 212.58 33.79, 212.58 54.59 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M194.38 72.79 C157.79 72.79, 121.21 72.79, 18.2 72.79 M194.38 72.79 C130.99 72.79, 67.6 72.79, 18.2 72.79 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M0 54.59 C0 41.86, 0 29.13, 0 18.2 M0 54.59 C0 43.3, 0 32.02, 0 18.2 M0 18.2 C0 6.07, 6.07 0, 18.2 0 M0 18.2 C0 6.07, 6.07 0, 18.2 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g stroke-linecap="round" transform="translate(939.9574652777774 508.6126302083332) rotate(0 106.2890625 36.392578125)"><path d="M18.2 0 C67.24 0, 116.28 0, 194.38 0 M18.2 0 C62.96 0, 107.73 0, 194.38 0 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M194.38 0 C206.51 0, 212.58 6.07, 212.58 18.2 M212.58 18.2 C212.58 25.65, 212.58 33.1, 212.58 54.59 M212.58 18.2 C212.58 27.28, 212.58 36.37, 212.58 54.59 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M212.58 54.59 C212.58 66.72, 206.51 72.79, 194.38 72.79 M194.38 72.79 C152.91 72.79, 111.44 72.79, 18.2 72.79 M194.38 72.79 C134 72.79, 73.61 72.79, 18.2 72.79 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M18.2 72.79 C6.07 72.79, 0 66.72, 0 54.59 M0 54.59 C0 40.88, 0 27.17, 0 18.2 M0 54.59 C0 42.15, 0 29.71, 0 18.2 M0 18.2 C0 6.07, 6.07 0, 18.2 0 M0 18.2 C0 6.07, 6.07 0, 18.2 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g stroke-linecap="round"><g transform="translate(431.04587036735484 368.6062199881048) rotate(0 -108.17848403819721 68.78494086096339)"><path d="M0 0 C-36.06 22.93, -180.3 114.64, -216.36 137.57 M0 0 C-36.06 22.93, -180.3 114.64, -216.36 137.57" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(431.04587036735484 368.6062199881048) rotate(0 -108.17848403819721 68.78494086096339)"><path d="M-201.12 117.75 C-206.44 124.66, -211.75 131.58, -216.36 137.57 M-201.12 117.75 C-206.66 124.95, -212.2 132.16, -216.36 137.57" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(431.04587036735484 368.6062199881048) rotate(0 -108.17848403819721 68.78494086096339)"><path d="M-191.94 132.18 C-200.46 134.06, -208.98 135.94, -216.36 137.57 M-191.94 132.18 C-200.82 134.14, -209.69 136.1, -216.36 137.57" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round"><g transform="translate(515.856397767174 368.63419363185545) rotate(0 -15.80244611834462 67.9438334308449)"><path d="M0 0 C-5.27 22.65, -26.34 113.24, -31.6 135.89 M0 0 C-5.27 22.65, -26.34 113.24, -31.6 135.89" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(515.856397767174 368.63419363185545) rotate(0 -15.80244611834462 67.9438334308449)"><path d="M-34.61 111.07 C-33.7 118.58, -32.79 126.09, -31.6 135.89 M-34.61 111.07 C-33.99 116.16, -33.38 121.25, -31.6 135.89" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(515.856397767174 368.63419363185545) rotate(0 -15.80244611834462 67.9438334308449)"><path d="M-17.95 114.94 C-22.09 121.28, -26.22 127.62, -31.6 135.89 M-17.95 114.94 C-20.75 119.24, -23.55 123.53, -31.6 135.89" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round"><g transform="translate(784.9997783170395 368.6062199881048) rotate(0 95.13611336411611 69.83865179846339)"><path d="M0 0 C31.71 23.28, 158.56 116.4, 190.27 139.68 M0 0 C31.71 23.28, 158.56 116.4, 190.27 139.68" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(784.9997783170395 368.6062199881048) rotate(0 95.13611336411611 69.83865179846339)"><path d="M166.27 132.67 C174.93 135.2, 183.59 137.73, 190.27 139.68 M166.27 132.67 C175.48 135.36, 184.69 138.05, 190.27 139.68" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(784.9997783170395 368.6062199881048) rotate(0 95.13611336411611 69.83865179846339)"><path d="M176.39 118.88 C181.4 126.39, 186.41 133.89, 190.27 139.68 M176.39 118.88 C181.72 126.86, 187.04 134.84, 190.27 139.68" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g transform="translate(741.3129340277774 525.2278645833333) rotate(0 9.785980224609375 17.5)"><text x="0" y="26.712" font-family="Nunito, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">...</text></g><g transform="translate(519.1519097222217 316.1961805555555) rotate(0 99.73218536376953 18.234814694259512)"><text x="0" y="25.703794793028216" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="29.175703510815232px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">1st level array</text></g><g transform="translate(112.55205451117581 525.4427083333333) rotate(0 59.91996765136719 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">2nd level</text></g><g transform="translate(991.4426795111758 527.5481770833333) rotate(0 59.91996765136719 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">2nd level</text></g><g stroke-linecap="round" transform="translate(447.7934027777774 507.4544270833333) rotate(0 35.123046875 35.02734375)"><path d="M17.51 0 C30.46 0, 43.4 0, 52.73 0 M52.73 0 C64.41 0, 70.25 5.84, 70.25 17.51 M70.25 17.51 C70.25 26.97, 70.25 36.42, 70.25 52.54 M70.25 52.54 C70.25 64.22, 64.41 70.05, 52.73 70.05 M52.73 70.05 C45.66 70.05, 38.59 70.05, 17.51 70.05 M17.51 70.05 C5.84 70.05, 0 64.22, 0 52.54 M0 52.54 C0 40.97, 0 29.4, 0 17.51 M0 17.51 C0 5.84, 5.84 0, 17.51 0" stroke="#1e1e1e" stroke-width="1.5" fill="none" stroke-dasharray="8 9"/></g><g transform="translate(340.7543402777774 628.0052083333333) rotate(0 113.79195404052734 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">&#42;PyThreadState</text></g><g stroke-linecap="round"><g transform="translate(455.8022301458077 618.6809895833333) rotate(0 8.300153154392774 -19.969402923438224)"><path d="M0 0 C2.77 -6.66, 13.83 -33.28, 16.6 -39.94 M0 0 C2.77 -6.66, 13.83 -33.28, 16.6 -39.94" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(455.8022301458077 618.6809895833333) rotate(0 8.300153154392774 -19.969402923438224)"><path d="M15.63 -18.33 C15.85 -23.18, 16.07 -28.03, 16.6 -39.94 M15.63 -18.33 C15.89 -24.13, 16.15 -29.92, 16.6 -39.94" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(455.8022301458077 618.6809895833333) rotate(0 8.300153154392774 -19.969402923438224)"><path d="M1.97 -24.01 C5.25 -27.59, 8.53 -31.16, 16.6 -39.94 M1.97 -24.01 C5.89 -28.28, 9.81 -32.55, 16.6 -39.94" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g transform="translate(140.32769097222172 108.65798611111109) rotate(0 82.57196807861328 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">autoTSSkey</text></g><g stroke-linecap="round" transform="translate(125.89019097222194 104.07161458333331) rotate(0 97.65625 22.890625)"><path d="M11.45 0 C74.57 0, 137.69 0, 183.87 0 M11.45 0 C77.99 0, 144.54 0, 183.87 0 M183.87 0 C191.5 0, 195.31 3.82, 195.31 11.45 M183.87 0 C191.5 0, 195.31 3.82, 195.31 11.45 M195.31 11.45 C195.31 18.96, 195.31 26.48, 195.31 34.34 M195.31 11.45 C195.31 18.46, 195.31 25.47, 195.31 34.34 M195.31 34.34 C195.31 41.97, 191.5 45.78, 183.87 45.78 M195.31 34.34 C195.31 41.97, 191.5 45.78, 183.87 45.78 M183.87 45.78 C129.87 45.78, 75.88 45.78, 11.45 45.78 M183.87 45.78 C116.3 45.78, 48.73 45.78, 11.45 45.78 M11.45 45.78 C3.82 45.78, 0 41.97, 0 34.34 M11.45 45.78 C3.82 45.78, 0 41.97, 0 34.34 M0 34.34 C0 28.22, 0 22.1, 0 11.45 M0 34.34 C0 28.37, 0 22.4, 0 11.45 M0 11.45 C0 3.82, 3.82 0, 11.45 0 M0 11.45 C0 3.82, 3.82 0, 11.45 0" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g stroke-linecap="round"><g stroke-opacity="0.3" fill-opacity="0.3" transform="translate(301.41188632896046 150.35348945462567) rotate(0 79.67840579369351 176.88683522548294)"><path d="M0 0 C15.77 35.38, 68.05 153.34, 94.61 212.3 C121.17 271.27, 148.57 330.2, 159.36 353.77" stroke="#1e1e1e" stroke-width="1.5" fill="none" stroke-dasharray="8 9"/></g><g stroke-opacity="0.3" fill-opacity="0.3" transform="translate(301.41188632896046 150.35348945462567) rotate(0 79.67840579369351 176.88683522548294)"><path d="M141.77 336.01 C147.31 341.61, 152.86 347.22, 159.36 353.77" stroke="#1e1e1e" stroke-width="1.5" fill="none"/></g><g stroke-opacity="0.3" fill-opacity="0.3" transform="translate(301.41188632896046 150.35348945462567) rotate(0 79.67840579369351 176.88683522548294)"><path d="M157.3 328.86 C157.95 336.72, 158.6 344.57, 159.36 353.77" stroke="#1e1e1e" stroke-width="1.5" fill="none"/></g></g><mask/><g stroke-opacity="0.3" fill-opacity="0.3" stroke-linecap="round" transform="translate(10 10) rotate(0 605.7335069444437 106.24782986111111)"><path d="M32 0 C446.32 0, 860.64 0, 1179.47 0 M1179.47 0 C1200.8 0, 1211.47 10.67, 1211.47 32 M1211.47 32 C1211.47 72.86, 1211.47 113.72, 1211.47 180.5 M1211.47 180.5 C1211.47 201.83, 1200.8 212.5, 1179.47 212.5 M1179.47 212.5 C804.15 212.5, 428.84 212.5, 32 212.5 M32 212.5 C10.67 212.5, 0 201.83, 0 180.5 M0 180.5 C0 128.56, 0 76.63, 0 32 M0 32 C0 10.67, 10.67 0, 32 0" stroke="#1e1e1e" stroke-width="1.5" fill="none" stroke-dasharray="8 9"/></g><g transform="translate(524.5095486111106 31.5321180555556) rotate(0 95.3819580078125 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">CPython data</text></g><g stroke-opacity="0.3" fill-opacity="0.3" stroke-linecap="round" transform="translate(11.015624999999318 235.18229166666669) rotate(0 608.1575520833334 229.22309027777777)"><path d="M32 0 C442.28 0, 852.56 0, 1184.32 0 M1184.32 0 C1205.65 0, 1216.32 10.67, 1216.32 32 M1216.32 32 C1216.32 175.57, 1216.32 319.13, 1216.32 426.45 M1216.32 426.45 C1216.32 447.78, 1205.65 458.45, 1184.32 458.45 M1184.32 458.45 C898.79 458.45, 613.27 458.45, 32 458.45 M32 458.45 C10.67 458.45, 0 447.78, 0 426.45 M0 426.45 C0 291, 0 155.56, 0 32 M0 32 C0 10.67, 10.67 0, 32 0" stroke="#1e1e1e" stroke-width="1.5" fill="none" stroke-dasharray="8 9"/></g><g transform="translate(491.5755208333326 250.15190972222234) rotate(0 139.8599395751953 17.5)"><text x="0" y="24.668" font-family="Excalifont, Xiaolai, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">struct pthread data</text></g></svg>


## Thread state list retrieval from global variables (`_PyRuntime` or `interp_head`)

In CPython 3.7 global variable `_PyRuntime` was introduced. This structure holds most of the runtime data including the list of `PyInterpreterState`. Given the `PyInterpreterState` object we can access `PyThreadState`'s associated with it by reading `tstate_head` field. This field stores a pointer to the head of interpreter's thread states list. The address of `_PyRuntime` can be found in  the ELF symbols sections.

Before the `_PyRuntime` there was another global variable containing interpreter list - `interp_head` which is available even in CPython 2.4. The `interp_head` address can be retrieved by disassembling `PyInterpreterState_Head` function which is a simpler getter for the variable.

The  picture below shows the layout of interpreter state and thread state lists which is almost the same for both `_PyRuntime` and `interp_head` cases.

<svg version="1.1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 707.9611162187016 449.4296875" width="1415.9222324374032" height="898.859375"><!--svg-source:excalidraw--><metadata/><defs></defs><rect x="0" y="0" width="707.9611162187016" height="449.4296875" fill="#ffffff"/><g stroke-linecap="round" transform="translate(113.24431934370162 52.130859375) rotate(0 254.40039062500006 28.98828125)"><path d="M14.49 0 C124.83 0, 235.16 0, 494.31 0 M14.49 0 C115.4 0, 216.31 0, 494.31 0 M494.31 0 C503.97 0, 508.8 4.83, 508.8 14.49 M494.31 0 C503.97 0, 508.8 4.83, 508.8 14.49 M508.8 14.49 C508.8 20.8, 508.8 27.11, 508.8 43.48 M508.8 14.49 C508.8 22.38, 508.8 30.27, 508.8 43.48 M508.8 43.48 C508.8 53.15, 503.97 57.98, 494.31 57.98 M508.8 43.48 C508.8 53.15, 503.97 57.98, 494.31 57.98 M494.31 57.98 C380.9 57.98, 267.49 57.98, 14.49 57.98 M494.31 57.98 C339.6 57.98, 184.9 57.98, 14.49 57.98 M14.49 57.98 C4.83 57.98, 0 53.15, 0 43.48 M14.49 57.98 C4.83 57.98, 0 53.15, 0 43.48 M0 43.48 C0 35.59, 0 27.7, 0 14.49 M0 43.48 C0 36.99, 0 30.49, 0 14.49 M0 14.49 C0 4.83, 4.83 0, 14.49 0 M0 14.49 C0 4.83, 4.83 0, 14.49 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(288.3586382694772 10) rotate(0 79.49196007847786 17.5)"><text x="0" y="24.668" font-family="Virgil, Segoe UI Emoji" font-size="28px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">_PyRuntime</text></g><g stroke-linecap="round" transform="translate(229.3380693437016 51.017578125) rotate(0 81.939453125 27.859375)"><path d="M13.93 0 C48.35 0, 82.78 0, 149.95 0 M149.95 0 C159.24 0, 163.88 4.64, 163.88 13.93 M163.88 13.93 C163.88 23.31, 163.88 32.69, 163.88 41.79 M163.88 41.79 C163.88 51.08, 159.24 55.72, 149.95 55.72 M149.95 55.72 C115.74 55.72, 81.52 55.72, 13.93 55.72 M13.93 55.72 C4.64 55.72, 0 51.08, 0 41.79 M0 41.79 C0 31.7, 0 21.62, 0 13.93 M0 13.93 C0 4.64, 4.64 0, 13.93 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(238.9982255937016 73.228515625) rotate(0 69.3199462890625 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">interpreters-&gt;main</text></g><g stroke-linecap="round"><g transform="translate(244.98691288384316 111.169921875) rotate(0 -105.55879677007078 26.935546875)"><path d="M0 0 C-31.85 1.71, -155.92 1.29, -191.1 10.27 C-226.29 19.25, -207.78 46.6, -211.12 53.87 M0 0 C-31.85 1.71, -155.92 1.29, -191.1 10.27 C-226.29 19.25, -207.78 46.6, -211.12 53.87" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(244.98691288384316 111.169921875) rotate(0 -105.55879677007078 26.935546875)"><path d="M-221.06 32.04 C-218.67 37.28, -216.29 42.52, -211.12 53.87 M-221.06 32.04 C-217.71 39.39, -214.37 46.73, -211.12 53.87" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(244.98691288384316 111.169921875) rotate(0 -105.55879677007078 26.935546875)"><path d="M-204.7 30.76 C-206.24 36.3, -207.78 41.85, -211.12 53.87 M-204.7 30.76 C-206.86 38.54, -209.02 46.31, -211.12 53.87" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round" transform="translate(28.32635059370159 168.052734375) rotate(0 91.044921875 30.015625)"><path d="M15.01 0 C65.39 0, 115.77 0, 167.08 0 M15.01 0 C66.28 0, 117.55 0, 167.08 0 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M182.09 15.01 C182.09 25.82, 182.09 36.63, 182.09 45.02 M182.09 15.01 C182.09 24.5, 182.09 33.98, 182.09 45.02 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M167.08 60.03 C130.04 60.03, 93.01 60.03, 15.01 60.03 M167.08 60.03 C126.06 60.03, 85.05 60.03, 15.01 60.03 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M0 45.02 C0 36.24, 0 27.45, 0 15.01 M0 45.02 C0 33.06, 0 21.09, 0 15.01 M0 15.01 C0 5, 5 0, 15.01 0 M0 15.01 C0 5, 5 0, 15.01 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(47.42010059370159 131.49609375) rotate(0 77.5759439766407 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyInterpreterState</text></g><g stroke-linecap="round" transform="translate(37.52947559370159 169.103515625) rotate(0 32.37109375 28.453125)"><path d="M14.23 0 C22.2 0, 30.16 0, 50.52 0 M50.52 0 C60 0, 64.74 4.74, 64.74 14.23 M64.74 14.23 C64.74 24.86, 64.74 35.49, 64.74 42.68 M64.74 42.68 C64.74 52.16, 60 56.91, 50.52 56.91 M50.52 56.91 C39.68 56.91, 28.84 56.91, 14.23 56.91 M14.23 56.91 C4.74 56.91, 0 52.16, 0 42.68 M0 42.68 C0 32.28, 0 21.88, 0 14.23 M0 14.23 C0 4.74, 4.74 0, 14.23 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(52.77257862104534 187.556640625) rotate(0 17.12799072265625 10)"><text x="17.12799072265625" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">next</text></g><g stroke-linecap="round" transform="translate(273.5392412187016 169.384765625) rotate(0 91.044921875 30.015625)"><path d="M15.01 0 C53.79 0, 92.57 0, 167.08 0 M15.01 0 C51.95 0, 88.89 0, 167.08 0 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M182.09 15.01 C182.09 22.94, 182.09 30.87, 182.09 45.02 M182.09 15.01 C182.09 22.32, 182.09 29.63, 182.09 45.02 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M167.08 60.03 C121.28 60.03, 75.47 60.03, 15.01 60.03 M167.08 60.03 C116.59 60.03, 66.09 60.03, 15.01 60.03 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M0 45.02 C0 38.61, 0 32.19, 0 15.01 M0 45.02 C0 33.47, 0 21.92, 0 15.01 M0 15.01 C0 5, 5 0, 15.01 0 M0 15.01 C0 5, 5 0, 15.01 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g stroke-linecap="round"><g transform="translate(69.21697559370159 163.23808842137134) rotate(0 101.375 -0.6169946713713443)"><path d="M0 0 C23.27 -1.23, 105.83 -8.38, 139.63 -7.36 C173.42 -6.34, 192.23 3.88, 202.75 6.13 M0 0 C23.27 -1.23, 105.83 -8.38, 139.63 -7.36 C173.42 -6.34, 192.23 3.88, 202.75 6.13" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(69.21697559370159 163.23808842137134) rotate(0 101.375 -0.6169946713713443)"><path d="M177.78 7.29 C183.59 7.02, 189.41 6.75, 202.75 6.13 M177.78 7.29 C186.19 6.9, 194.61 6.51, 202.75 6.13" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(69.21697559370159 163.23808842137134) rotate(0 101.375 -0.6169946713713443)"><path d="M182.87 -9.04 C187.5 -5.5, 192.13 -1.97, 202.75 6.13 M182.87 -9.04 C189.57 -3.93, 196.27 1.18, 202.75 6.13" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round" transform="translate(289.4279130937016 170.521484375) rotate(0 32.37109375 28.453125)"><path d="M14.23 0 C22.66 0, 31.1 0, 50.52 0 M50.52 0 C60 0, 64.74 4.74, 64.74 14.23 M64.74 14.23 C64.74 22.05, 64.74 29.87, 64.74 42.68 M64.74 42.68 C64.74 52.16, 60 56.91, 50.52 56.91 M50.52 56.91 C36.35 56.91, 22.18 56.91, 14.23 56.91 M14.23 56.91 C4.74 56.91, 0 52.16, 0 42.68 M0 42.68 C0 35.27, 0 27.85, 0 14.23 M0 14.23 C0 4.74, 4.74 0, 14.23 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(304.67101612104534 188.974609375) rotate(0 17.12799072265625 10)"><text x="17.12799072265625" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">next</text></g><g stroke-linecap="round" transform="translate(515.8712724687016 168.513671875) rotate(0 91.044921875 30.015625)"><path d="M15.01 0 C65.32 0, 115.64 0, 167.08 0 M15.01 0 C62.97 0, 110.94 0, 167.08 0 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M167.08 0 C177.09 0, 182.09 5, 182.09 15.01 M182.09 15.01 C182.09 24.88, 182.09 34.75, 182.09 45.02 M182.09 15.01 C182.09 22.24, 182.09 29.47, 182.09 45.02 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M182.09 45.02 C182.09 55.03, 177.09 60.03, 167.08 60.03 M167.08 60.03 C119.29 60.03, 71.49 60.03, 15.01 60.03 M167.08 60.03 C110.94 60.03, 54.81 60.03, 15.01 60.03 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M15.01 60.03 C5 60.03, 0 55.03, 0 45.02 M0 45.02 C0 36.3, 0 27.57, 0 15.01 M0 45.02 C0 38.22, 0 31.41, 0 15.01 M0 15.01 C0 5, 5 0, 15.01 0 M0 15.01 C0 5, 5 0, 15.01 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g stroke-linecap="round" transform="translate(529.4005693437016 169.783203125) rotate(0 32.37109375 28.453125)"><path d="M14.23 0 C23.85 0, 33.47 0, 50.52 0 M50.52 0 C60 0, 64.74 4.74, 64.74 14.23 M64.74 14.23 C64.74 20.47, 64.74 26.71, 64.74 42.68 M64.74 42.68 C64.74 52.16, 60 56.91, 50.52 56.91 M50.52 56.91 C38.19 56.91, 25.87 56.91, 14.23 56.91 M14.23 56.91 C4.74 56.91, 0 52.16, 0 42.68 M0 42.68 C0 32.87, 0 23.05, 0 14.23 M0 14.23 C0 4.74, 4.74 0, 14.23 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(544.6436723710453 188.236328125) rotate(0 17.12799072265625 10)"><text x="17.12799072265625" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">next</text></g><g stroke-linecap="round"><g transform="translate(324.1036943437016 165.099609375) rotate(0 101.916015625 0.33984375)"><path d="M0 0 C20.11 -1.16, 86.66 -8.25, 120.63 -6.97 C154.6 -5.7, 189.97 5.21, 203.83 7.65 M0 0 C20.11 -1.16, 86.66 -8.25, 120.63 -6.97 C154.6 -5.7, 189.97 5.21, 203.83 7.65" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(324.1036943437016 165.099609375) rotate(0 101.916015625 0.33984375)"><path d="M179.03 10.81 C186.15 9.91, 193.28 9, 203.83 7.65 M179.03 10.81 C185.83 9.95, 192.63 9.08, 203.83 7.65" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(324.1036943437016 165.099609375) rotate(0 101.916015625 0.33984375)"><path d="M182.8 -5.87 C188.84 -1.98, 194.88 1.9, 203.83 7.65 M182.8 -5.87 C188.57 -2.16, 194.33 1.54, 203.83 7.65" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round" transform="translate(120.42791309370159 170.720703125) rotate(0 37.458984375 27.576171875)"><path d="M13.79 0 C24.13 0, 34.48 0, 61.13 0 M61.13 0 C70.32 0, 74.92 4.6, 74.92 13.79 M74.92 13.79 C74.92 23.63, 74.92 33.46, 74.92 41.36 M74.92 41.36 C74.92 50.56, 70.32 55.15, 61.13 55.15 M61.13 55.15 C44.81 55.15, 28.49 55.15, 13.79 55.15 M13.79 55.15 C4.6 55.15, 0 50.56, 0 41.36 M0 41.36 C0 30.61, 0 19.86, 0 13.79 M0 13.79 C0 4.6, 4.6 0, 13.79 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(127.06291850818752 178.296875) rotate(0 30.82397896051407 20)"><text x="30.82397896051407" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">threads</text><text x="30.82397896051407" y="34.096000000000004" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">-&gt;main</text></g><g stroke-linecap="round" transform="translate(29.75213184370159 286.490234375) rotate(0 69.203125 29.498046875)"><path d="M14.75 0 C47.71 0, 80.67 0, 123.66 0 M14.75 0 C55.18 0, 95.61 0, 123.66 0 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M138.41 14.75 C138.41 25.22, 138.41 35.69, 138.41 44.25 M138.41 14.75 C138.41 22.89, 138.41 31.03, 138.41 44.25 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M123.66 59 C94.55 59, 65.44 59, 14.75 59 M123.66 59 C90.38 59, 57.1 59, 14.75 59 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M0 44.25 C0 36.89, 0 29.53, 0 14.75 M0 44.25 C0 37.24, 0 30.23, 0 14.75 M0 14.75 C0 4.92, 4.92 0, 14.75 0 M0 14.75 C0 4.92, 4.92 0, 14.75 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(39.22478809370159 305.603515625) rotate(0 61.13596823811531 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g stroke-linecap="round" transform="translate(26.86150684370159 380.43359375) rotate(0 69.203125 29.498046875)"><path d="M14.75 0 C40.33 0, 65.91 0, 123.66 0 M14.75 0 C52.42 0, 90.08 0, 123.66 0 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M138.41 14.75 C138.41 22.22, 138.41 29.7, 138.41 44.25 M138.41 14.75 C138.41 26.07, 138.41 37.39, 138.41 44.25 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M123.66 59 C101.62 59, 79.58 59, 14.75 59 M123.66 59 C99.43 59, 75.2 59, 14.75 59 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M0 44.25 C0 36.05, 0 27.86, 0 14.75 M0 44.25 C0 37.6, 0 30.95, 0 14.75 M0 14.75 C0 4.92, 4.92 0, 14.75 0 M0 14.75 C0 4.92, 4.92 0, 14.75 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(34.42085110558628 401.712890625) rotate(0 61.13596823811531 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g stroke-linecap="round"><g transform="translate(28.86541309370159 317.7336924012542) rotate(0 -9.41015625 46.763036611872906)"><path d="M0 0 C-3.14 8.13, -17.94 33.2, -18.82 48.79 C-19.7 64.38, -7.52 86.07, -5.26 93.53 M0 0 C-3.14 8.13, -17.94 33.2, -18.82 48.79 C-19.7 64.38, -7.52 86.07, -5.26 93.53" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(28.86541309370159 317.7336924012542) rotate(0 -9.41015625 46.763036611872906)"><path d="M-20.97 76.22 C-16.23 81.44, -11.5 86.66, -5.26 93.53 M-20.97 76.22 C-17.18 80.4, -13.38 84.59, -5.26 93.53" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(28.86541309370159 317.7336924012542) rotate(0 -9.41015625 46.763036611872906)"><path d="M-6.18 70.17 C-5.9 77.22, -5.62 84.26, -5.26 93.53 M-6.18 70.17 C-5.95 75.82, -5.73 81.46, -5.26 93.53" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round"><g transform="translate(156.3526939365505 229.689453125) rotate(0 -48.99090879801885 26.76953125)"><path d="M0 0 C-8.38 3.23, -33.95 10.48, -50.28 19.4 C-66.61 28.32, -90.03 47.85, -97.98 53.54 M0 0 C-8.38 3.23, -33.95 10.48, -50.28 19.4 C-66.61 28.32, -90.03 47.85, -97.98 53.54" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(156.3526939365505 229.689453125) rotate(0 -48.99090879801885 26.76953125)"><path d="M-84.51 32.48 C-88.59 38.85, -92.66 45.22, -97.98 53.54 M-84.51 32.48 C-87.82 37.66, -91.14 42.84, -97.98 53.54" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(156.3526939365505 229.689453125) rotate(0 -48.99090879801885 26.76953125)"><path d="M-74.13 46.06 C-81.34 48.32, -88.56 50.59, -97.98 53.54 M-74.13 46.06 C-79.99 47.9, -85.86 49.74, -97.98 53.54" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round" transform="translate(280.4904130937016 285.17578125) rotate(0 69.203125 29.498046875)"><path d="M14.75 0 C46.31 0, 77.87 0, 123.66 0 M14.75 0 C52.93 0, 91.11 0, 123.66 0 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M138.41 14.75 C138.41 25.24, 138.41 35.72, 138.41 44.25 M138.41 14.75 C138.41 20.81, 138.41 26.88, 138.41 44.25 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M123.66 59 C100.93 59, 78.21 59, 14.75 59 M123.66 59 C100.32 59, 76.99 59, 14.75 59 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M0 44.25 C0 37.07, 0 29.9, 0 14.75 M0 44.25 C0 33.36, 0 22.47, 0 14.75 M0 14.75 C0 4.92, 4.92 0, 14.75 0 M0 14.75 C0 4.92, 4.92 0, 14.75 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g stroke-linecap="round" transform="translate(532.8888505937016 282.23046875) rotate(0 69.203125 29.498046875)"><path d="M14.75 0 C55.54 0, 96.34 0, 123.66 0 M14.75 0 C41.23 0, 67.72 0, 123.66 0 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M123.66 0 C133.49 0, 138.41 4.92, 138.41 14.75 M138.41 14.75 C138.41 24.86, 138.41 34.97, 138.41 44.25 M138.41 14.75 C138.41 20.98, 138.41 27.22, 138.41 44.25 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M138.41 44.25 C138.41 54.08, 133.49 59, 123.66 59 M123.66 59 C85.82 59, 47.98 59, 14.75 59 M123.66 59 C101.68 59, 79.7 59, 14.75 59 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M14.75 59 C4.92 59, 0 54.08, 0 44.25 M0 44.25 C0 32.92, 0 21.6, 0 14.75 M0 44.25 C0 34.87, 0 25.5, 0 14.75 M0 14.75 C0 4.92, 4.92 0, 14.75 0 M0 14.75 C0 4.92, 4.92 0, 14.75 0" stroke="#1e1e1e" stroke-width="2" fill="none"/></g><g transform="translate(284.7660871865469 303.326171875) rotate(0 64.41963840715471 10.537109375)"><text x="0" y="14.853109374999999" font-family="Virgil, Segoe UI Emoji" font-size="16.859375px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g transform="translate(540.3036636055863 301.068359375) rotate(0 61.13596823811531 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyThreadState</text></g><g stroke-linecap="round" transform="translate(369.3829912187016 173.47265625) rotate(0 37.421875 27.576171875)"><path d="M13.79 0 C24.85 0, 35.91 0, 61.06 0 M61.06 0 C70.25 0, 74.84 4.6, 74.84 13.79 M74.84 13.79 C74.84 19.95, 74.84 26.1, 74.84 41.36 M74.84 41.36 C74.84 50.56, 70.25 55.15, 61.06 55.15 M61.06 55.15 C46.64 55.15, 32.22 55.15, 13.79 55.15 M13.79 55.15 C4.6 55.15, 0 50.56, 0 41.36 M0 41.36 C0 32.39, 0 23.41, 0 13.79 M0 13.79 C0 4.6, 4.6 0, 13.79 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(375.9808872581875 181.048828125) rotate(0 30.82397896051407 20)"><text x="30.82397896051407" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">threads</text><text x="30.82397896051407" y="34.096000000000004" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">-&gt;main</text></g><g stroke-linecap="round" transform="translate(607.6486162187016 169.5) rotate(0 38.193359375 27.576171875)"><path d="M13.79 0 C24.89 0, 36 0, 62.6 0 M62.6 0 C71.79 0, 76.39 4.6, 76.39 13.79 M76.39 13.79 C76.39 21.76, 76.39 29.73, 76.39 41.36 M76.39 41.36 C76.39 50.56, 71.79 55.15, 62.6 55.15 M62.6 55.15 C46.62 55.15, 30.65 55.15, 13.79 55.15 M13.79 55.15 C4.6 55.15, 0 50.56, 0 41.36 M0 41.36 C0 35.22, 0 29.07, 0 13.79 M0 13.79 C0 4.6, 4.6 0, 13.79 0" stroke="#1e1e1e" stroke-width="2.5" fill="none" stroke-dasharray="8 10"/></g><g transform="translate(615.0179966331875 177.076171875) rotate(0 30.82397896051407 20)"><text x="30.82397896051407" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">threads</text><text x="30.82397896051407" y="34.096000000000004" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="middle" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">-&gt;main</text></g><g stroke-linecap="round"><g transform="translate(389.0255693437016 229.900390625) rotate(0 -44.947265625 26.69921875)"><path d="M0 0 C-8.04 3.55, -33.28 12.42, -48.27 21.32 C-63.25 30.22, -82.96 48.05, -89.89 53.4 M0 0 C-8.04 3.55, -33.28 12.42, -48.27 21.32 C-63.25 30.22, -82.96 48.05, -89.89 53.4" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(389.0255693437016 229.900390625) rotate(0 -44.947265625 26.69921875)"><path d="M-77.21 31.85 C-80.72 37.81, -84.23 43.77, -89.89 53.4 M-77.21 31.85 C-81.72 39.52, -86.24 47.18, -89.89 53.4" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(389.0255693437016 229.900390625) rotate(0 -44.947265625 26.69921875)"><path d="M-66.33 45.05 C-72.85 47.36, -79.37 49.67, -89.89 53.4 M-66.33 45.05 C-74.71 48.02, -83.1 50.99, -89.89 53.4" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g stroke-linecap="round"><g transform="translate(626.4982255937016 228.849609375) rotate(0 -39.50390625 25.6796875)"><path d="M0 0 C-7.16 3.2, -29.8 10.63, -42.96 19.19 C-56.13 27.75, -73 46, -79.01 51.36 M0 0 C-7.16 3.2, -29.8 10.63, -42.96 19.19 C-56.13 27.75, -73 46, -79.01 51.36" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(626.4982255937016 228.849609375) rotate(0 -39.50390625 25.6796875)"><path d="M-68.45 29.63 C-72.29 37.54, -76.14 45.45, -79.01 51.36 M-68.45 29.63 C-70.96 34.8, -73.48 39.97, -79.01 51.36" stroke="#1e1e1e" stroke-width="1" fill="none"/></g><g transform="translate(626.4982255937016 228.849609375) rotate(0 -39.50390625 25.6796875)"><path d="M-56.95 41.5 C-64.98 45.09, -73.01 48.68, -79.01 51.36 M-56.95 41.5 C-62.2 43.85, -67.45 46.19, -79.01 51.36" stroke="#1e1e1e" stroke-width="1" fill="none"/></g></g><mask/><g transform="translate(282.4535316170609 130.251953125) rotate(0 77.5759439766407 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyInterpreterState</text></g><g transform="translate(521.9535316170609 134.349609375) rotate(0 77.5759439766407 10)"><text x="0" y="14.096" font-family="Virgil, Segoe UI Emoji" font-size="16px" fill="#1e1e1e" text-anchor="start" style="white-space: pre;" direction="ltr" dominant-baseline="alphabetic">PyInterpreterState</text></g></svg>

## Restoring the mapping `(pid, thread_id)` -> `*PyThreadState`

We store a mapping `(pid, thread_id)` -> `*PyThreadState` which allows `*PyThreadState` retrieval on failed BPF reads or other scenarios (e.g. TLS variable with current thread state stores NULL pointer because of released GIL).

In CPython 3.11 `native_thread_id` field was introduced on `PyThreadState` structure. For Linux this field stores TID in some PID namespace. Thereby we can store `(pid, native_thread_id)` pair as a key to the `*PyThreadState`. Upon lookup we can use current task's PID and TID in innermost PID namespace.

Before CPython 3.11 `thread_id` field on `PyThreadState` structure contained the `thread_id` returned by pthread library. We only support glibc libpthread of version 2.4+ here. Actually in this setting this `thread_id` is just a pointer to `struct pthread` of the thread. Upon lookup we can use current task's PID and `current_task->thread.fsbase` because it stores a pointer to TCB which is actually a header of `struct pthread`, so this is just a pointer to the current thread structure. 

## Combination of approaches

By combining these approaches, we can improve the accuracy of the stack collection. `_PyThreadState_Current` is `NULL` if the current OS thread is not holding a GIL. In this case, the mapping `(pid, thread_id)` -> `*PyThreadState` can be used to find the correct `*PyThreadState`. Also, occasionally we need to trigger the `PyThreadState` linked list traversal to fill the map.

Collecting the stack of threads which are not holding a GIL is crucial for a more accurate picture of what the program is doing. The OS thread may be blocked on I/O operations or executing compression/decompression off-GIL.
