Start nvidia module

This commit is contained in:
jussi 2019-09-17 22:54:07 +03:00
parent d8a013dcba
commit b15bd8c105
10 changed files with 169 additions and 11 deletions

View File

@ -1,3 +1,7 @@
project('tuxclocker')
cc = meson.get_compiler('c')
incdir = include_directories('src/include')
subdir('src')

View File

@ -9,13 +9,16 @@
enum tc_assignable_value_category {TC_ASSIGNABLE_RANGE, TC_ASSIGNABLE_ENUM};
// Is the range double or integer
enum tc_assignable_range_data_type {TC_ASSIGNABLE_RANGE_INT, TC_ASSIGNABLE_RANGE_DOUBLE};
enum tc_assignable_range_data_type {
TC_ASSIGNABLE_RANGE_INT,
TC_ASSIGNABLE_RANGE_DOUBLE
};
typedef struct tc_assignable_range_double_t{
typedef struct tc_assignable_range_double_t {
double min, max;
} tc_assignable_range_double_t;
typedef struct tc_assignable_range_int_t{
typedef struct tc_assignable_range_int_t {
int64_t min, max;
} tc_assignable_range_int_t;
@ -32,8 +35,6 @@ typedef struct {
char **properties;
} tc_assignable_enum_t;
typedef struct tc_assignable_node_t {
// Assignable name eg. fan speed
char *name;
@ -54,3 +55,12 @@ typedef struct tc_assignable_node_t {
uint16_t children_count;
struct tc_assignable_node_t **children_nodes;
} tc_assignable_node_t;
/* Utility functions for assignables */
// Allocates memory for a tunable node
tc_assignable_node_t *tc_assignable_node_new();
// Deallocates memory of the node
void tc_assignable_node_destroy(tc_assignable_node_t *node);
// Add a child to a node
int8_t tc_assignable_node_add_child(tc_assignable_node_t *node, tc_assignable_node_t *child);

8
src/include/tc_common.h Normal file
View File

@ -0,0 +1,8 @@
#pragma once
// Common definitions for tuxclocker
// Error values
#define TC_SUCCESS 0
#define TC_EGENERIC (-1)
#define TC_ENOMEM (-2)

View File

@ -2,6 +2,21 @@
#include <stdint.h>
// Categories for modules.
enum tc_module_category {
TC_CATEGORY_ASSIGNABLE,
TC_CATEGORY_PROPERTY
};
typedef struct tc_module_t {
enum tc_module_category category;
const char *name;
// Initializes the module's internal state
int8_t (*init_callback)();
// Frees the internal memory of the module
int8_t (*close_callback)();
} tc_module_t;

0
src/lib/meson.build Normal file
View File

27
src/lib/tc_assignable.c Normal file
View File

@ -0,0 +1,27 @@
#include <stdlib.h>
#include <tc_common.h>
#include <tc_assignable.h>
tc_assignable_node_t *tc_assignable_node_new() {
tc_assignable_node_t *node = calloc(1, sizeof(tc_assignable_node_t));
return node;
}
void tc_assignable_node_destroy(tc_assignable_node_t *node) {
// The name is allocated on the heap
if (node->name != NULL) {
free(node->name);
}
free(node);
}
int8_t tc_assignable_node_add_child(tc_assignable_node_t *parent, tc_assignable_node_t *child) {
parent->children_count++;
if ((parent->children_nodes = realloc(parent->children_nodes, parent->children_count)) == NULL) {
return TC_ENOMEM;
}
parent->children_nodes[parent->children_count] = child;
return TC_SUCCESS;
}

View File

@ -1 +1,7 @@
# Define libtuxclocker target here since others depend on it
libtuxclocker = shared_library('libtuxclocker',
['lib/tc_assignable.c'],
include_directories : incdir)
subdir('modules')
subdir('lib')

View File

@ -1 +1,12 @@
shared_library('libnvidia', 'nvidia.c')
libnvml = cc.find_library('nvidia-ml')
libx = cc.find_library('X11')
libxnvctrl = cc.find_library('XNVCtrl')
nvml_h = cc.has_header('nvml.h')
shared_library('libnvidia', 'nvidia_linux.c',
include_directories : incdir,
dependencies : [libnvml, libx, libxnvctrl],
link_with : libtuxclocker)

View File

@ -1,5 +0,0 @@
#include "/opt/cuda/include/nvml.h"
#define MAX_GPUS 32
static nvmlDevice_t nvml_handles[MAX_GPUS];

View File

@ -0,0 +1,82 @@
#include "/opt/cuda/include/nvml.h"
#include <X11/Xlib.h>
#include <string.h>
#include <tc_assignable.h>
#include <tc_common.h>
#define MAX_GPUS 32
// Local function declarations
static int8_t init();
static int8_t close();
static int8_t generate_assignable_tree();
static uint32_t gpu_count;
static nvmlDevice_t nvml_handles[MAX_GPUS];
static Display *dpy;
static tc_assignable_node_t *root_node;
static int8_t init() {
// Initialize library
if (nvmlInit_v2() != NVML_SUCCESS) {
return TC_EGENERIC;
}
// Query GPU count
if (nvmlDeviceGetCount(&gpu_count) != NVML_SUCCESS) {
return TC_EGENERIC;
}
if (gpu_count > MAX_GPUS) {
return TC_ENOMEM;
}
// Get nvml handles
uint32_t valid_count = 0;
for (uint8_t i = 0; i < gpu_count; i++) {
nvmlDevice_t dev;
if (nvmlDeviceGetHandleByIndex_v2(i, &dev) == NVML_SUCCESS) {
nvml_handles[valid_count] = dev;
valid_count++;
}
}
gpu_count = valid_count;
// Get X11 display
if ((dpy = XOpenDisplay(NULL)) == NULL) {
return TC_EGENERIC;
}
// Generate the tree structure of assignables for every GPU. Free in close().
generate_assignable_tree();
return TC_SUCCESS;
}
static int8_t close() {
}
static int8_t generate_assignable_tree() {
// Allocate memory for root node
root_node = tc_assignable_node_new();
for (uint32_t i = 0; i < gpu_count; i++) {
// Get GPU name and use it as the root item for GPU
char gpu_name[NVML_DEVICE_NAME_BUFFER_SIZE];
if (nvmlDeviceGetName(nvml_handles[i], gpu_name, NVML_DEVICE_NAME_BUFFER_SIZE) != NVML_SUCCESS) {
continue;
}
// Got the name, append the item to the root item
tc_assignable_node_t *gpu_name_node = tc_assignable_node_new();
gpu_name_node->name = strdup(gpu_name);
// Append to the root node
if (tc_assignable_node_add_child(root_node, gpu_name_node) != TC_SUCCESS) {
}
}
}