pm: add two examples for the power management API
https://jira.digi.com/browse/DEL-6659 Signed-off-by: Francisco Gil <francisco.gilmartinez@digi.com>
This commit is contained in:
parent
844d13fec0
commit
0e94c71cfb
|
|
@ -0,0 +1,44 @@
|
|||
#
|
||||
# Copyright 2019, Digi International Inc.
|
||||
#
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
#
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
# REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
# AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
# INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
# LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
# OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
# PERFORMANCE OF THIS SOFTWARE.
|
||||
#
|
||||
|
||||
BINARYCPU := apix-cpu-example
|
||||
BINARYPM := apix-pm-application
|
||||
|
||||
BINARIES := $(BINARYCPU) $(BINARYPM)
|
||||
|
||||
CFLAGS += -Wall -O0
|
||||
|
||||
CFLAGS += $(shell pkg-config --cflags libdigiapix)
|
||||
LDLIBS += $(shell pkg-config --libs libdigiapix)
|
||||
|
||||
.PHONY: all
|
||||
all: $(BINARIES)
|
||||
|
||||
$(BINARYCPU): apix-cpu-sample.o
|
||||
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $(BINARYCPU)
|
||||
|
||||
|
||||
$(BINARYPM): apix-pm-sample.o
|
||||
$(CC) $(LDFLAGS) $^ $(LDLIBS) -o $(BINARYPM)
|
||||
|
||||
.PHONY: install
|
||||
install: $(BINARIES)
|
||||
install -d $(DESTDIR)/usr/bin
|
||||
install -m 0755 $^ $(DESTDIR)/usr/bin/
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
-rm -f *.o $(BINARIES)
|
||||
|
|
@ -0,0 +1,96 @@
|
|||
Digi APIX Power Management example Applications
|
||||
===============================================
|
||||
|
||||
Example applications to access and manage CPU functions using the Digi APIX library.
|
||||
|
||||
These applications show how to work with different functions and provide different
|
||||
examples to work with the CPU.
|
||||
|
||||
Running the apix-cpu-example application
|
||||
-----------------------
|
||||
Once the binary is in the target, launch the application:
|
||||
|
||||
```
|
||||
# ./apix-cpu-example
|
||||
Example application using libdigiapix CPU support
|
||||
|
||||
Usage: apix-cpu-example [options]
|
||||
|
||||
-l List available frequencies
|
||||
-s <frequency> Set the desired frequency
|
||||
-v Show the current governor
|
||||
-g List available governors
|
||||
-f <governor> Set the desired governor
|
||||
-t List the temperatures of the system
|
||||
-c <temperature> Set the critical temperature
|
||||
-p <temperature> Set the passive temperature
|
||||
-u Get the CPU usage
|
||||
-n Get the number of CPU cores
|
||||
-d <core_number> Disable the selected core
|
||||
-e <core_number> Enable the selected core
|
||||
|
||||
Examples:
|
||||
apix-cpu-example -l
|
||||
apix-cpu-example -f userspace
|
||||
apix-cpu-example -t
|
||||
```
|
||||
|
||||
The application needs a valid argument to run, some of the arguments need additional parameters.
|
||||
|
||||
Running the apix-pm-application application
|
||||
-----------------------
|
||||
Once the binary is in the target, launch the application:
|
||||
|
||||
```
|
||||
# ./apix-pm-application
|
||||
Example application using libdigiapix power management support.
|
||||
This application enables counter measurements in the CPU and GPU
|
||||
in order to reduce the temperature.
|
||||
|
||||
Usage: apix-pm-application [options]
|
||||
|
||||
-c Apply CPU counter measurements
|
||||
-g Apply GPU counter measurements
|
||||
-b Apply CPU & GPU counter measurements
|
||||
|
||||
Examples:
|
||||
apix-pm-application -g
|
||||
apix-pm-application -b
|
||||
```
|
||||
|
||||
This application enables countermeasures in order to reduce the temperature of the CPU.
|
||||
|
||||
If the CPU countermeasures are set, it will select the userspace governor and will set
|
||||
the minimum frequency in the device in order to reduce the temperature.
|
||||
|
||||
If the GPU counter measurements are set, it will reduce the GPU scaler to half of its original value.
|
||||
Note: Some modules such as CC6UL don't have a GPU.
|
||||
|
||||
Compiling the application
|
||||
-------------------------
|
||||
This demo can be compiled using a Digi Embedded Yocto based toolchain. Make
|
||||
sure to source the corresponding toolchain of the platform you are using,
|
||||
for example, for ConnectCore 6UL:
|
||||
```
|
||||
~$ . <DEY-toolchain-path>/environment-setup-cortexa7hf-vfp-neon-dey-linux-gnueabi
|
||||
~$ make
|
||||
```
|
||||
|
||||
For more information, see the [Digi Embedded Yocto](https://github.com/digi-embedded/meta-digi).
|
||||
|
||||
License
|
||||
-------
|
||||
Copyright 2019, Digi International Inc.
|
||||
|
||||
Permission to use, copy, modify, and/or distribute this software for any purpose
|
||||
with or without fee is hereby granted, provided that the above copyright notice
|
||||
and this permission notice appear in all copies.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
|
||||
FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
|
||||
OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
|
||||
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
|
||||
THIS SOFTWARE.
|
||||
|
||||
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* Copyright 2019, Digi International Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libdigiapix/pwr_management.h>
|
||||
|
||||
/*
|
||||
* usage_and_exit() - Show usage information and exit with 'exitval' return
|
||||
* value
|
||||
*
|
||||
* @name: Application name.
|
||||
* @exitval: The exit code.
|
||||
*/
|
||||
static void usage_and_exit(const char *name, int exitval)
|
||||
{
|
||||
printf(
|
||||
"Example application using libdigiapix power management support\n"
|
||||
"\n"
|
||||
"Usage: %s [options]\n\n"
|
||||
"-l List available frequencies\n"
|
||||
"-s <frequency> Set the desired frequency \n"
|
||||
"-v Show the current governor\n"
|
||||
"-g List available governors\n"
|
||||
"-f <governor> Set the desired governor\n"
|
||||
"-t List the temperatures of the system\n"
|
||||
"-c <temperature> Set the critical temperature in mºC\n"
|
||||
"-p <temperature> Set the passive temperature in mºC\n"
|
||||
"-u Get the CPU usage\n"
|
||||
"-n Get the number of CPU cores\n"
|
||||
"-d <core_number> Disable the selected core\n"
|
||||
"-e <core_number> Enable the selected core\n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"%s -l\n"
|
||||
"%s -f userspace\n"
|
||||
"%s -t\n"
|
||||
"\n", name, name, name, name);
|
||||
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
/*
|
||||
* list_available_governors() - Print the available governors
|
||||
*/
|
||||
static void list_available_governors()
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("These are the governors available:\n");
|
||||
for (i = 0; i < MAX_GOVERNORS; i++) {
|
||||
for (i = 0; i < GOVERNOR_SIZE; i++) {
|
||||
if (ldx_cpu_is_governor_available(i) == EXIT_SUCCESS)
|
||||
printf("\t\t\t%s\n", ldx_cpu_get_governor_string_from_type(i));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* list_temperatures() - Print the available temperatures
|
||||
*/
|
||||
static void list_temperatures()
|
||||
{
|
||||
printf("Critical temperature %d mºC\n",
|
||||
ldx_cpu_get_critical_trip_point());
|
||||
printf("Passive temperature %d mºC\n",
|
||||
ldx_cpu_get_passive_trip_point());
|
||||
printf("Current temperature %d mºC\n",
|
||||
ldx_cpu_get_current_temp());
|
||||
}
|
||||
|
||||
/*
|
||||
* list_available_frequencies() - Print the available frequencies
|
||||
*/
|
||||
static void list_available_frequencies()
|
||||
{
|
||||
int i;
|
||||
available_frequencies_t freq = ldx_cpu_get_available_freq();
|
||||
|
||||
printf("These are the available frequencies:\n");
|
||||
for (i = 0; i < freq.len; i++) {
|
||||
printf("\t\t\t%d\n", freq.data[i]);
|
||||
}
|
||||
ldx_cpu_free_available_freq(freq);
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *name = basename(argv[0]);
|
||||
const char *governor;
|
||||
governor_mode_t governor_mode;
|
||||
int ret = EXIT_FAILURE;
|
||||
int frequency, temperature, usage, core, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "s:f:m:c:d:e:p:gtlunvh ")) > 0) {
|
||||
switch (opt) {
|
||||
case 'l':
|
||||
list_available_frequencies();
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
case 's':
|
||||
frequency = strtoul(optarg, NULL, 10);
|
||||
if (ldx_cpu_set_scaling_freq(frequency) == EXIT_FAILURE) {
|
||||
printf("Error setting the scaling frequency to: %d\n", frequency);
|
||||
} else {
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case 'g':
|
||||
list_available_governors();
|
||||
break;
|
||||
case 'v':
|
||||
governor = ldx_cpu_get_governor_string_from_type(ldx_cpu_get_governor());
|
||||
if (governor != NULL){
|
||||
printf("This is the current governor: %s\n", governor);
|
||||
ret = EXIT_SUCCESS;
|
||||
} else {
|
||||
printf("Unable to get the current governor");
|
||||
}
|
||||
break;
|
||||
case 'f':
|
||||
governor_mode = ldx_cpu_get_governor_type_from_string(optarg);
|
||||
if (governor_mode == GOVERNOR_INVALID) {
|
||||
printf("Invalid governor: %s", optarg);
|
||||
} else {
|
||||
if (ldx_cpu_set_governor(governor_mode) == EXIT_FAILURE) {
|
||||
printf("Unable to set governor: %s\n", optarg);
|
||||
} else {
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 't':
|
||||
list_temperatures();
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
case 'c':
|
||||
temperature = strtoul(optarg, NULL, 10);
|
||||
if (ldx_cpu_set_critical_trip_point(temperature) == EXIT_FAILURE) {
|
||||
printf("Unable to set the critical trip point temperature: %d\n", temperature);
|
||||
} else {
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case 'p':
|
||||
temperature = strtoul(optarg, NULL, 10);
|
||||
if (ldx_cpu_set_passive_trip_point(temperature) == EXIT_FAILURE)
|
||||
printf("Unable to set the passive trip point temperature: %d\n", temperature);
|
||||
else
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
case 'u':
|
||||
usage = ldx_cpu_get_usage();
|
||||
if (usage == -1) {
|
||||
printf("Error getting the CPU usage\n");
|
||||
} else {
|
||||
printf("The usage of the CPU is: %d %%\n", usage);
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case 'n':
|
||||
core = ldx_cpu_get_number_of_cores();
|
||||
if (core == -1) {
|
||||
printf("Error getting the number of cores\n");
|
||||
} else {
|
||||
printf("The number of CPU cores is: %d\n", core);
|
||||
ret = EXIT_SUCCESS;
|
||||
}
|
||||
break;
|
||||
case 'd':
|
||||
core = strtoul(optarg, NULL, 10);
|
||||
printf("Disabling core: %d\n", core);
|
||||
if (ldx_cpu_disable_core(core) == EXIT_FAILURE)
|
||||
printf("Cannot disable the core with index: %d\n", core);
|
||||
else
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
case 'e':
|
||||
core = strtoul(optarg, NULL, 10);
|
||||
printf("Enabling core: %d\n", core);
|
||||
if (ldx_cpu_enable_core(core) == EXIT_FAILURE)
|
||||
printf("Cannot enable the core with index: %d\n", core);
|
||||
else
|
||||
ret = EXIT_SUCCESS;
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage_and_exit(name, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
||||
if (ret == EXIT_FAILURE)
|
||||
usage_and_exit(name, ret);
|
||||
|
||||
return ret;
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright 2019, Digi International Inc.
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
|
||||
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
|
||||
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
|
||||
* OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||
* PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <libgen.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <libdigiapix/pwr_management.h>
|
||||
|
||||
#define CPU_SAMPLING_TIME 6
|
||||
#define MAX_SAMPLES 10
|
||||
/*
|
||||
* usage_and_exit() - Show usage information and exit with 'exitval' return
|
||||
* value
|
||||
*
|
||||
* @name: Application name.
|
||||
* @exitval: The exit code.
|
||||
*/
|
||||
static void usage_and_exit(const char *name, int exitval)
|
||||
{
|
||||
printf(
|
||||
"Example application using libdigiapix power management support. \n"
|
||||
"This application enables counter measurements in the CPU and GPU\n"
|
||||
"in order to reduce the temperature.\n"
|
||||
"\n"
|
||||
"Usage: %s [options]\n\n"
|
||||
"-c Apply CPU counter measurements \n"
|
||||
"-g Apply GPU counter measurements \n"
|
||||
"-b Apply CPU & GPU counter measurements \n"
|
||||
"\n"
|
||||
"Examples:\n"
|
||||
"%s -g\n"
|
||||
"%s -b\n"
|
||||
"\n", name, name, name);
|
||||
|
||||
exit(exitval);
|
||||
}
|
||||
|
||||
/*
|
||||
* verify_temperature_reduction() - Print the current temperature during
|
||||
* CPU_SAMPLING_TIME * MAX_SAMPLES seconds
|
||||
*
|
||||
* This function prints the temperature each CPU_SAMPLING_TIME seconds.
|
||||
*
|
||||
* Return: EXIT_SUCCESS on success, EXIT_FAILURE if something fails.
|
||||
*/
|
||||
|
||||
static int verify_temperature_reduction()
|
||||
{
|
||||
int i, temperature;
|
||||
|
||||
printf("Checking if the temperature is being reduced...\n");
|
||||
for (i = 0; i < MAX_SAMPLES; i++) {
|
||||
temperature = ldx_cpu_get_current_temp();
|
||||
|
||||
if (temperature == -1) {
|
||||
printf("Error getting the temperature\n");
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
printf("Current temperature: %d \n", temperature);
|
||||
sleep(CPU_SAMPLING_TIME);
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* apply_countermeasurements() - Apply counter measurements to reduce the temperature
|
||||
*
|
||||
* @gpu: 1 to enable the gpu counter measurements.
|
||||
* @cpu: 1 to enable the cpu counter measurements.
|
||||
*
|
||||
* This function reduces the GPU multiplier to half of its value if
|
||||
* This function reduces the GPU multiplier to half its value if
|
||||
* the gpu value is enabled.
|
||||
*
|
||||
* This function reduces the CPU frequency to the minimum if the cpu value
|
||||
* is enabled.
|
||||
*
|
||||
* Return: EXIT_SUCCESS on success, EXIT_FAILURE if something fails.
|
||||
*/
|
||||
static int apply_countermeasurements(int gpu, int cpu)
|
||||
{
|
||||
governor_mode_t governor;
|
||||
int freq;
|
||||
int ret = EXIT_SUCCESS;
|
||||
int gpu_multiplier;
|
||||
|
||||
if (gpu) {
|
||||
gpu_multiplier = ldx_gpu_get_multiplier();
|
||||
if (gpu_multiplier == -1) {
|
||||
printf("Error getting the gpu multiplier, verify that your platform has a GPU\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (ldx_gpu_set_multiplier(gpu_multiplier / 2) == EXIT_FAILURE) {
|
||||
printf("Error setting the gpu multiplier to %d\n", gpu_multiplier / 2);
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
if (cpu) {
|
||||
governor = ldx_cpu_get_governor();
|
||||
|
||||
if (governor == GOVERNOR_INVALID) {
|
||||
printf("Error getting governor\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Only with the 'userspace' governor can we modify and manage the frequency */
|
||||
if (ldx_cpu_set_governor(ldx_cpu_get_governor_type_from_string("userspace"))) {
|
||||
printf("Error setting the 'userspace' governor\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
freq = ldx_cpu_get_scaling_freq();
|
||||
|
||||
if (freq == -1) {
|
||||
printf("Error getting the current frequency, restoring the previous governor\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (ldx_cpu_set_scaling_freq(ldx_cpu_get_min_scaling_freq()) == EXIT_FAILURE) {
|
||||
printf("Error setting the scaling frequency\n");
|
||||
ret = EXIT_FAILURE;
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
ret = verify_temperature_reduction();
|
||||
|
||||
if (cpu) {
|
||||
/* Restore the frequency */
|
||||
if (ldx_cpu_set_scaling_freq(freq)) {
|
||||
printf("Error restoring the previous frequency\n");
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
/* Restore CPU parameters */
|
||||
if (cpu) {
|
||||
if (ldx_cpu_set_governor(governor) == EXIT_FAILURE) {
|
||||
printf("Error restoring the governor\n");
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
/* Restore GPU parameters */
|
||||
if (gpu) {
|
||||
if (ldx_gpu_set_multiplier(gpu_multiplier)){
|
||||
printf("Error restoring the gpu multiplier\n");
|
||||
ret = EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
exit:
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char *name = basename(argv[0]);
|
||||
int opt;
|
||||
int cpu = 0;
|
||||
int gpu = 0;
|
||||
|
||||
while ((opt = getopt(argc, argv, "gcbh")) > 0) {
|
||||
switch (opt) {
|
||||
case 'g':
|
||||
gpu = 1;
|
||||
printf("Applying GPU counter measurements\n");
|
||||
break;
|
||||
case 'c':
|
||||
cpu = 1;
|
||||
printf("Applying CPU counter measurements\n");
|
||||
break;
|
||||
case 'b':
|
||||
gpu = 1;
|
||||
cpu = 1;
|
||||
printf("Applying GPU & CPU counter measurements\n");
|
||||
break;
|
||||
case 'h':
|
||||
default:
|
||||
usage_and_exit(name, EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
if (cpu == 1 || gpu == 1){
|
||||
return apply_countermeasurements(gpu, cpu);
|
||||
}
|
||||
|
||||
usage_and_exit(name, EXIT_FAILURE);
|
||||
}
|
||||
Loading…
Reference in New Issue