blob: 90d8a97fe03c1f1bde7ebbdd143201e092c6bc1f [file] [log] [blame]
/*
*heat_cpu.c
*
* Copyright (C) 2011, Linaro Limited.
*
* This program 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 2
* of the License, or (at your option) any later version.
*
* This program 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 this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* Contributors:
* Robert Lee <rob.lee@linaro.org>
* Amit Daniel <amit.kachhap@linaro.org>
* VERSION=0.4
*/
/*
* program to heat up your cpus
*
* Creates a thread for each cpu which will run in a loop that executes
* code that (hopefully) produces a large amount of heat.
*
* The each thread's policy is set to make it very low priority. This allows
* this script to be ran in conjunction with other code that may want to run
* and exercise (produce heat) from other various parts of the SoC such
* as the GPU and VPU.
*/
#define _GNU_SOURCE
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <sched.h>
#include <pthread.h>
#include <string.h>
#include <math.h>
#define NR_THREAD 3
int cont = 1;
int cpu_index;
long long a = 1, c = 1;
float f = M_PI;
pid_t thr_id[NR_THREAD];
int moderate_inst;
#ifdef ANDROID
int conditionMet;
pthread_cond_t cond = PTHREAD_COND_INITIALIZER;
pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
#endif
void *do_loop(void *data)
{
const long long b = 3;
float f = 1.12;
a = 1;
c = 1;
#ifdef ANDROID
long int thread = (long int) data;
thr_id[thread] = gettid();
pthread_mutex_lock(&mutex);
while (!conditionMet)
pthread_cond_wait(&cond, &mutex);
pthread_mutex_unlock(&mutex);
#endif
while (cont) {
if (!moderate_inst) {
a += a * b;
c += c * b;
f += f * b;
} else {
a += 1;
}
}
return 0;
}
int main(int arg_count, char *argv[])
{
int ret, i;
int num_cpus = sysconf(_SC_NPROCESSORS_ONLN);
cpu_set_t cpuset;
printf("Num CPUs: %d\n", num_cpus);
if (arg_count > 1) {
if (!strcmp("moderate", argv[1])) {
moderate_inst = 1;
printf("use moderate heating\n");
}
}
/* clear out cpus */
CPU_ZERO(&cpuset);
/* Create a pthread_attr_t object for each core */
pthread_attr_t *p = (pthread_attr_t *) malloc(
num_cpus * sizeof(pthread_attr_t));
if (!p) {
printf("ERROR: out of memory\n");
return -1;
}
pthread_t *p_thread_ptr = (pthread_t *) malloc(
num_cpus * sizeof(pthread_attr_t));
if (!p_thread_ptr) {
printf("ERROR: out of memory\n");
return -1;
}
for (i = 0; i < num_cpus; i++) {
ret = pthread_attr_init(&p[i]);
if (ret) {
printf("Error initializing pattr\n");
return ret;
}
#ifndef ANDROID
/* Make workload thread's very low priority if allowed*/
#ifdef SCHED_IDLE
ret = pthread_attr_setschedpolicy(&p[i], SCHED_IDLE);
#endif
#else
ret = pthread_attr_setschedpolicy(&p[i], SCHED_NORMAL);
#endif
/* for each new object */
CPU_SET(i, &cpuset);
#ifndef ANDROID
ret = pthread_attr_setaffinity_np(&p[i],
sizeof(cpu_set_t), &cpuset);
if (ret) {
printf("Error setting affinity on pthread attribute\n");
printf("i: %i\n", i);
printf("Error: %s\n", strerror(ret));
return ret;
}
#endif
CPU_CLR(i, &cpuset);
}
for (i = 0; i < num_cpus; i++) {
/* create a new thread that will execute 'do_loop()' */
ret = pthread_create(&p_thread_ptr[i], &p[i],
do_loop, (void *)i);
if (ret < 0)
printf("Error setting affinity for cpu%d\n", i);
#ifdef ANDROID
CPU_ZERO(&cpuset);
CPU_SET(i, &cpuset);
ret = sched_setaffinity(thr_id[i], sizeof(cpuset), &cpuset);
if (ret) {
printf("Error setting affinity on pthread th_id\n");
printf("Error: %s\n", strerror(ret));
return ret;
}
#endif
}
#ifdef ANDROID
pthread_mutex_lock(&mutex);
conditionMet = 1;
pthread_cond_broadcast(&cond);
pthread_mutex_unlock(&mutex);
#endif
while (1)
sleep(1);
return 0;
}