Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package nvtop for openSUSE:Factory checked in at 2023-10-25 18:05:22 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/nvtop (Old) and /work/SRC/openSUSE:Factory/.nvtop.new.24901 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "nvtop" Wed Oct 25 18:05:22 2023 rev:3 rq:1120313 version:3.0.2+31 Changes: -------- --- /work/SRC/openSUSE:Factory/nvtop/nvtop.changes 2023-06-22 23:27:51.542391743 +0200 +++ /work/SRC/openSUSE:Factory/.nvtop.new.24901/nvtop.changes 2023-10-25 18:06:08.273132743 +0200 @@ -1,0 +2,12 @@ +Wed Oct 25 02:13:50 UTC 2023 - malcolmle...@opensuse.org + +- Update to version 3.0.2+31: + * Fix cache_entry for Intel and AMD GPU. + * Fix compilation warnings. + * Disable fdinfo callbacks for hidden gpus. + * Split off linux-specific files from build. + * cmake: use check_linker_flag for checking linker flags. + * Clarify warning messages for Intel and MSM GPUs. + * Added Apple support. + +------------------------------------------------------------------- Old: ---- nvtop-3.0.2+2.obscpio New: ---- nvtop-3.0.2+31.obscpio ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ nvtop.spec ++++++ --- /var/tmp/diff_new_pack.m9hba4/_old 2023-10-25 18:06:09.021157899 +0200 +++ /var/tmp/diff_new_pack.m9hba4/_new 2023-10-25 18:06:09.021157899 +0200 @@ -18,7 +18,7 @@ Name: nvtop -Version: 3.0.2+2 +Version: 3.0.2+31 Release: 0 License: GPL-3.0-or-later Summary: A (h)top like task monitor for NVIDIA and AMD GPUs ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.m9hba4/_old 2023-10-25 18:06:09.065159380 +0200 +++ /var/tmp/diff_new_pack.m9hba4/_new 2023-10-25 18:06:09.069159514 +0200 @@ -1,6 +1,6 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/Syllo/nvtop.git</param> - <param name="changesrevision">9a8458b541a195a0c5cadafb66e240962c852b39</param></service></servicedata> + <param name="changesrevision">45a1796375cd617d16167869bb88e5e69c809468</param></service></servicedata> (No newline at EOF) ++++++ nvtop-3.0.2+2.obscpio -> nvtop-3.0.2+31.obscpio ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/CMakeLists.txt new/nvtop-3.0.2+31/CMakeLists.txt --- old/nvtop-3.0.2+2/CMakeLists.txt 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/CMakeLists.txt 2023-10-21 16:57:54.000000000 +0200 @@ -1,4 +1,4 @@ -cmake_minimum_required(VERSION 3.10) +cmake_minimum_required(VERSION 3.18) #///////////////////////////////////////////////////////////////////# # PROJECT # @@ -60,10 +60,25 @@ set(CMAKE_INSTALL_RPATH "") endif() -option(NVIDIA_SUPPORT "Build support for NVIDIA GPUs through libnvml" ON) -option(AMDGPU_SUPPORT "Build support for AMD GPUs through amdgpu driver" ON) -option(INTEL_SUPPORT "Build support for Intel GPUs through i915 driver" ON) -option(MSM_SUPPORT "Build support for Adreno GPUs through msm driver" ON) +if(APPLE) + set(APPLE_SUPPORT_DEFAULT ON) + set(NVIDIA_SUPPORT_DEFAULT OFF) + set(AMDGPU_SUPPORT_DEFAULT OFF) + set(INTEL_SUPPORT_DEFAULT OFF) + set(MSM_SUPPORT_DEFAULT OFF) +else() + set(APPLE_SUPPORT_DEFAULT OFF) + set(NVIDIA_SUPPORT_DEFAULT ON) + set(AMDGPU_SUPPORT_DEFAULT ON) + set(INTEL_SUPPORT_DEFAULT ON) + set(MSM_SUPPORT_DEFAULT ON) +endif() + +option(NVIDIA_SUPPORT "Build support for NVIDIA GPUs through libnvml" ${NVIDIA_SUPPORT_DEFAULT}) +option(AMDGPU_SUPPORT "Build support for AMD GPUs through amdgpu driver" ${AMDGPU_SUPPORT_DEFAULT}) +option(INTEL_SUPPORT "Build support for Intel GPUs through i915 driver" ${INTEL_SUPPORT_DEFAULT}) +option(MSM_SUPPORT "Build support for Adreno GPUs through msm driver" ${MSM_SUPPORT_DEFAULT}) +option(APPLE_SUPPORT "Build support for Apple GPUs through Metal" ${APPLE_SUPPORT_DEFAULT}) add_subdirectory(src) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/README.markdown new/nvtop-3.0.2+31/README.markdown --- old/nvtop-3.0.2+2/README.markdown 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/README.markdown 2023-10-21 16:57:54.000000000 +0200 @@ -4,9 +4,9 @@ What is NVTOP? -------------- -Nvtop stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel -and NVIDIA GPUs. It can handle multiple GPUs and print information about them in -a htop familiar way. +NVTOP stands for Neat Videocard TOP, a (h)top like task monitor for AMD, Intel +and NVIDIA GPUs. It can handle multiple GPUs and print information +about them in a htop-familiar way. Because a picture is worth a thousand words: @@ -24,6 +24,7 @@ - [Intel](#intel) - [NVIDIA](#nvidia) - [Adreno](#adreno) + - [Apple](#apple) - [Build](#build) - [Distribution Specific Installation Process](#distribution-specific-installation-process) - [Ubuntu / Debian](#ubuntu--debian) @@ -112,22 +113,29 @@ Hence, you will need a kernel with a version greater or equal to 6.0 to see the processes using Adreno GPUs. +### Apple + +NVTOP includes some initial support for Apple using Metal. This is only supported when building for Apple, and when building for Apple only this vendor is supported. + +**APPLE SUPPORT STATUS** +- Apple support is still being worked on. Some bugs and limitations may apply. + Build ----- -Several libraries are required in order for NVTOP to display GPU information: +Several libraries are required in order for NVTOP to display GPU info: * The *ncurses* library driving the user interface. * This makes the screen look beautiful. * For NVIDIA: the *NVIDIA Management Library* (*NVML*) which comes with the GPU driver. - * This queries the GPU for information. + * This queries the GPU for info. * For AMD: the libdrm library used to query AMD GPUs through the kernel driver. ## Distribution Specific Installation Process ### Ubuntu / Debian -If your distribution provides the snap utility, follow the [snap installation process](#snap) to obtain an up-to-date version of nvtop. +If your distribution provides the snap utility, follow the [snap installation process](#snap) to obtain an up-to-date version of `nvtop`. A standalone application is available as [AppImage](#appimage). @@ -161,7 +169,7 @@ - NVIDIA drivers (see [Ubuntu Wiki](https://help.ubuntu.com/community/BinaryDriverHowto/Nvidia) or [Ubuntu PPA](https://launchpad.net/~graphics-drivers/+archive/ubuntu/ppa) or [Debian Wiki](https://wiki.debian.org/NvidiaGraphicsDrivers#NVIDIA_Proprietary_Driver)) - NVTOP Dependencies - - CMake, ncurses and git + - CMake, ncurses and Git ```bash sudo apt install cmake libncurses5-dev libncursesw5-dev git ``` @@ -179,20 +187,20 @@ - ```bash sudo dnf install nvtop ``` - + #### Red Hat Enterprise Linux 8 and 9 - ```bash sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-$(rpm -E %{rhel}).noarch.rpm sudo dnf install nvtop ``` - + #### CentOS Stream, Rocky Linux, AlmaLinux - ```bash sudo dnf install -y epel-release sudo dnf install nvtop - ``` + ``` #### Build process for Fedora / Red Hat / CentOS: @@ -205,7 +213,7 @@ - NVIDIA drivers, **CUDA required for nvml libraries** (see [RPM Fusion](https://rpmfusion.org/Howto/NVIDIA)) - NVTOP Dependencies - - CMake, ncurses, c++ and git + - CMake, ncurses, C++ and Git ```bash sudo dnf install cmake ncurses-devel git gcc-c++ ``` @@ -215,7 +223,7 @@ ### OpenSUSE -A standalone application is available as [AppImage](#appimage). +A standalone application is available as an [AppImage](#appimage). Build process for OpenSUSE: @@ -228,7 +236,7 @@ - NVIDIA drivers (see [SUSE Support Database](https://en.opensuse.org/SDB:NVIDIA_drivers)) - NVTOP Dependencies - - CMake, ncurses and git + - CMake, ncurses and Git ```bash sudo zypper install cmake ncurses-devel git ``` @@ -271,7 +279,7 @@ snap install nvtop # Add the capability to kill processes inside nvtop snap connect nvtop:process-control - # Add the capability to inspect GPU info (Fan, PCIe, Power, etc) + # Add the capability to inspect GPU information (fan, PCIe, power, etc) snap connect nvtop:hardware-observe # AMDGPU process list support (read /proc/<pid>) snap connect nvtop:system-observe @@ -279,13 +287,13 @@ snap connect nvtop:kubernetes-support ``` -Notice: The connect commands allow +Notice: The connect commands allow ### Docker - NVIDIA drivers (same as above) -- [nvidia-docker](https://github.com/NVIDIA/nvidia-docker) (See [Container Toolkit Installation Guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)) +- [nvidia-docker](https://github.com/NVIDIA/nvidia-docker) (See [Container Toolkit Installation Guide](https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/install-guide.html#docker)) - ```bash git clone https://github.com/Syllo/nvtop.git && cd nvtop @@ -308,26 +316,25 @@ # make DESTDIR="/your/install/path" install ``` -If you use **conda** as environment manager and encounter an error while building nvtop, try `conda deactivate` before invoking `cmake`. +If you use **conda** as environment manager and encounter an error while building NVTOP, try `conda deactivate` before invoking `cmake`. -The build system supports multiple build type (e.g. -DCMAKE_BUILD_TYPE=RelWithDebInfo): +The build system supports multiple build types (e.g. -DCMAKE_BUILD_TYPE=RelWithDebInfo): -* Release: Binary without debug information -* RelWithDebInfo: Binary with debug information +* Release: Binary without debug info +* RelWithDebInfo: Binary with debug info * Debug: Compile with warning flags and address/undefined sanitizers enabled (for development purposes) Troubleshoot ------------ - The plot looks bad: - - Verify that you installed the wide character version of the NCurses library (libncurses**w**5-dev for Debian / Ubuntu), clean the build directory - and restart the build process. + - Verify that you installed the wide character version of the ncurses library (libncurses**w**5-dev for Debian / Ubuntu), clean the build directory and restart the build process. - **Putty**: Tell putty not to lie about its capabilities (`$TERM`) by setting the field ``Terminal-type string`` to ``putty`` in the menu ``Connection > Data > Terminal Details``. License ------- -Nvtop is licensed under the GPLV3 license or any later version. +NVTOP is licensed under the GPLv3 license or any later version. You will find a copy of the license inside the COPYING file of the repository or -at the gnu website <[www.gnu.org/licenses/](http://www.gnu.org/licenses/)>. +at the GNU website <[www.gnu.org/licenses/](http://www.gnu.org/licenses/)>. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/cmake/compile-flags-helpers.cmake new/nvtop-3.0.2+31/cmake/compile-flags-helpers.cmake --- old/nvtop-3.0.2+2/cmake/compile-flags-helpers.cmake 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/cmake/compile-flags-helpers.cmake 2023-10-21 16:57:54.000000000 +0200 @@ -1,3 +1,5 @@ +include(CheckLinkerFlag) + function(add_compiler_option_to_target_type TARGET BUILDTYPE VISIBILITY OPTIONS) include(CheckCCompilerFlag) list(APPEND OPTIONS ${ARGN}) @@ -29,7 +31,7 @@ list(APPEND OPTIONS ${ARGN}) foreach(LINK_OPTION IN LISTS OPTIONS) string(REPLACE "," "_" LINK_OPTION_NAME "${LINK_OPTION}") - check_c_compiler_flag(${LINK_OPTION} "linker_has${LINK_OPTION_NAME}") + check_linker_flag(C "${LINK_OPTION}" "linker_has${LINK_OPTION_NAME}") if (${linker_has${LINK_OPTION_NAME}}) target_link_libraries(${TARGET} ${VISIBILITY} $<$<CONFIG:${BUILDTYPE}>:${LINK_OPTION}>) @@ -42,7 +44,7 @@ list(APPEND OPTIONS ${ARGN}) foreach(LINK_OPTION IN LISTS OPTIONS) string(REPLACE "," "_" LINK_OPTION_NAME "${LINK_OPTION}") - check_c_compiler_flag(${LINK_OPTION} "linker_has${LINK_OPTION_NAME}") + check_linker_flag(C "${LINK_OPTION}" "linker_has${LINK_OPTION_NAME}") if (${linker_has${LINK_OPTION_NAME}}) target_link_libraries(${TARGET} ${VISIBILITY} $<$<NOT:$<CONFIG:${BUILDTYPE}>>:${LINK_OPTION}>) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/include/nvtop/extract_processinfo_fdinfo.h new/nvtop-3.0.2+31/include/nvtop/extract_processinfo_fdinfo.h --- old/nvtop-3.0.2+2/include/nvtop/extract_processinfo_fdinfo.h 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/include/nvtop/extract_processinfo_fdinfo.h 2023-10-21 16:57:54.000000000 +0200 @@ -50,6 +50,14 @@ void processinfo_drop_callback(const struct gpu_info *info); /** + * @brief Enables or disables a fdinfo processing callback + * + * @param info Enabling/Disabling the callback to this gpu_info + * @param enable True to enable the callback, false to disable + */ +void processinfo_enable_disable_callback_for(const struct gpu_info *info, bool enable); + +/** * @brief Scann all the processes in /proc. Call the registered callbacks on * each file descriptor to the DRM driver that can successfully be oppened. If a * callback succeeds, the gpu_info structure processes array will be updated diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/CMakeLists.txt new/nvtop-3.0.2+31/src/CMakeLists.txt --- old/nvtop-3.0.2+2/src/CMakeLists.txt 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/CMakeLists.txt 2023-10-21 16:57:54.000000000 +0200 @@ -12,13 +12,10 @@ interface_options.c interface_setup_win.c interface_ring_buffer.c - get_process_info_linux.c extract_gpuinfo.c - extract_processinfo_fdinfo.c time.c plot.c - ini.c - info_messages_linux.c) + ini.c) check_c_source_compiles( " @@ -40,6 +37,18 @@ find_package(Systemd) option(USE_LIBUDEV_OVER_LIBSYSTEMD "Use libudev, even if libsystemd is present" OFF) +if(UNIX AND NOT APPLE) + target_sources(nvtop PRIVATE + get_process_info_linux.c + extract_processinfo_fdinfo.c + info_messages_linux.c) +elseif(APPLE) + target_sources(nvtop PRIVATE + get_process_info_mac.c + extract_processinfo_mac.c + info_messages_mac.c) +endif() + if(NVIDIA_SUPPORT) target_sources(nvtop PRIVATE extract_gpuinfo_nvidia.c) endif() @@ -83,6 +92,16 @@ target_sources(nvtop PRIVATE extract_gpuinfo_intel.c) endif() +if(APPLE_SUPPORT) + target_sources(nvtop PRIVATE extract_gpuinfo_apple.m) + target_link_libraries(nvtop PRIVATE + "-framework Metal" + "-framework AppKit" + "-framework Foundation" + "-framework QuartzCore" + "-framework IOKit") +endif() + target_include_directories(nvtop PRIVATE ${PROJECT_SOURCE_DIR}/include ${PROJECT_BINARY_DIR}/include) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_amdgpu.c new/nvtop-3.0.2+31/src/extract_gpuinfo_amdgpu.c --- old/nvtop-3.0.2+2/src/extract_gpuinfo_amdgpu.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_amdgpu.c 2023-10-21 16:57:54.000000000 +0200 @@ -80,9 +80,9 @@ static char didnt_call_gpuinfo_init[] = "uninitialized"; static const char *local_error_string = didnt_call_gpuinfo_init; -#define HASH_FIND_CLIENT(head, key_ptr, out_ptr) HASH_FIND(hh, head, key_ptr, sizeof(unsigned), out_ptr) +#define HASH_FIND_CLIENT(head, key_ptr, out_ptr) HASH_FIND(hh, head, key_ptr, sizeof(struct unique_cache_id), out_ptr) -#define HASH_ADD_CLIENT(head, in_ptr) HASH_ADD(hh, head, client_id, sizeof(unsigned), in_ptr) +#define HASH_ADD_CLIENT(head, in_ptr) HASH_ADD(hh, head, client_id, sizeof(struct unique_cache_id), in_ptr) #define SET_AMDGPU_CACHE(cachePtr, field, value) SET_VALUE(cachePtr, field, value, amdgpu_cache_) #define RESET_AMDGPU_CACHE(cachePtr, field) INVALIDATE_VALUE(cachePtr, field, amdgpu_cache_) @@ -962,7 +962,7 @@ #ifndef NDEBUG // We should only process one fdinfo entry per client id per update struct amdgpu_process_info_cache *cache_entry_check; - HASH_FIND_CLIENT(gpu_info->current_update_process_cache, &cid, cache_entry_check); + HASH_FIND_CLIENT(gpu_info->current_update_process_cache, &cache_entry->client_id, cache_entry_check); assert(!cache_entry_check && "We should not be processing a client id twice per update"); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_amdgpu_utils.c new/nvtop-3.0.2+31/src/extract_gpuinfo_amdgpu_utils.c --- old/nvtop-3.0.2+2/src/extract_gpuinfo_amdgpu_utils.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_amdgpu_utils.c 2023-10-21 16:57:54.000000000 +0200 @@ -23,6 +23,8 @@ #include "amdgpu_ids.h" +const char *amdgpu_parse_marketing_name(struct amdgpu_gpu_info *info); + const char * amdgpu_parse_marketing_name(struct amdgpu_gpu_info *info) { int i; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_apple.m new/nvtop-3.0.2+31/src/extract_gpuinfo_apple.m --- old/nvtop-3.0.2+2/src/extract_gpuinfo_apple.m 1970-01-01 01:00:00.000000000 +0100 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_apple.m 2023-10-21 16:57:54.000000000 +0200 @@ -0,0 +1,241 @@ +/* + * Copyright (C) 2023 Robin Voetter <ro...@voetter.nl> + * + * This file is part of Nvtop. + * + * Nvtop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Nvtop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with nvtop. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "nvtop/common.h" +#include "nvtop/device_discovery.h" +#include "nvtop/extract_gpuinfo_common.h" +#include "nvtop/time.h" + +#include <assert.h> +#include <Metal/Metal.h> +#include <IOKit/IOKitLib.h> +#include <QuartzCore/QuartzCore.h> + +struct gpu_info_apple { + struct gpu_info base; + id<MTLDevice> device; + io_service_t gpu_service; +}; + +static bool gpuinfo_apple_init(void); +static void gpuinfo_apple_shutdown(void); +static const char *gpuinfo_apple_last_error_string(void); +static bool gpuinfo_apple_get_device_handles(struct list_head *devices, unsigned *count); +static void gpuinfo_apple_populate_static_info(struct gpu_info *_gpu_info); +static void gpuinfo_apple_refresh_dynamic_info(struct gpu_info *_gpu_info); +static void gpuinfo_apple_get_running_processes(struct gpu_info *_gpu_info); + +static struct gpu_vendor gpu_vendor_apple = { + .init = gpuinfo_apple_init, + .shutdown = gpuinfo_apple_shutdown, + .last_error_string = gpuinfo_apple_last_error_string, + .get_device_handles = gpuinfo_apple_get_device_handles, + .populate_static_info = gpuinfo_apple_populate_static_info, + .refresh_dynamic_info = gpuinfo_apple_refresh_dynamic_info, + .refresh_running_processes = gpuinfo_apple_get_running_processes, + .name = "apple", +}; + +static unsigned apple_gpu_count; +static struct gpu_info_apple *gpu_infos; + +__attribute__((constructor)) static void init_extract_gpuinfo_apple(void) { register_gpu_vendor(&gpu_vendor_apple); } + +static bool gpuinfo_apple_init(void) { + apple_gpu_count = 0; + gpu_infos = NULL; + return true; +} + +static void gpuinfo_apple_shutdown(void) { + for (unsigned i = 0; i < apple_gpu_count; ++i) { + struct gpu_info_apple *gpu_info = &gpu_infos[i]; + [gpu_info->device release]; + IOObjectRelease(gpu_info->gpu_service); + } + + free(gpu_infos); + gpu_infos = NULL; + apple_gpu_count = 0; +} + +static const char *gpuinfo_apple_last_error_string(void) { + return "An unanticipated error occurred while accessing Apple " + "information\n"; +} + +static bool gpuinfo_apple_get_device_handles(struct list_head *devices, unsigned *count) { + NSArray<id<MTLDevice>> *mtl_devices = MTLCopyAllDevices(); + + const unsigned mtl_count = [mtl_devices count]; + gpu_infos = calloc(mtl_count, sizeof(*gpu_infos)); + for (unsigned int i = 0; i < mtl_count; ++i) { + id<MTLDevice> dev = mtl_devices[i]; + const uint64_t registry_id = [dev registryID]; + const io_service_t gpu_service = IOServiceGetMatchingService(kIOMainPortDefault, IORegistryEntryIDMatching(registry_id)); + assert(MACH_PORT_VALID(gpu_service)); + + gpu_infos[apple_gpu_count].base.vendor = &gpu_vendor_apple; + gpu_infos[apple_gpu_count].device = dev; + gpu_infos[i].gpu_service = gpu_service; + list_add_tail(&gpu_infos[apple_gpu_count].base.list, devices); + ++apple_gpu_count; + } + + *count = apple_gpu_count; + + [mtl_devices release]; + return true; +} + +static void gpuinfo_apple_populate_static_info(struct gpu_info *_gpu_info) { + struct gpu_info_apple *gpu_info = container_of(_gpu_info, struct gpu_info_apple, base); + struct gpuinfo_static_info *static_info = &gpu_info->base.static_info; + RESET_ALL(static_info->valid); + + const char *name = [[gpu_info->device name] UTF8String]; + strncpy(static_info->device_name, name, sizeof(static_info->device_name)); + SET_VALID(gpuinfo_device_name_valid, static_info->valid); + + static_info->integrated_graphics = [gpu_info->device location] == MTLDeviceLocationBuiltIn; +} + +static void gpuinfo_apple_refresh_dynamic_info(struct gpu_info *_gpu_info) { + struct gpu_info_apple *gpu_info = container_of(_gpu_info, struct gpu_info_apple, base); + struct gpuinfo_dynamic_info *dynamic_info = &gpu_info->base.dynamic_info; + RESET_ALL(dynamic_info->valid); + + CFMutableDictionaryRef cf_props; + if (IORegistryEntryCreateCFProperties(gpu_info->gpu_service, &cf_props, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { + return; + } + NSDictionary *props = (__bridge NSDictionary*) cf_props; + NSDictionary *performance_statistics = [props objectForKey:@"PerformanceStatistics"]; + if (!performance_statistics) { + return; + } + + id device_utilization_info = [performance_statistics objectForKey:@"Device Utilization %"]; + if (device_utilization_info != nil) { + const uint64_t gpu_util_rate = [device_utilization_info integerValue]; + SET_GPUINFO_DYNAMIC(dynamic_info, gpu_util_rate, gpu_util_rate); + } + + if ([gpu_info->device hasUnifiedMemory]) { + // [gpu_info->device currentAllocatedSize] returns the amount of memory allocated by this process, not + // as allocated on the GPU globally. The performance statistics dictionary has the real value that we + // are interested in, the amount of system memory allocated by the GPU. + id system_memory_info = [performance_statistics objectForKey:@"Alloc system memory"]; + if (system_memory_info != nil) { + const uint64_t mem_used = [system_memory_info integerValue]; + SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, mem_used); + } + + // Memory is unified, so query the amount of system memory instead. + mach_msg_type_number_t host_size = HOST_BASIC_INFO_COUNT; + host_basic_info_data_t info; + if (host_info(mach_host_self(), HOST_BASIC_INFO, (host_info_t) &info, &host_size) == KERN_SUCCESS) { + SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, info.max_mem); + } + } else { + // TODO: Figure out how to get used memory for this case. + + // It does not really seem to be possible to get the amount of memory of a particular GPU. + // In this case, just get the recommended working set size. This is what MoltenVK also does. + const uint64_t mem_total = [gpu_info->device recommendedMaxWorkingSetSize]; + SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, mem_total); + } + + CFRelease(props); + + if (GPUINFO_DYNAMIC_FIELD_VALID(dynamic_info, used_memory) && GPUINFO_DYNAMIC_FIELD_VALID(dynamic_info, total_memory)) { + SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, dynamic_info->total_memory - dynamic_info->used_memory); + SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, + (dynamic_info->total_memory - dynamic_info->free_memory) * 100 / dynamic_info->total_memory); + + } +} + +static bool gpuinfo_apple_get_process_info(struct gpu_process* process, io_object_t user_client) { + RESET_ALL(process->valid); + process->type = gpu_process_graphical_compute; + + CFMutableDictionaryRef cf_props; + if (IORegistryEntryCreateCFProperties(user_client, &cf_props, kCFAllocatorDefault, kNilOptions) != kIOReturnSuccess) { + return false; + } + NSDictionary* user_client_info = (__bridge NSDictionary*) cf_props; + + id client_creator_info = [user_client_info objectForKey:@"IOUserClientCreator"]; + if (client_creator_info == nil) { + return false; + } + + const char* client_creator = [client_creator_info UTF8String]; + // Client creator is in form: pid <pid>, <name> + if (sscanf(client_creator, "pid %u,", &process->pid) < 1) { + return false; + } + + CFRelease(cf_props); + + return true; +} + +static void gpuinfo_apple_get_running_processes(struct gpu_info *_gpu_info) { + struct gpu_info_apple *gpu_info = container_of(_gpu_info, struct gpu_info_apple, base); + _gpu_info->processes_count = 0; + + // We can find out which processes are running on a particular GPU using the IO Registry. The + // IOService associated to the MTLDevice has "AGXDeviceUserClient" child nodes, which hold some + // basic information about processes that are running on the GPU. + + io_iterator_t iterator; + if (IORegistryEntryGetChildIterator(gpu_info->gpu_service, kIOServicePlane, &iterator) != kIOReturnSuccess) { + return; + } + + unsigned int count = 0; + for (io_object_t child = IOIteratorNext(iterator); child; child = IOIteratorNext(iterator)) { + io_name_t class_name; + if (IOObjectGetClass(child, class_name) != kIOReturnSuccess) { + continue; + } else if (strncmp(class_name, "AGXDeviceUserClient", sizeof(class_name)) != 0) { + continue; + } + + if (_gpu_info->processes_array_size < count + 1) { + _gpu_info->processes_array_size += COMMON_PROCESS_LINEAR_REALLOC_INC; + _gpu_info->processes = reallocarray(_gpu_info->processes, _gpu_info->processes_array_size, sizeof(*_gpu_info->processes)); + if (!_gpu_info->processes) { + perror("Could not allocate memory: "); + exit(EXIT_FAILURE); + } + } + + if (gpuinfo_apple_get_process_info(&_gpu_info->processes[count], child)) { + ++count; + } + + IOObjectRelease(child); + } + + _gpu_info->processes_count = count; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_intel.c new/nvtop-3.0.2+31/src/extract_gpuinfo_intel.c --- old/nvtop-3.0.2+2/src/extract_gpuinfo_intel.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_intel.c 2023-10-21 16:57:54.000000000 +0200 @@ -29,8 +29,8 @@ #include <string.h> #include <uthash.h> -#define HASH_FIND_CLIENT(head, key_ptr, out_ptr) HASH_FIND(hh, head, key_ptr, sizeof(unsigned), out_ptr) -#define HASH_ADD_CLIENT(head, in_ptr) HASH_ADD(hh, head, client_id, sizeof(unsigned), in_ptr) +#define HASH_FIND_CLIENT(head, key_ptr, out_ptr) HASH_FIND(hh, head, key_ptr, sizeof(struct unique_cache_id), out_ptr) +#define HASH_ADD_CLIENT(head, in_ptr) HASH_ADD(hh, head, client_id, sizeof(struct unique_cache_id), in_ptr) #define SET_INTEL_CACHE(cachePtr, field, value) SET_VALUE(cachePtr, field, value, intel_cache_) #define RESET_INTEL_CACHE(cachePtr, field) INVALIDATE_VALUE(cachePtr, field, intel_cache_) @@ -226,7 +226,7 @@ #ifndef NDEBUG // We should only process one fdinfo entry per client id per update struct intel_process_info_cache *cache_entry_check; - HASH_FIND_CLIENT(gpu_info->current_update_process_cache, &cid, cache_entry_check); + HASH_FIND_CLIENT(gpu_info->current_update_process_cache, &cache_entry->client_id, cache_entry_check); assert(!cache_entry_check && "We should not be processing a client id twice per update"); #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_msm.c new/nvtop-3.0.2+31/src/extract_gpuinfo_msm.c --- old/nvtop-3.0.2+2/src/extract_gpuinfo_msm.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_msm.c 2023-10-21 16:57:54.000000000 +0200 @@ -95,6 +95,7 @@ static struct gpu_info_msm *gpu_infos; static void *libdrm_handle; +static FILE* meminfo_file = NULL; static int last_libdrm_return_status = 0; static char didnt_call_gpuinfo_init[] = "uninitialized"; @@ -194,6 +195,8 @@ goto init_error_clean_exit; local_error_string = NULL; + + meminfo_file = fopen("/proc/meminfo", "r"); return true; init_error_clean_exit: @@ -217,6 +220,11 @@ libdrm_handle = NULL; local_error_string = didnt_call_gpuinfo_init; } + + if (meminfo_file) { + fclose(meminfo_file); + meminfo_file = NULL; + } } static const char *gpuinfo_msm_last_error_string(void) { @@ -243,6 +251,23 @@ } } +static uint64_t parse_memory_multiplier(const char *str) { + if (strcmp(str, " B") == 0) { + return 1; + } + else if (strcmp(str, " KiB") == 0 || strcmp(str, " kB") == 0) { + return 1024; + } + else if (strcmp(str, " MiB") == 0) { + return 1024 * 1024; + } + else if (strcmp(str, " GiB") == 0) { + return 1024 * 1024 * 1024; + } + + return 1; +} + static const char drm_msm_engine_gpu[] = "drm-engine-gpu"; static const char drm_msm_cycles_gpu[] = "drm-cycles-gpu"; static const char drm_msm_maxfreq_gpu[] = "drm-maxfreq-gpu"; @@ -298,20 +323,7 @@ if (endptr == val) continue; - uint64_t multiplier = 1; - if (strcmp(endptr, " B") == 0) { - multiplier = 1; - } - else if (strcmp(endptr, " KiB") == 0) { - multiplier = 1024; - } - else if (strcmp(endptr, " MiB") == 0) { - multiplier = 1024 * 1024; - } - else if (strcmp(endptr, " GiB") == 0) { - multiplier = 1024 * 1024 * 1024; - } - + uint64_t multiplier = parse_memory_multiplier(endptr); SET_GPUINFO_PROCESS(process_info, gpu_memory_usage, mem_int * multiplier); } } @@ -452,7 +464,6 @@ void gpuinfo_msm_populate_static_info(struct gpu_info *_gpu_info) { struct gpu_info_msm *gpu_info = container_of(_gpu_info, struct gpu_info_msm, base); struct gpuinfo_static_info *static_info = &gpu_info->base.static_info; - const char *dev_name; static_info->integrated_graphics = true; RESET_ALL(static_info->valid); @@ -470,20 +481,24 @@ } } + +static const char meminfo_total[] = "MemTotal"; +static const char meminfo_available[] = "MemAvailable"; + void gpuinfo_msm_refresh_dynamic_info(struct gpu_info *_gpu_info) { struct gpu_info_msm *gpu_info = container_of(_gpu_info, struct gpu_info_msm, base); - struct gpuinfo_static_info *static_info = &gpu_info->base.static_info; + // struct gpuinfo_static_info *static_info = &gpu_info->base.static_info; struct gpuinfo_dynamic_info *dynamic_info = &gpu_info->base.dynamic_info; RESET_ALL(dynamic_info->valid); dynamic_info->encode_decode_shared = true; // GPU clock - uint64_t val; - if (gpuinfo_msm_query_param(gpu_info->fd, MSM_PARAM_MAX_FREQ, &val) == 0) { + uint64_t clock_val; + if (gpuinfo_msm_query_param(gpu_info->fd, MSM_PARAM_MAX_FREQ, &clock_val) == 0) { // TODO: No way to query current clock speed. - SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, val / 1000000); - SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed_max, val / 1000000); + SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed, clock_val / 1000000); + SET_GPUINFO_DYNAMIC(dynamic_info, gpu_clock_speed_max, clock_val / 1000000); } // Mem clock @@ -492,14 +507,51 @@ // TODO: find how to extract global utilization // gpu util will be computed as the sum of all the processes utilization for now - struct sysinfo info; - if (sysinfo(&info) == 0) { - SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, info.totalram); - SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, info.totalram - info.freeram); - SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, info.freeram); - SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, - (dynamic_info->total_memory - dynamic_info->free_memory) * 100 / dynamic_info->total_memory); + rewind(meminfo_file); + fflush(meminfo_file); + static char *line = NULL; + static size_t line_buf_size = 0; + ssize_t count = 0; + uint64_t mem_total = 0; + uint64_t mem_available = 0; + size_t keys_acquired = 0; + while (keys_acquired != 2 && (count = getline(&line, &line_buf_size, meminfo_file)) != -1) { + char *key, *val; + // Get rid of the newline if present + if (line[count - 1] == '\n') { + line[--count] = '\0'; + } + + if (!extract_drm_fdinfo_key_value(line, &key, &val)) + continue; + + bool is_total = !strcmp(key, meminfo_total); + bool is_available = !strcmp(key, meminfo_available); + + if (is_total || is_available) { + uint64_t mem_int; + char *endptr; + + mem_int = strtoull(val, &endptr, 10); + if (endptr == val) + continue; + + mem_int *= parse_memory_multiplier(endptr); + if (is_total) { + mem_total = mem_int; + } + else if (is_available) { + mem_available = mem_int; + } + ++keys_acquired; + } } + + SET_GPUINFO_DYNAMIC(dynamic_info, total_memory, mem_total); + SET_GPUINFO_DYNAMIC(dynamic_info, used_memory, mem_total - mem_available); + SET_GPUINFO_DYNAMIC(dynamic_info, free_memory, mem_available); + SET_GPUINFO_DYNAMIC(dynamic_info, mem_util_rate, + (dynamic_info->total_memory - dynamic_info->free_memory) * 100 / dynamic_info->total_memory); } static void swap_process_cache_for_next_update(struct gpu_info_msm *gpu_info) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_gpuinfo_msm_utils.c new/nvtop-3.0.2+31/src/extract_gpuinfo_msm_utils.c --- old/nvtop-3.0.2+2/src/extract_gpuinfo_msm_utils.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_gpuinfo_msm_utils.c 2023-10-21 16:57:54.000000000 +0200 @@ -63,17 +63,21 @@ {CHIPID(540), "Adreno 540"}, // Adreno 6xx - {CHIPID(615), "Adreno 615"}, - {CHIPID(616), "Adreno 616"}, - {CHIPID(618), "Adreno 618"}, - {CHIPID(619), "Adreno 619"}, - {CHIPID(620), "Adreno 620"}, - {CHIPID(630), "Adreno 630"}, - {CHIPID(640), "Adreno 640"}, - {CHIPID(650), "Adreno 650"}, - {CHIPID(660), "Adreno 660"}, - {CHIPID(680), "Adreno 680"}, - {CHIPID(690), "Adreno 690"}, + {CHIPID(615), "Adreno 615"}, + {CHIPID(616), "Adreno 616"}, + {CHIPID(618), "Adreno 618"}, + {CHIPID(619), "Adreno 619"}, + {CHIPID(620), "Adreno 620"}, + {CHIPID(630), "Adreno 630"}, + {CHIPID(640), "Adreno 640"}, + // QCM6490 + {0x00ac06030500, "Adreno 643"}, + {CHIPID(650), "Adreno 650"}, + {CHIPID(660), "Adreno 660"}, + {CHIPID(680), "Adreno 680"}, + {CHIPID(690), "Adreno 690"}, + // no-speedbin Adreno 690 + {0xffff06090000, "Adreno 690"}, // Adreno 7xx {CHIPID(730), "Adreno 730"}, @@ -85,6 +89,8 @@ {0x006006030500, "Adreno 7c+ Gen 3 Lite"}, }; +const char * msm_parse_marketing_name(uint64_t gpu_id); + const char * msm_parse_marketing_name(uint64_t gpu_id) { for (unsigned i = 0; i < ARRAY_SIZE(msm_ids); i++) { if (gpu_id == msm_ids[i].id) { diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_processinfo_fdinfo.c new/nvtop-3.0.2+31/src/extract_processinfo_fdinfo.c --- old/nvtop-3.0.2+2/src/extract_processinfo_fdinfo.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/extract_processinfo_fdinfo.c 2023-10-21 16:57:54.000000000 +0200 @@ -21,6 +21,7 @@ #include "nvtop/extract_processinfo_fdinfo.h" #include "nvtop/common.h" +#include "nvtop/extract_gpuinfo_common.h" #include <ctype.h> #include <dirent.h> @@ -38,6 +39,7 @@ struct callback_entry { struct gpu_info *gpu_info; processinfo_fdinfo_callback callback; + bool active; }; static unsigned registered_callback_entries; @@ -66,9 +68,18 @@ } callback_entries[registered_callback_entries].gpu_info = info; callback_entries[registered_callback_entries].callback = callback; + callback_entries[registered_callback_entries].active = true; registered_callback_entries++; } +void processinfo_enable_disable_callback_for(const struct gpu_info *info, bool enable) { + for (unsigned index = 0; index < registered_callback_entries; ++index) { + if (callback_entries[index].gpu_info == info) { + callback_entries[index].active = enable; + } + } +} + static bool is_drm_fd(int fd_dir_fd, const char *name) { struct stat stat; int ret; @@ -83,7 +94,12 @@ #define DRM_FD_LINEAR_REALLOC_INC 8 void processinfo_sweep_fdinfos(void) { - if (registered_callback_entries == 0) + bool anyActiveCallback = false; + for (unsigned callback_idx = 0; !anyActiveCallback && callback_idx < registered_callback_entries; ++callback_idx) { + struct callback_entry *current_callback = &callback_entries[callback_idx]; + anyActiveCallback = anyActiveCallback || current_callback->active; + } + if (!anyActiveCallback) return; DIR *proc_dir = opendir("/proc"); @@ -178,7 +194,10 @@ RESET_ALL(processes_info_local.valid); processes_info_local.type = gpu_process_unknown; current_callback = &callback_entries[callback_idx]; - callback_success = current_callback->callback(current_callback->gpu_info, fdinfo_file, &processes_info_local); + if (current_callback->active) + callback_success = current_callback->callback(current_callback->gpu_info, fdinfo_file, &processes_info_local); + else + callback_success = false; } fclose(fdinfo_file); if (!callback_success) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/extract_processinfo_mac.c new/nvtop-3.0.2+31/src/extract_processinfo_mac.c --- old/nvtop-3.0.2+2/src/extract_processinfo_mac.c 1970-01-01 01:00:00.000000000 +0100 +++ new/nvtop-3.0.2+31/src/extract_processinfo_mac.c 2023-10-21 16:57:54.000000000 +0200 @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2023 Robin Voetter <ro...@voetter.nl> + * + * This file is part of Nvtop. + * + * Nvtop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Nvtop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with nvtop. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "nvtop/extract_processinfo_fdinfo.h" + +void processinfo_drop_callback(const struct gpu_info *info) { + (void) info; +} + +void processinfo_register_fdinfo_callback(processinfo_fdinfo_callback callback, struct gpu_info *info) { + (void) callback; + (void) info; +} + +void processinfo_sweep_fdinfos(void) { +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/get_process_info_mac.c new/nvtop-3.0.2+31/src/get_process_info_mac.c --- old/nvtop-3.0.2+2/src/get_process_info_mac.c 1970-01-01 01:00:00.000000000 +0100 +++ new/nvtop-3.0.2+31/src/get_process_info_mac.c 2023-10-21 16:57:54.000000000 +0200 @@ -0,0 +1,137 @@ +/* + * + * Copyright (C) 2023 Robin Voetter <ro...@voetter.nl> + * + * This file is part of Nvtop. + * + * Nvtop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Nvtop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with nvtop. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "nvtop/get_process_info.h" + +#include <libproc.h> +#include <sys/sysctl.h> +#include <pwd.h> +#include <mach/mach_time.h> + +#include <string.h> +#include <stdio.h> + +void get_username_from_pid(pid_t pid, char **buffer) { + struct proc_bsdshortinfo proc; + const int st = proc_pidinfo(pid, PROC_PIDT_SHORTBSDINFO, 0, &proc, PROC_PIDT_SHORTBSDINFO_SIZE); + if (st != PROC_PIDT_SHORTBSDINFO_SIZE) { + goto error; + } + + struct passwd *user_info = getpwuid(proc.pbsi_uid); + if (user_info == NULL) { + goto error; + } + + const size_t namelen = strlen(user_info->pw_name) + 1; + *buffer = malloc(namelen * sizeof(**buffer)); + strncpy(*buffer, user_info->pw_name, namelen); + return; +error: + *buffer = NULL; +} + +void get_command_from_pid(pid_t pid, char **buffer) { + // See https://chromium.googlesource.com/crashpad/crashpad/+/360e441c53ab4191a6fd2472cc57c3343a2f6944/util/posix/process_util_mac.cc + size_t argmax; + size_t argmax_estimate; + char *procargs = NULL; + int tries = 3; + do { + int mib[] = {CTL_KERN, KERN_PROCARGS2, pid}; + if (sysctl(mib, 3, NULL, &argmax_estimate, NULL, 0) != 0) { + goto error_free_procargs; + } + + argmax = argmax_estimate + 1; + procargs = realloc(procargs, argmax); + if (sysctl(mib, 3, procargs, &argmax, NULL, 0) != 0) { + goto error_free_procargs; + } + } while (argmax == argmax_estimate + 1 && --tries != 0); + + unsigned argc; + memcpy(&argc, procargs, sizeof(argc)); + + size_t i = sizeof(argc); + // Skip executable path. + while (i < argmax && procargs[i] != 0) { + ++i; + } + // Find the first string + while (i < argmax && procargs[i] == 0) { + ++i; + } + + const size_t argv0 = i; + // Count the total size of the args by finding the end. + for (unsigned int arg = 0; arg < argc && i < argmax; ++arg) { + while (i < argmax && procargs[i] != 0) { + ++i; + } + ++i; // We are going to replace this null character with a space (or a null in the case of the last). + } + const size_t args_size = i - argv0; + if (args_size == 0) { + goto error_free_procargs; + } + char* args = malloc(args_size); + *buffer = args; + + i = argv0; + for (unsigned int arg = 0; arg < argc && i < argmax; ++arg) { + while (i < argmax && procargs[i] != 0) { + *args++ = procargs[i++]; + } + *args++ = ' '; + ++i; + } + args[-1] = 0; + + free(procargs); + return; +error_free_procargs: + free(procargs); + *buffer = NULL; + return; +} + +bool get_process_info(pid_t pid, struct process_cpu_usage *usage) { + struct proc_taskinfo proc; + const int st = proc_pidinfo(pid, PROC_PIDTASKINFO, 0, &proc, PROC_PIDTASKINFO_SIZE); + if (st != PROC_PIDTASKINFO_SIZE) { + return false; + } + + nvtop_get_current_time(&usage->timestamp); + + // TODO: Should we implement this workaround? + // https://github.com/htop-dev/htop/blob/main/darwin/PlatformHelpers.c#L98 + mach_timebase_info_data_t info; + mach_timebase_info(&info); + const double nanoseconds_per_tick = (double)info.numer / (double)info.denom; + + usage->total_user_time = (proc.pti_total_user * nanoseconds_per_tick) / 1000000000.0; + usage->total_kernel_time = (proc.pti_total_system * nanoseconds_per_tick) / 1000000000.0; + usage->virtual_memory = proc.pti_virtual_size; + usage->resident_memory = proc.pti_resident_size; + return true; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/info_messages_linux.c new/nvtop-3.0.2+31/src/info_messages_linux.c --- old/nvtop-3.0.2+2/src/info_messages_linux.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/info_messages_linux.c 2023-10-21 16:57:54.000000000 +0200 @@ -40,8 +40,8 @@ static char *allMessages[] = { "Nvtop won't be able to show AMD GPU processes on your kernel version (requires Linux >= 5.14)", "Nvtop won't be able to show Intel GPU utilization and processes on your kernel version (requires Linux >= 5.19)", - "This version of Nvtop is missing support for reporting Intel GPU memory, power, fan and temperature", - "This version of Nvtop is missing support for reporting MSM power, fan and temperature", + "This version of Nvtop does not yet support reporting all data for Intel GPUs, such as memory, power, fan and temperature information", + "This version of Nvtop does not yet support reporting all data for MSM GPUs, such as power, fan and temperature information", }; static const char *message_array[sizeof(allMessages) / sizeof(*allMessages)]; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/info_messages_mac.c new/nvtop-3.0.2+31/src/info_messages_mac.c --- old/nvtop-3.0.2+2/src/info_messages_mac.c 1970-01-01 01:00:00.000000000 +0100 +++ new/nvtop-3.0.2+31/src/info_messages_mac.c 2023-10-21 16:57:54.000000000 +0200 @@ -0,0 +1,29 @@ +/* + * + * Copyright (C) 2023 Robin Voetter <ro...@voetter.nl> + * + * This file is part of Nvtop. + * + * Nvtop is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Nvtop is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with nvtop. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include "list.h" +#include "nvtop/info_messages.h" + +void get_info_messages(struct list_head *devices, unsigned *num_messages, const char ***messages) { + (void) devices; + (void) messages; + *num_messages = 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/interface.c new/nvtop-3.0.2+31/src/interface.c --- old/nvtop-3.0.2+2/src/interface.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/interface.c 2023-10-21 16:57:54.000000000 +0200 @@ -1341,8 +1341,8 @@ "SIGXFSZ", "SIGVTALRM", "SIGPROF", "SIGWINCH", "SIGIO", "SIGPWR", "SIGSYS", }; -// SIGPWR does not exist on FreeBSD, while it is a synonym for SIGINFO on Linux -#ifdef __FreeBSD__ +// SIGPWR does not exist on FreeBSD or Apple, while it is a synonym for SIGINFO on Linux +#if defined(__FreeBSD__) || defined(__APPLE__) #define SIGPWR SIGINFO #endif diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/nvtop-3.0.2+2/src/interface_options.c new/nvtop-3.0.2+31/src/interface_options.c --- old/nvtop-3.0.2+2/src/interface_options.c 2023-06-15 11:47:30.000000000 +0200 +++ new/nvtop-3.0.2+31/src/interface_options.c 2023-10-21 16:57:54.000000000 +0200 @@ -21,6 +21,7 @@ #include "nvtop/interface_options.h" #include "ini.h" +#include "nvtop/extract_processinfo_fdinfo.h" #include "nvtop/interface_common.h" #include <assert.h> @@ -98,6 +99,8 @@ options->gpu_specific_opts[0].doNotMonitor = false; numMonitored++; } + list_for_each_entry(device, monitoredGpu, list) { processinfo_enable_disable_callback_for(device, true); } + list_for_each_entry(device, nonMonitoredGpu, list) { processinfo_enable_disable_callback_for(device, false); } return numMonitored; } ++++++ nvtop.obsinfo ++++++ --- /var/tmp/diff_new_pack.m9hba4/_old 2023-10-25 18:06:09.237165165 +0200 +++ /var/tmp/diff_new_pack.m9hba4/_new 2023-10-25 18:06:09.237165165 +0200 @@ -1,5 +1,5 @@ name: nvtop -version: 3.0.2+2 -mtime: 1686822450 -commit: 9a8458b541a195a0c5cadafb66e240962c852b39 +version: 3.0.2+31 +mtime: 1697900274 +commit: 45a1796375cd617d16167869bb88e5e69c809468