LCOV - code coverage report
Current view: top level - port - cplgetcurrentthreadcount.cpp (source / functions) Hit Total Coverage
Test: gdal_filtered.info Lines: 16 16 100.0 %
Date: 2025-08-01 10:10:57 Functions: 1 1 100.0 %

          Line data    Source code
       1             : /******************************************************************************
       2             :  *
       3             :  * Project:  GDAL
       4             :  * Purpose:  Return number of current threads in current process
       5             :  * Author:   Even Rouault <even dot rouault at spatialys.com>
       6             :  *
       7             :  ******************************************************************************
       8             :  * Copyright (c) 2025, Even Rouault <even dot rouault at spatialys.com>
       9             :  *
      10             :  * SPDX-License-Identifier: MIT
      11             :  ****************************************************************************/
      12             : 
      13             : #include "cpl_multiproc.h"
      14             : 
      15             : /************************************************************************/
      16             : /*                         CPLGetCurrentThreadCount()                   */
      17             : /************************************************************************/
      18             : 
      19             : /**
      20             :  * \fn CPLGetCurrentThreadCount()
      21             :  *
      22             :  * Return the current number of threads of the current process.
      23             :  *
      24             :  * Implemented for Linux, Windows, FreeBSD, netBSD and MACOSX.
      25             :  *
      26             :  * Return 0 on other platforms or in case of error.
      27             :  *
      28             :  * @since 3.12
      29             :  */
      30             : 
      31             : #ifdef __linux
      32             : 
      33             : #include "cpl_string.h"
      34             : 
      35             : #include <cstdio>
      36             : #include <string>
      37             : 
      38           6 : int CPLGetCurrentThreadCount()
      39             : {
      40           6 :     int nRet = 0;
      41           6 :     FILE *fp = fopen("/proc/self/stat", "rb");
      42           6 :     if (fp)
      43             :     {
      44          12 :         std::string osBuffer;
      45           6 :         osBuffer.resize(4096);
      46           6 :         const size_t nRead = fread(osBuffer.data(), 1, osBuffer.size(), fp);
      47           6 :         if (nRead > 0 && nRead < osBuffer.size())
      48             :         {
      49           6 :             osBuffer.resize(nRead);
      50           6 :             const auto nPos = osBuffer.find(')');
      51           6 :             if (nPos != std::string::npos)
      52             :             {
      53             :                 const CPLStringList aosTokens(
      54          12 :                     CSLTokenizeString2(osBuffer.c_str() + nPos + 1, " ", 0));
      55           6 :                 if (aosTokens.size() >= 18)
      56             :                 {
      57           6 :                     nRet = atoi(aosTokens[17]);
      58             :                 }
      59             :             }
      60             :         }
      61           6 :         fclose(fp);
      62             :     }
      63           6 :     return nRet;
      64             : }
      65             : 
      66             : #elif defined(__WIN32)
      67             : 
      68             : #include <windows.h>
      69             : #include <tlhelp32.h>
      70             : 
      71             : int CPLGetCurrentThreadCount()
      72             : {
      73             :     int nRet = 0;
      74             : 
      75             :     const DWORD pid = GetCurrentProcessId();
      76             :     HANDLE hThreadSnap = CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
      77             :     if (hThreadSnap != INVALID_HANDLE_VALUE)
      78             :     {
      79             :         THREADENTRY32 te32;
      80             :         te32.dwSize = static_cast<int>(sizeof(THREADENTRY32));
      81             : 
      82             :         if (Thread32First(hThreadSnap, &te32))
      83             :         {
      84             :             do
      85             :             {
      86             :                 if (te32.th32OwnerProcessID == pid)
      87             :                 {
      88             :                     nRet++;
      89             :                 }
      90             :             } while (Thread32Next(hThreadSnap, &te32));
      91             :         }
      92             : 
      93             :         CloseHandle(hThreadSnap);
      94             :     }
      95             :     return nRet;
      96             : }
      97             : 
      98             : #elif defined(__FreeBSD__)
      99             : 
     100             : #include <sys/types.h>
     101             : #include <sys/user.h>  // must be after sys/types.h
     102             : #include <sys/sysctl.h>
     103             : #include <unistd.h>
     104             : 
     105             : int CPLGetCurrentThreadCount()
     106             : {
     107             :     const pid_t pid = getpid();
     108             :     int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PID, static_cast<int>(pid)};
     109             : 
     110             :     struct kinfo_proc kp;
     111             :     size_t len = sizeof(kp);
     112             : 
     113             :     if (sysctl(mib, 4, &kp, &len, nullptr, 0) == -1)
     114             :     {
     115             :         return 0;
     116             :     }
     117             : 
     118             :     return kp.ki_numthreads;
     119             : }
     120             : 
     121             : #elif defined(__NetBSD__)
     122             : 
     123             : #include <sys/types.h>
     124             : #include <sys/sysctl.h>
     125             : #include <sys/lwp.h>
     126             : #include <unistd.h>
     127             : 
     128             : int CPLGetCurrentThreadCount()
     129             : {
     130             :     const pid_t pid = getpid();
     131             :     int mib[5] = {CTL_KERN, KERN_PROC, static_cast<int>(pid),
     132             :                   static_cast<int>(sizeof(struct kinfo_lwp)), 0};
     133             : 
     134             :     size_t len = 0;
     135             :     if (sysctl(mib, 5, nullptr, &len, nullptr, 0) == -1)
     136             :     {
     137             :         return 0;
     138             :     }
     139             : 
     140             :     return static_cast<int>(len / sizeof(struct kinfo_lwp));
     141             : }
     142             : 
     143             : #elif defined(__APPLE__) && defined(__MACH__)
     144             : 
     145             : #include <mach/mach.h>
     146             : 
     147             : int CPLGetCurrentThreadCount()
     148             : {
     149             :     const mach_port_t task = mach_task_self();
     150             : 
     151             :     thread_act_array_t thread_list;
     152             :     mach_msg_type_number_t thread_count = 0;
     153             : 
     154             :     kern_return_t kr = task_threads(task, &thread_list, &thread_count);
     155             :     if (kr == KERN_SUCCESS)
     156             :     {
     157             :         for (mach_msg_type_number_t i = 0; i < thread_count; i++)
     158             :         {
     159             :             mach_port_deallocate(task, thread_list[i]);
     160             :         }
     161             : 
     162             :         vm_deallocate(task, reinterpret_cast<vm_address_t>(thread_list),
     163             :                       thread_count * sizeof(thread_t));
     164             :     }
     165             : 
     166             :     return static_cast<int>(thread_count);
     167             : }
     168             : 
     169             : #else
     170             : 
     171             : #include "cpl_error.h"
     172             : 
     173             : int CPLGetCurrentThreadCount()
     174             : {
     175             :     CPLDebugOnce(
     176             :         "CPL",
     177             :         "CPLGetCurrentThreadCount() unimplemented on this operating system");
     178             :     return 0;
     179             : }
     180             : 
     181             : #endif

Generated by: LCOV version 1.14