~ubuntu-branches/ubuntu/utopic/thermald/utopic

« back to all changes in this revision

Viewing changes to .pc/0029-coverity-scans-Uninitialized-scalar-field-errors.patch/src/thd_engine.cpp

  • Committer: Package Import Robot
  • Author(s): Colin King
  • Date: 2014-05-19 12:41:22 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20140519124122-zan11arvjxtbqcq5
Tags: 1.2-1
* Adjust for coretemp path change
* Deny non root users to send system bus dbus messages
* Remove compile warning
* Remove rpmlint warning for manual page
* Remove old patches that are now included into version 1.2
* Sync up with version 1.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * thd_engine.cpp: thermal engine class implementation
3
 
 *
4
 
 * Copyright (C) 2012 Intel Corporation. All rights reserved.
5
 
 *
6
 
 * This program is free software; you can redistribute it and/or
7
 
 * modify it under the terms of the GNU General Public License version
8
 
 * 2 or later as published by the Free Software Foundation.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
 
 * 02110-1301, USA.
19
 
 *
20
 
 *
21
 
 * Author Name <Srinivas.Pandruvada@linux.intel.com>
22
 
 *
23
 
 */
24
 
 
25
 
/* This class acts as the parent class of all thermal engines. Main functions are:
26
 
 * - Initialization
27
 
 * - Read cooling devices and thermal zones(sensors), which can be overridden in child
28
 
 * - Starts a poll loop, All the thermal processing happens in this thread's context
29
 
 * - Message processing loop
30
 
 * - If either a poll interval is expired or notified via netlink, it schedules a
31
 
 *   a change notification on the associated cthd_zone to read and process.
32
 
 */
33
 
 
34
 
#include <dirent.h>
35
 
#include <errno.h>
36
 
#include <sys/types.h>
37
 
#include <cpuid.h>
38
 
#include <locale>
39
 
#include "thd_engine.h"
40
 
#include "thd_cdev_therm_sys_fs.h"
41
 
#include "thd_zone_therm_sys_fs.h"
42
 
 
43
 
static void *cthd_engine_thread(void *arg);
44
 
 
45
 
cthd_engine::cthd_engine() :
46
 
                cdev_cnt(0), zone_count(0), sensor_count(0), parse_thermal_zone_success(
47
 
                                false), parse_thermal_cdev_success(false), poll_timeout_msec(
48
 
                                -1), wakeup_fd(0), control_mode(COMPLEMENTRY), write_pipe_fd(0), preference(
49
 
                                0), status(true), thz_last_time(0), terminate(false), genuine_intel(
50
 
                                0), has_invariant_tsc(0), has_aperf(0), proc_list_matched(
51
 
                                false), poll_interval_sec(0), poll_sensor_mask(0) {
52
 
        thd_engine = pthread_t();
53
 
        thd_attr = pthread_attr_t();
54
 
        thd_cond_var = pthread_cond_t();
55
 
        thd_cond_mutex = pthread_mutex_t();
56
 
}
57
 
 
58
 
cthd_engine::~cthd_engine() {
59
 
        unsigned int i;
60
 
 
61
 
        for (i = 0; i < sensors.size(); ++i) {
62
 
                delete sensors[i];
63
 
        }
64
 
        sensors.clear();
65
 
        for (i = 0; i < zones.size(); ++i) {
66
 
                delete zones[i];
67
 
        }
68
 
        zones.clear();
69
 
        for (i = 0; i < cdevs.size(); ++i) {
70
 
                delete cdevs[i];
71
 
        }
72
 
        cdevs.clear();
73
 
}
74
 
 
75
 
void cthd_engine::thd_engine_thread() {
76
 
        unsigned int i;
77
 
        int n;
78
 
 
79
 
        thd_log_info("thd_engine_thread begin\n");
80
 
        for (;;) {
81
 
                if (terminate)
82
 
                        break;
83
 
                n = poll(poll_fds, THD_NUM_OF_POLL_FDS, poll_timeout_msec);
84
 
                thd_log_debug("poll exit %d \n", n);
85
 
                if (n < 0) {
86
 
                        thd_log_warn("Write to pipe failed \n");
87
 
                        continue;
88
 
                }
89
 
                if (n == 0) {
90
 
                        if (!status) {
91
 
                                thd_log_warn("Thermal Daemon is disabled \n");
92
 
                                continue;
93
 
                        }
94
 
                        // Polling mode enabled. Trigger a temp change message
95
 
                        for (i = 0; i < zones.size(); ++i) {
96
 
                                cthd_zone *zone = zones[i];
97
 
                                zone->zone_temperature_notification(0, 0);
98
 
                        }
99
 
                }
100
 
                if (poll_fds[0].revents & POLLIN) {
101
 
                        // Kobj uevent
102
 
                        if (kobj_uevent.check_for_event()) {
103
 
                                time_t tm;
104
 
 
105
 
                                time(&tm);
106
 
                                thd_log_debug("kobj uevent for thermal\n");
107
 
                                if ((tm - thz_last_time) >= thz_notify_debounce_interval) {
108
 
                                        for (i = 0; i < zones.size(); ++i) {
109
 
                                                cthd_zone *zone = zones[i];
110
 
                                                zone->zone_temperature_notification(0, 0);
111
 
                                        }
112
 
                                } else {
113
 
                                        thd_log_debug("IGNORE THZ kevent\n");
114
 
                                }
115
 
                                thz_last_time = tm;
116
 
                        }
117
 
                }
118
 
                if (poll_fds[wakeup_fd].revents & POLLIN) {
119
 
                        message_capsul_t msg;
120
 
 
121
 
                        thd_log_debug("wakeup fd event\n");
122
 
                        int result = read(poll_fds[wakeup_fd].fd, &msg,
123
 
                                        sizeof(message_capsul_t));
124
 
                        if (result < 0) {
125
 
                                thd_log_warn("read on wakeup fd failed\n");
126
 
                                poll_fds[wakeup_fd].revents = 0;
127
 
                                continue;
128
 
                        }
129
 
                        if (proc_message(&msg) < 0) {
130
 
                                thd_log_debug("Terminating thread..\n");
131
 
                        }
132
 
                }
133
 
        }
134
 
        thd_log_debug("thd_engine_thread_end\n");
135
 
}
136
 
 
137
 
bool cthd_engine::set_preference(const int pref) {
138
 
        return true;
139
 
}
140
 
 
141
 
int cthd_engine::thd_engine_start(bool ignore_cpuid_check) {
142
 
        int ret;
143
 
        int wake_fds[2];
144
 
 
145
 
        if (ignore_cpuid_check) {
146
 
                thd_log_debug("Ignore CPU ID check for MSRs \n");
147
 
                proc_list_matched = true;
148
 
        } else
149
 
                check_cpu_id();
150
 
 
151
 
        // Pipe is used for communication between two processes
152
 
        ret = pipe(wake_fds);
153
 
        if (ret) {
154
 
                thd_log_error("Thermal sysfs: pipe creation failed %d:\n", ret);
155
 
                return THD_FATAL_ERROR;
156
 
        }
157
 
        if (fcntl(wake_fds[0], F_SETFL, O_NONBLOCK) < 0) {
158
 
                thd_log_error("Cannot set non-blocking on pipe: %s\n",
159
 
                        strerror(errno));
160
 
                return THD_FATAL_ERROR;
161
 
        }
162
 
        if (fcntl(wake_fds[1], F_SETFL, O_NONBLOCK) < 0) {
163
 
                thd_log_error("Cannot set non-blocking on pipe: %s\n",
164
 
                        strerror(errno));
165
 
                return THD_FATAL_ERROR;
166
 
        }
167
 
        write_pipe_fd = wake_fds[1];
168
 
        wakeup_fd = THD_NUM_OF_POLL_FDS - 1;
169
 
 
170
 
        memset(poll_fds, 0, sizeof(poll_fds));
171
 
        poll_fds[wakeup_fd].fd = wake_fds[0];
172
 
        poll_fds[wakeup_fd].events = POLLIN;
173
 
        poll_fds[wakeup_fd].revents = 0;
174
 
 
175
 
        poll_timeout_msec = -1;
176
 
        if (poll_interval_sec) {
177
 
                thd_log_warn("Polling mode is enabled: %d\n", poll_interval_sec);
178
 
                poll_timeout_msec = poll_interval_sec * 1000;
179
 
        }
180
 
 
181
 
        ret = read_thermal_sensors();
182
 
        if (ret != THD_SUCCESS) {
183
 
                thd_log_error("Thermal sysfs Error in reading sensors\n");
184
 
                // This is a fatal error and daemon will exit
185
 
                return THD_FATAL_ERROR;
186
 
        }
187
 
 
188
 
        ret = read_cooling_devices();
189
 
        if (ret != THD_SUCCESS) {
190
 
                thd_log_error("Thermal sysfs Error in reading cooling devs\n");
191
 
                // This is a fatal error and daemon will exit
192
 
                return THD_FATAL_ERROR;
193
 
        }
194
 
 
195
 
        ret = read_thermal_zones();
196
 
        if (ret != THD_SUCCESS) {
197
 
                thd_log_error("No thermal sensors found\n");
198
 
                // This is a fatal error and daemon will exit
199
 
                return THD_FATAL_ERROR;
200
 
        }
201
 
 
202
 
        // Check if polling is disabled and sensors don't support
203
 
        // async mode, in that enable force polling
204
 
        if (!poll_interval_sec) {
205
 
                unsigned int i;
206
 
                for (i = 0; i < zones.size(); ++i) {
207
 
                        cthd_zone *zone = zones[i];
208
 
                        if (!zone->zone_active_status())
209
 
                                continue;
210
 
                        if (!zone->check_sensor_async_status()) {
211
 
                                thd_log_warn(
212
 
                                                "Polling will be enabled as some sensors are not capable to notify asynchnously \n");
213
 
                                poll_timeout_msec = def_poll_interval;
214
 
                                break;
215
 
                        }
216
 
                }
217
 
                if (i == zones.size()) {
218
 
                        thd_log_info("Proceed without polling mode! \n");
219
 
                }
220
 
        }
221
 
 
222
 
        poll_fds[0].fd = kobj_uevent.kobj_uevent_open();
223
 
        if (poll_fds[0].fd < 0) {
224
 
                thd_log_warn("Invalid kobj_uevent handle\n");
225
 
                goto skip_kobj;
226
 
        }
227
 
        thd_log_info("FD = %d\n", poll_fds[0].fd);
228
 
        kobj_uevent.register_dev_path(
229
 
                        (char *) "/devices/virtual/thermal/thermal_zone");
230
 
        poll_fds[0].events = POLLIN;
231
 
        poll_fds[0].revents = 0;
232
 
        skip_kobj:
233
 
#ifndef DISABLE_PTHREAD
234
 
        // condition variable
235
 
        pthread_cond_init(&thd_cond_var, NULL);
236
 
        pthread_mutex_init(&thd_cond_mutex, NULL);
237
 
        // Create thread
238
 
        pthread_attr_init(&thd_attr);
239
 
        pthread_attr_setdetachstate(&thd_attr, PTHREAD_CREATE_DETACHED);
240
 
        ret = pthread_create(&thd_engine, &thd_attr, cthd_engine_thread,
241
 
                        (void*) this);
242
 
#else
243
 
        {
244
 
                pid_t childpid;
245
 
 
246
 
                if((childpid = fork()) == - 1)
247
 
                {
248
 
                        perror("fork");
249
 
                        exit(EXIT_FAILURE);
250
 
                }
251
 
 
252
 
                if(childpid == 0)
253
 
                {
254
 
                        /* Child process closes up input side of pipe */
255
 
                        close(wake_fds[1]);
256
 
                        cthd_engine_thread((void*)this);
257
 
                }
258
 
                else
259
 
                {
260
 
                        /* Parent process closes up output side of pipe */
261
 
                        close(wake_fds[0]);
262
 
                }
263
 
        }
264
 
#endif
265
 
        preference = thd_pref.get_preference();
266
 
        thd_log_info("Current user preference is %d\n", preference);
267
 
 
268
 
        if (control_mode == EXCLUSIVE) {
269
 
                thd_log_info("Control is taken over from kernel\n");
270
 
                takeover_thermal_control();
271
 
        }
272
 
        return ret;
273
 
}
274
 
 
275
 
int cthd_engine::thd_engine_stop() {
276
 
        return THD_SUCCESS;
277
 
}
278
 
 
279
 
static void *cthd_engine_thread(void *arg) {
280
 
        cthd_engine *obj = (cthd_engine*) arg;
281
 
 
282
 
        obj->thd_engine_thread();
283
 
 
284
 
        return NULL;
285
 
}
286
 
 
287
 
void cthd_engine::send_message(message_name_t msg_id, int size,
288
 
                unsigned char *msg) {
289
 
        message_capsul_t msg_cap;
290
 
 
291
 
        memset(&msg_cap, 0, sizeof(message_capsul_t));
292
 
 
293
 
        msg_cap.msg_id = msg_id;
294
 
        msg_cap.msg_size = (size > MAX_MSG_SIZE) ? MAX_MSG_SIZE : size;
295
 
        if (msg)
296
 
                memcpy(msg_cap.msg, msg, msg_cap.msg_size);
297
 
        int result = write(write_pipe_fd, &msg_cap, sizeof(message_capsul_t));
298
 
        if (result < 0)
299
 
                thd_log_warn("Write to pipe failed \n");
300
 
}
301
 
 
302
 
void cthd_engine::process_pref_change() {
303
 
        int new_pref;
304
 
 
305
 
        thd_pref.refresh();
306
 
        new_pref = thd_pref.get_preference();
307
 
        if (new_pref == PREF_DISABLED) {
308
 
                status = false;
309
 
                return;
310
 
        }
311
 
        status = true;
312
 
        if (preference != new_pref) {
313
 
                thd_log_warn("Preference changed \n");
314
 
        }
315
 
        preference = new_pref;
316
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
317
 
                cthd_zone *zone = zones[i];
318
 
                zone->update_zone_preference();
319
 
        }
320
 
 
321
 
        if (control_mode == EXCLUSIVE) {
322
 
                thd_log_info("Control is taken over from kernel\n");
323
 
                takeover_thermal_control();
324
 
        }
325
 
}
326
 
 
327
 
void cthd_engine::thd_engine_terminate() {
328
 
        send_message(TERMINATE, 0, NULL);
329
 
        sleep(1);
330
 
        process_terminate();
331
 
}
332
 
 
333
 
int cthd_engine::thd_engine_set_user_max_temp(const char *zone_type,
334
 
                const char *user_set_point) {
335
 
        std::string str(user_set_point);
336
 
        cthd_zone *zone;
337
 
 
338
 
        thd_log_debug("thd_engine_set_user_set_point %s\n", user_set_point);
339
 
 
340
 
        std::locale loc;
341
 
        if (std::isdigit(str[0], loc) == 0) {
342
 
                thd_log_warn("thd_engine_set_user_set_point Invalid set point\n");
343
 
                return THD_ERROR;
344
 
        }
345
 
 
346
 
        zone = get_zone(zone_type);
347
 
        if (!zone) {
348
 
                thd_log_warn("thd_engine_set_user_set_point Invalid zone\n");
349
 
                return THD_ERROR;
350
 
        }
351
 
        return zone->update_max_temperature(atoi(user_set_point));
352
 
}
353
 
 
354
 
void cthd_engine::thermal_zone_change(message_capsul_t *msg) {
355
 
 
356
 
        thermal_zone_notify_t *pmsg = (thermal_zone_notify_t*) msg->msg;
357
 
        for (unsigned i = 0; i < zones.size(); ++i) {
358
 
                cthd_zone *zone = zones[i];
359
 
                if (zone->zone_active_status())
360
 
                        zone->zone_temperature_notification(pmsg->type, pmsg->data);
361
 
                else {
362
 
                        thd_log_debug("zone is not active\n");
363
 
                }
364
 
        }
365
 
}
366
 
 
367
 
void cthd_engine::poll_enable_disable(bool status, message_capsul_t *msg) {
368
 
        unsigned int *sensor_id = (unsigned int*) msg->msg;
369
 
 
370
 
        if (status) {
371
 
                poll_sensor_mask |= (1 << (*sensor_id));
372
 
                poll_timeout_msec = def_poll_interval;
373
 
                thd_log_debug("thd_engine polling enabled via %u \n", *sensor_id);
374
 
        } else {
375
 
                poll_sensor_mask &= ~(1 << (*sensor_id));
376
 
                if (!poll_sensor_mask) {
377
 
                        poll_timeout_msec = -1;
378
 
                        thd_log_debug("thd_engine polling last disabled via %u \n",
379
 
                                        *sensor_id);
380
 
                }
381
 
        }
382
 
}
383
 
 
384
 
int cthd_engine::proc_message(message_capsul_t *msg) {
385
 
        int ret = 0;
386
 
 
387
 
        thd_log_debug("Receieved message %d\n", msg->msg_id);
388
 
        switch (msg->msg_id) {
389
 
        case WAKEUP:
390
 
                break;
391
 
        case TERMINATE:
392
 
                thd_log_warn("Terminating ...\n");
393
 
 
394
 
                ret = -1;
395
 
                terminate = true;
396
 
                break;
397
 
        case PREF_CHANGED:
398
 
                process_pref_change();
399
 
                break;
400
 
        case THERMAL_ZONE_NOTIFY:
401
 
                if (!status) {
402
 
                        thd_log_warn("Thermal Daemon is disabled \n");
403
 
                        break;
404
 
                }
405
 
                thermal_zone_change(msg);
406
 
                break;
407
 
        case CALIBRATE: {
408
 
                //TO DO
409
 
        }
410
 
                break;
411
 
        case RELOAD_ZONES:
412
 
                thd_engine_reload_zones();
413
 
                break;
414
 
        case POLL_ENABLE:
415
 
                if (!poll_interval_sec) {
416
 
                        poll_enable_disable(true, msg);
417
 
                }
418
 
                break;
419
 
        case POLL_DISABLE:
420
 
                if (!poll_interval_sec) {
421
 
                        poll_enable_disable(false, msg);
422
 
                }
423
 
                break;
424
 
        default:
425
 
                break;
426
 
        }
427
 
 
428
 
        return ret;
429
 
}
430
 
 
431
 
cthd_cdev *cthd_engine::thd_get_cdev_at_index(int index) {
432
 
        for (int i = 0; i < cdev_cnt; ++i) {
433
 
                if (cdevs[i]->thd_cdev_get_index() == index)
434
 
                        return cdevs[i];
435
 
        }
436
 
        return NULL;
437
 
}
438
 
 
439
 
void cthd_engine::takeover_thermal_control() {
440
 
        csys_fs sysfs("/sys/class/thermal/");
441
 
 
442
 
        DIR *dir;
443
 
        struct dirent *entry;
444
 
        const std::string base_path = "/sys/class/thermal/";
445
 
 
446
 
        thd_log_info("Taking over thermal control \n");
447
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
448
 
                while ((entry = readdir(dir)) != NULL) {
449
 
                        if (!strncmp(entry->d_name, "thermal_zone",
450
 
                                        strlen("thermal_zone"))) {
451
 
                                int i;
452
 
 
453
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
454
 
                                std::stringstream policy;
455
 
                                std::string curr_policy;
456
 
 
457
 
                                policy << "thermal_zone" << i << "/policy";
458
 
                                if (sysfs.exists(policy.str().c_str())) {
459
 
                                        sysfs.read(policy.str(), curr_policy);
460
 
                                        zone_preferences.push_back(curr_policy);
461
 
                                        sysfs.write(policy.str(), "user_space");
462
 
                                }
463
 
                        }
464
 
                }
465
 
                closedir(dir);
466
 
        }
467
 
}
468
 
 
469
 
void cthd_engine::giveup_thermal_control() {
470
 
        if (control_mode != EXCLUSIVE)
471
 
                return;
472
 
 
473
 
        if (zone_preferences.size() == 0)
474
 
                return;
475
 
 
476
 
        thd_log_info("Giving up thermal control \n");
477
 
 
478
 
        csys_fs sysfs("/sys/class/thermal/");
479
 
 
480
 
        DIR *dir;
481
 
        struct dirent *entry;
482
 
        const std::string base_path = "/sys/class/thermal/";
483
 
        int cnt = 0;
484
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
485
 
                while ((entry = readdir(dir)) != NULL) {
486
 
                        if (!strncmp(entry->d_name, "thermal_zone",
487
 
                                        strlen("thermal_zone"))) {
488
 
                                int i;
489
 
 
490
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
491
 
                                std::stringstream policy;
492
 
 
493
 
                                policy << "thermal_zone" << i << "/policy";
494
 
                                if (sysfs.exists(policy.str().c_str())) {
495
 
                                        sysfs.write(policy.str(), zone_preferences[cnt++]);
496
 
                                }
497
 
                        }
498
 
                }
499
 
                closedir(dir);
500
 
        }
501
 
}
502
 
 
503
 
void cthd_engine::process_terminate() {
504
 
        thd_log_warn("terminating on user request ..\n");
505
 
        giveup_thermal_control();
506
 
        exit(EXIT_SUCCESS);
507
 
}
508
 
 
509
 
void cthd_engine::thd_engine_poll_enable(int sensor_id) {
510
 
        send_message(POLL_ENABLE, (int) sizeof(sensor_id),
511
 
                        (unsigned char*) &sensor_id);
512
 
}
513
 
 
514
 
void cthd_engine::thd_engine_poll_disable(int sensor_id) {
515
 
        send_message(POLL_DISABLE, (int) sizeof(sensor_id),
516
 
                        (unsigned char*) &sensor_id);
517
 
}
518
 
 
519
 
void cthd_engine::thd_engine_reload_zones() {
520
 
        thd_log_warn(" Reloading zones\n");
521
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
522
 
                cthd_zone *zone = zones[i];
523
 
                delete zone;
524
 
        }
525
 
        zones.clear();
526
 
 
527
 
        int ret = read_thermal_zones();
528
 
        if (ret != THD_SUCCESS) {
529
 
                thd_log_error("No thermal sensors found\n");
530
 
                // This is a fatal error and daemon will exit
531
 
                return;
532
 
        }
533
 
}
534
 
 
535
 
// Add any tested platform ids in this table
536
 
static supported_ids_t id_table[] = { { 6, 0x2a }, // Sandybridge
537
 
                { 6, 0x2d }, // Sandybridge
538
 
                { 6, 0x3a }, // IvyBridge
539
 
                { 6, 0x3c }, { 6, 0x3e }, { 6, 0x3f }, { 6, 0x45 }, // Haswell ULT */
540
 
                { 6, 0x46 }, // Haswell ULT */
541
 
 
542
 
                { 0, 0 } // Last Invalid entry
543
 
};
544
 
 
545
 
int cthd_engine::check_cpu_id() {
546
 
#ifndef ANDROID
547
 
        // Copied from turbostat program
548
 
        unsigned int ebx, ecx, edx, max_level;
549
 
        unsigned int fms, family, model, stepping;
550
 
        genuine_intel = 0;
551
 
        int i = 0;
552
 
        bool valid = false;
553
 
 
554
 
        proc_list_matched = false;
555
 
        ebx = ecx = edx = 0;
556
 
 
557
 
        __cpuid(0, max_level, ebx, ecx, edx);
558
 
        if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
559
 
                genuine_intel = 1;
560
 
        if (genuine_intel == 0) {
561
 
                // Simply return without further capability check
562
 
                return THD_SUCCESS;
563
 
        }
564
 
        __cpuid(1, fms, ebx, ecx, edx);
565
 
        family = (fms >> 8) & 0xf;
566
 
        model = (fms >> 4) & 0xf;
567
 
        stepping = fms & 0xf;
568
 
        if (family == 6 || family == 0xf)
569
 
                model += ((fms >> 16) & 0xf) << 4;
570
 
 
571
 
        thd_log_warn(
572
 
                        "%u CPUID levels; family:model:stepping 0x%x:%x:%x (%u:%u:%u)\n",
573
 
                        max_level, family, model, stepping, family, model, stepping);
574
 
 
575
 
        while (id_table[i].family) {
576
 
                if (id_table[i].family == family && id_table[i].model == model) {
577
 
                        proc_list_matched = true;
578
 
                        valid = true;
579
 
                        break;
580
 
                }
581
 
                i++;
582
 
        }
583
 
        if (!valid) {
584
 
                thd_log_warn(" No support RAPL and Intel P state driver\n");
585
 
        }
586
 
 
587
 
        if (!(edx & (1 << 5))) {
588
 
                thd_log_warn("No MSR supported on processor \n");
589
 
        }
590
 
#endif
591
 
        return THD_SUCCESS;
592
 
}
593
 
 
594
 
void cthd_engine::thd_read_default_thermal_sensors() {
595
 
        DIR *dir;
596
 
        struct dirent *entry;
597
 
        const std::string base_path = "/sys/class/thermal/";
598
 
 
599
 
        thd_log_debug("thd_read_default_thermal_sensors \n");
600
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
601
 
                while ((entry = readdir(dir)) != NULL) {
602
 
                        if (!strncmp(entry->d_name, "thermal_zone",
603
 
                                        strlen("thermal_zone"))) {
604
 
                                int i;
605
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
606
 
                                cthd_sensor *sensor = new cthd_sensor(i,
607
 
                                                base_path + entry->d_name + "/", "");
608
 
                                if (sensor->sensor_update() != THD_SUCCESS) {
609
 
                                        delete sensor;
610
 
                                        continue;
611
 
                                }
612
 
                                sensors.push_back(sensor);
613
 
                        }
614
 
                }
615
 
                closedir(dir);
616
 
        }
617
 
        sensor_count = sensors.size();
618
 
        thd_log_info("thd_read_default_thermal_sensors loaded %d sensors \n",
619
 
                        sensor_count);
620
 
}
621
 
 
622
 
void cthd_engine::thd_read_default_thermal_zones() {
623
 
        DIR *dir;
624
 
        struct dirent *entry;
625
 
        const std::string base_path = "/sys/class/thermal/";
626
 
 
627
 
        thd_log_debug("thd_read_default_thermal_zones \n");
628
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
629
 
                while ((entry = readdir(dir)) != NULL) {
630
 
                        if (!strncmp(entry->d_name, "thermal_zone",
631
 
                                        strlen("thermal_zone"))) {
632
 
                                int i;
633
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
634
 
                                cthd_sysfs_zone *zone = new cthd_sysfs_zone(i,
635
 
                                                "/sys/class/thermal/thermal_zone");
636
 
                                if (zone->zone_update() != THD_SUCCESS) {
637
 
                                        delete zone;
638
 
                                        continue;
639
 
                                }
640
 
                                if (control_mode == EXCLUSIVE)
641
 
                                        zone->set_zone_active();
642
 
                                zones.push_back(zone);
643
 
                        }
644
 
                }
645
 
                closedir(dir);
646
 
        }
647
 
        zone_count = zones.size();
648
 
        thd_log_info("thd_read_default_thermal_zones loaded %d zones \n",
649
 
                        zone_count);
650
 
}
651
 
 
652
 
void cthd_engine::thd_read_default_cooling_devices() {
653
 
 
654
 
        DIR *dir;
655
 
        struct dirent *entry;
656
 
        const std::string base_path = "/sys/class/thermal/";
657
 
 
658
 
        thd_log_debug("thd_read_default_cooling devices \n");
659
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
660
 
                while ((entry = readdir(dir)) != NULL) {
661
 
                        if (!strncmp(entry->d_name, "cooling_device",
662
 
                                        strlen("cooling_device"))) {
663
 
                                int i;
664
 
                                i = atoi(entry->d_name + strlen("cooling_device"));
665
 
                                cthd_sysfs_cdev *cdev = new cthd_sysfs_cdev(i,
666
 
                                                "/sys/class/thermal/");
667
 
                                if (cdev->update() != THD_SUCCESS) {
668
 
                                        delete cdev;
669
 
                                        continue;
670
 
                                }
671
 
                                cdevs.push_back(cdev);
672
 
                        }
673
 
                }
674
 
                closedir(dir);
675
 
        }
676
 
        cdev_cnt = cdevs.size();
677
 
        thd_log_info("thd_read_default_cooling devices loaded %d cdevs \n",
678
 
                        cdev_cnt);
679
 
}
680
 
 
681
 
cthd_zone* cthd_engine::search_zone(std::string name) {
682
 
        cthd_zone *zone;
683
 
 
684
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
685
 
                zone = zones[i];
686
 
                if (!zone)
687
 
                        continue;
688
 
                if (zone->get_zone_type() == name)
689
 
                        return zone;
690
 
        }
691
 
 
692
 
        return NULL;
693
 
}
694
 
 
695
 
cthd_cdev* cthd_engine::search_cdev(std::string name) {
696
 
        cthd_cdev *cdev;
697
 
 
698
 
        for (unsigned int i = 0; i < cdevs.size(); ++i) {
699
 
                cdev = cdevs[i];
700
 
                if (!cdev)
701
 
                        continue;
702
 
                if (cdev->get_cdev_type() == name)
703
 
                        return cdev;
704
 
        }
705
 
 
706
 
        return NULL;
707
 
}
708
 
 
709
 
cthd_sensor* cthd_engine::search_sensor(std::string name) {
710
 
        cthd_sensor *sensor;
711
 
 
712
 
        for (unsigned int i = 0; i < sensors.size(); ++i) {
713
 
                sensor = sensors[i];
714
 
                if (!sensor)
715
 
                        continue;
716
 
                if (sensor->get_sensor_type() == name)
717
 
                        return sensor;
718
 
        }
719
 
 
720
 
        return NULL;
721
 
}
722
 
 
723
 
cthd_sensor* cthd_engine::get_sensor(int index) {
724
 
        if (index >= 0 && index < (int) sensors.size())
725
 
                return sensors[index];
726
 
        else
727
 
                return NULL;
728
 
}
729
 
 
730
 
cthd_zone* cthd_engine::get_zone(int index) {
731
 
        if (index == -1)
732
 
                return NULL;
733
 
        if (index >= 0 && index < (int) zones.size())
734
 
                return zones[index];
735
 
        else
736
 
                return NULL;
737
 
}
738
 
 
739
 
cthd_zone* cthd_engine::get_zone(std::string type) {
740
 
        cthd_zone *zone;
741
 
 
742
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
743
 
                zone = zones[i];
744
 
                if (zone->get_zone_type() == type)
745
 
                        return zone;
746
 
        }
747
 
 
748
 
        return NULL;
749
 
}