Edit

kc3-lang/angle/src/gpu_info_util/SystemInfo_libpci.cpp

Branch :

  • Show log

    Commit

  • Author : Frank Henigman
    Date : 2017-05-03 23:32:29
    Hash : aa7203ef
    Message : Inherit privately from angle::NonCopyable. Make all inheritance from angle::NonCopyable private so the compiler complains about this (admittedly unlikely) code: class Foo: angle::NonCopyable { virtual ~Foo() { ... } }; angle::NonCopyable *p = new Foo; delete p; In the above code ~Foo() is not called, only ~NonCopyable(), because the latter is not virtual. Making it virtual would add overhead to all derived classes which don't already have a virtual method. Also tighten access in NonCopyable, because we can. BUG=angleproject:2026 Change-Id: Id0dc4d959cfb7bb82cf49382118129abb1d3a4f0 Reviewed-on: https://chromium-review.googlesource.com/495352 Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Corentin Wallez <cwallez@chromium.org> Commit-Queue: Frank Henigman <fjhenigman@chromium.org>

  • src/gpu_info_util/SystemInfo_libpci.cpp
  • //
    // Copyright (c) 2013-2017 The ANGLE Project Authors. All rights reserved.
    // Use of this source code is governed by a BSD-style license that can be
    // found in the LICENSE file.
    //
    
    // SystemInfo_libpci.cpp: implementation of the libPCI-specific parts of SystemInfo.h
    
    #include "gpu_info_util/SystemInfo_internal.h"
    
    #include <dlfcn.h>
    #include <pci/pci.h>
    #include <unistd.h>
    
    #include "common/angleutils.h"
    #include "common/debug.h"
    
    #if !defined(GPU_INFO_USE_LIBPCI)
    #error SystemInfo_libpci.cpp compiled without GPU_INFO_USE_LIBPCI
    #endif
    
    namespace angle
    {
    
    namespace
    {
    
    struct LibPCI : private angle::NonCopyable
    {
        LibPCI()
        {
            if (access("/sys/bus/pci/", F_OK) != 0 && access("/sys/bs/pci_express/", F_OK) != 0)
            {
                return;
            }
    
            mHandle = dlopen("libpci.so.3", RTLD_LAZY);
    
            if (mHandle == nullptr)
            {
                mHandle = dlopen("libpci.so", RTLD_LAZY);
            }
    
            if (mHandle == nullptr)
            {
                return;
            }
    
            mValid =
                (Alloc = reinterpret_cast<decltype(Alloc)>(dlsym(mHandle, "pci_alloc"))) != nullptr &&
                (Init = reinterpret_cast<decltype(Init)>(dlsym(mHandle, "pci_init"))) != nullptr &&
                (Cleanup = reinterpret_cast<decltype(Cleanup)>(dlsym(mHandle, "pci_cleanup"))) !=
                    nullptr &&
                (ScanBus = reinterpret_cast<decltype(ScanBus)>(dlsym(mHandle, "pci_scan_bus"))) !=
                    nullptr &&
                (FillInfo = reinterpret_cast<decltype(FillInfo)>(dlsym(mHandle, "pci_fill_info"))) !=
                    nullptr &&
                (LookupName = reinterpret_cast<decltype(LookupName)>(
                     dlsym(mHandle, "pci_lookup_name"))) != nullptr;
        }
    
        bool IsValid() const { return mValid; }
    
        ~LibPCI()
        {
            if (mHandle != nullptr)
            {
                dlclose(mHandle);
            }
        }
    
        decltype(&::pci_alloc) Alloc            = nullptr;
        decltype(&::pci_init) Init              = nullptr;
        decltype(&::pci_cleanup) Cleanup        = nullptr;
        decltype(&::pci_scan_bus) ScanBus       = nullptr;
        decltype(&::pci_fill_info) FillInfo     = nullptr;
        decltype(&::pci_lookup_name) LookupName = nullptr;
    
      private:
        void *mHandle = nullptr;
        bool mValid   = false;
    };
    
    }  // anonymous namespace
    
    // Adds an entry per PCI GPU found and fills the device and vendor ID.
    bool GetPCIDevicesWithLibPCI(std::vector<GPUDeviceInfo> *devices)
    {
        LibPCI pci;
        if (!pci.IsValid())
        {
            return false;
        }
    
        pci_access *access = pci.Alloc();
        ASSERT(access != nullptr);
        pci.Init(access);
        pci.ScanBus(access);
    
        for (pci_dev *device = access->devices; device != nullptr; device = device->next)
        {
            pci.FillInfo(device, PCI_FILL_IDENT | PCI_FILL_CLASS);
    
            // Skip non-GPU devices
            switch (device->device_class)
            {
                case PCI_CLASS_DISPLAY_VGA:
                case PCI_CLASS_DISPLAY_XGA:
                case PCI_CLASS_DISPLAY_3D:
                    break;
                default:
                    continue;
            }
    
            // Skip unknown devices
            if (device->vendor_id == 0 || device->device_id == 0)
            {
                continue;
            }
    
            GPUDeviceInfo info;
            info.vendorId = device->vendor_id;
            info.deviceId = device->device_id;
    
            devices->push_back(info);
        }
    
        pci.Cleanup(access);
    
        return true;
    }
    }