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

« back to all changes in this revision

Viewing changes to .pc/0017-Fix-up-some-memory-leaks-in-THD_SUCCESS-branches.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
 
        fcntl(wake_fds[0], F_SETFL, O_NONBLOCK);
158
 
        fcntl(wake_fds[1], F_SETFL, O_NONBLOCK);
159
 
        write_pipe_fd = wake_fds[1];
160
 
        wakeup_fd = THD_NUM_OF_POLL_FDS - 1;
161
 
 
162
 
        memset(poll_fds, 0, sizeof(poll_fds));
163
 
        poll_fds[wakeup_fd].fd = wake_fds[0];
164
 
        poll_fds[wakeup_fd].events = POLLIN;
165
 
        poll_fds[wakeup_fd].revents = 0;
166
 
 
167
 
        poll_timeout_msec = -1;
168
 
        if (poll_interval_sec) {
169
 
                thd_log_warn("Polling mode is enabled: %d\n", poll_interval_sec);
170
 
                poll_timeout_msec = poll_interval_sec * 1000;
171
 
        }
172
 
 
173
 
        ret = read_thermal_sensors();
174
 
        if (ret != THD_SUCCESS) {
175
 
                thd_log_error("Thermal sysfs Error in reading sensors\n");
176
 
                // This is a fatal error and daemon will exit
177
 
                return THD_FATAL_ERROR;
178
 
        }
179
 
 
180
 
        ret = read_cooling_devices();
181
 
        if (ret != THD_SUCCESS) {
182
 
                thd_log_error("Thermal sysfs Error in reading cooling devs\n");
183
 
                // This is a fatal error and daemon will exit
184
 
                return THD_FATAL_ERROR;
185
 
        }
186
 
 
187
 
        ret = read_thermal_zones();
188
 
        if (ret != THD_SUCCESS) {
189
 
                thd_log_error("No thermal sensors found\n");
190
 
                // This is a fatal error and daemon will exit
191
 
                return THD_FATAL_ERROR;
192
 
        }
193
 
 
194
 
        // Check if polling is disabled and sensors don't support
195
 
        // async mode, in that enable force polling
196
 
        if (!poll_interval_sec) {
197
 
                unsigned int i;
198
 
                for (i = 0; i < zones.size(); ++i) {
199
 
                        cthd_zone *zone = zones[i];
200
 
                        if (!zone->zone_active_status())
201
 
                                continue;
202
 
                        if (!zone->check_sensor_async_status()) {
203
 
                                thd_log_warn(
204
 
                                                "Polling will be enabled as some sensors are not capable to notify asynchnously \n");
205
 
                                poll_timeout_msec = def_poll_interval;
206
 
                                break;
207
 
                        }
208
 
                }
209
 
                if (i == zones.size()) {
210
 
                        thd_log_info("Proceed without polling mode! \n");
211
 
                }
212
 
        }
213
 
 
214
 
        poll_fds[0].fd = kobj_uevent.kobj_uevent_open();
215
 
        if (poll_fds[0].fd < 0) {
216
 
                thd_log_warn("Invalid kobj_uevent handle\n");
217
 
                goto skip_kobj;
218
 
        }
219
 
        thd_log_info("FD = %d\n", poll_fds[0].fd);
220
 
        kobj_uevent.register_dev_path(
221
 
                        (char *) "/devices/virtual/thermal/thermal_zone");
222
 
        poll_fds[0].events = POLLIN;
223
 
        poll_fds[0].revents = 0;
224
 
        skip_kobj:
225
 
#ifndef DISABLE_PTHREAD
226
 
        // condition variable
227
 
        pthread_cond_init(&thd_cond_var, NULL);
228
 
        pthread_mutex_init(&thd_cond_mutex, NULL);
229
 
        // Create thread
230
 
        pthread_attr_init(&thd_attr);
231
 
        pthread_attr_setdetachstate(&thd_attr, PTHREAD_CREATE_DETACHED);
232
 
        ret = pthread_create(&thd_engine, &thd_attr, cthd_engine_thread,
233
 
                        (void*) this);
234
 
#else
235
 
        {
236
 
                pid_t childpid;
237
 
 
238
 
                if((childpid = fork()) == - 1)
239
 
                {
240
 
                        perror("fork");
241
 
                        exit(EXIT_FAILURE);
242
 
                }
243
 
 
244
 
                if(childpid == 0)
245
 
                {
246
 
                        /* Child process closes up input side of pipe */
247
 
                        close(wake_fds[1]);
248
 
                        cthd_engine_thread((void*)this);
249
 
                }
250
 
                else
251
 
                {
252
 
                        /* Parent process closes up output side of pipe */
253
 
                        close(wake_fds[0]);
254
 
                }
255
 
        }
256
 
#endif
257
 
        preference = thd_pref.get_preference();
258
 
        thd_log_info("Current user preference is %d\n", preference);
259
 
 
260
 
        if (control_mode == EXCLUSIVE) {
261
 
                thd_log_info("Control is taken over from kernel\n");
262
 
                takeover_thermal_control();
263
 
        }
264
 
        return ret;
265
 
}
266
 
 
267
 
int cthd_engine::thd_engine_stop() {
268
 
        return THD_SUCCESS;
269
 
}
270
 
 
271
 
static void *cthd_engine_thread(void *arg) {
272
 
        cthd_engine *obj = (cthd_engine*) arg;
273
 
 
274
 
        obj->thd_engine_thread();
275
 
 
276
 
        return NULL;
277
 
}
278
 
 
279
 
void cthd_engine::send_message(message_name_t msg_id, int size,
280
 
                unsigned char *msg) {
281
 
        message_capsul_t msg_cap;
282
 
 
283
 
        memset(&msg_cap, 0, sizeof(message_capsul_t));
284
 
 
285
 
        msg_cap.msg_id = msg_id;
286
 
        msg_cap.msg_size = (size > MAX_MSG_SIZE) ? MAX_MSG_SIZE : size;
287
 
        if (msg)
288
 
                memcpy(msg_cap.msg, msg, msg_cap.msg_size);
289
 
        int result = write(write_pipe_fd, &msg_cap, sizeof(message_capsul_t));
290
 
        if (result < 0)
291
 
                thd_log_warn("Write to pipe failed \n");
292
 
}
293
 
 
294
 
void cthd_engine::process_pref_change() {
295
 
        int new_pref;
296
 
 
297
 
        thd_pref.refresh();
298
 
        new_pref = thd_pref.get_preference();
299
 
        if (new_pref == PREF_DISABLED) {
300
 
                status = false;
301
 
                return;
302
 
        }
303
 
        status = true;
304
 
        if (preference != new_pref) {
305
 
                thd_log_warn("Preference changed \n");
306
 
        }
307
 
        preference = new_pref;
308
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
309
 
                cthd_zone *zone = zones[i];
310
 
                zone->update_zone_preference();
311
 
        }
312
 
 
313
 
        if (control_mode == EXCLUSIVE) {
314
 
                thd_log_info("Control is taken over from kernel\n");
315
 
                takeover_thermal_control();
316
 
        }
317
 
}
318
 
 
319
 
void cthd_engine::thd_engine_terminate() {
320
 
        send_message(TERMINATE, 0, NULL);
321
 
        sleep(1);
322
 
        process_terminate();
323
 
}
324
 
 
325
 
int cthd_engine::thd_engine_set_user_max_temp(const char *zone_type,
326
 
                const char *user_set_point) {
327
 
        std::string str(user_set_point);
328
 
        cthd_zone *zone;
329
 
 
330
 
        thd_log_debug("thd_engine_set_user_set_point %s\n", user_set_point);
331
 
 
332
 
        std::locale loc;
333
 
        if (std::isdigit(str[0], loc) == 0) {
334
 
                thd_log_warn("thd_engine_set_user_set_point Invalid set point\n");
335
 
                return THD_ERROR;
336
 
        }
337
 
 
338
 
        zone = get_zone(zone_type);
339
 
        if (!zone) {
340
 
                thd_log_warn("thd_engine_set_user_set_point Invalid zone\n");
341
 
                return THD_ERROR;
342
 
        }
343
 
        return zone->update_max_temperature(atoi(user_set_point));
344
 
}
345
 
 
346
 
void cthd_engine::thermal_zone_change(message_capsul_t *msg) {
347
 
 
348
 
        thermal_zone_notify_t *pmsg = (thermal_zone_notify_t*) msg->msg;
349
 
        for (unsigned i = 0; i < zones.size(); ++i) {
350
 
                cthd_zone *zone = zones[i];
351
 
                if (zone->zone_active_status())
352
 
                        zone->zone_temperature_notification(pmsg->type, pmsg->data);
353
 
                else {
354
 
                        thd_log_debug("zone is not active\n");
355
 
                }
356
 
        }
357
 
}
358
 
 
359
 
void cthd_engine::poll_enable_disable(bool status, message_capsul_t *msg) {
360
 
        unsigned int *sensor_id = (unsigned int*) msg->msg;
361
 
 
362
 
        if (status) {
363
 
                poll_sensor_mask |= (1 << (*sensor_id));
364
 
                poll_timeout_msec = def_poll_interval;
365
 
                thd_log_debug("thd_engine polling enabled via %u \n", *sensor_id);
366
 
        } else {
367
 
                poll_sensor_mask &= ~(1 << (*sensor_id));
368
 
                if (!poll_sensor_mask) {
369
 
                        poll_timeout_msec = -1;
370
 
                        thd_log_debug("thd_engine polling last disabled via %u \n",
371
 
                                        *sensor_id);
372
 
                }
373
 
        }
374
 
}
375
 
 
376
 
int cthd_engine::proc_message(message_capsul_t *msg) {
377
 
        int ret = 0;
378
 
 
379
 
        thd_log_debug("Receieved message %d\n", msg->msg_id);
380
 
        switch (msg->msg_id) {
381
 
        case WAKEUP:
382
 
                break;
383
 
        case TERMINATE:
384
 
                thd_log_warn("Terminating ...\n");
385
 
 
386
 
                ret = -1;
387
 
                terminate = true;
388
 
                break;
389
 
        case PREF_CHANGED:
390
 
                process_pref_change();
391
 
                break;
392
 
        case THERMAL_ZONE_NOTIFY:
393
 
                if (!status) {
394
 
                        thd_log_warn("Thermal Daemon is disabled \n");
395
 
                        break;
396
 
                }
397
 
                thermal_zone_change(msg);
398
 
                break;
399
 
        case CALIBRATE: {
400
 
                //TO DO
401
 
        }
402
 
                break;
403
 
        case RELOAD_ZONES:
404
 
                thd_engine_reload_zones();
405
 
                break;
406
 
        case POLL_ENABLE:
407
 
                if (!poll_interval_sec) {
408
 
                        poll_enable_disable(true, msg);
409
 
                }
410
 
                break;
411
 
        case POLL_DISABLE:
412
 
                if (!poll_interval_sec) {
413
 
                        poll_enable_disable(false, msg);
414
 
                }
415
 
                break;
416
 
        default:
417
 
                break;
418
 
        }
419
 
 
420
 
        return ret;
421
 
}
422
 
 
423
 
cthd_cdev *cthd_engine::thd_get_cdev_at_index(int index) {
424
 
        for (int i = 0; i < cdev_cnt; ++i) {
425
 
                if (cdevs[i]->thd_cdev_get_index() == index)
426
 
                        return cdevs[i];
427
 
        }
428
 
        return NULL;
429
 
}
430
 
 
431
 
void cthd_engine::takeover_thermal_control() {
432
 
        csys_fs sysfs("/sys/class/thermal/");
433
 
 
434
 
        DIR *dir;
435
 
        struct dirent *entry;
436
 
        const std::string base_path = "/sys/class/thermal/";
437
 
 
438
 
        thd_log_info("Taking over thermal control \n");
439
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
440
 
                while ((entry = readdir(dir)) != NULL) {
441
 
                        if (!strncmp(entry->d_name, "thermal_zone",
442
 
                                        strlen("thermal_zone"))) {
443
 
                                int i;
444
 
 
445
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
446
 
                                std::stringstream policy;
447
 
                                std::stringstream type;
448
 
                                std::string type_val;
449
 
                                std::string curr_policy;
450
 
 
451
 
                                type << "thermal_zone" << i << "/type";
452
 
                                if (sysfs.exists(type.str().c_str())) {
453
 
                                        sysfs.read(type.str(), type_val);
454
 
                                }
455
 
                                policy << "thermal_zone" << i << "/policy";
456
 
                                if (sysfs.exists(policy.str().c_str())) {
457
 
                                        sysfs.read(policy.str(), curr_policy);
458
 
                                        zone_preferences.push_back(curr_policy);
459
 
                                        sysfs.write(policy.str(), "user_space");
460
 
                                }
461
 
                        }
462
 
                }
463
 
                closedir(dir);
464
 
        }
465
 
}
466
 
 
467
 
void cthd_engine::giveup_thermal_control() {
468
 
        if (control_mode != EXCLUSIVE)
469
 
                return;
470
 
 
471
 
        if (zone_preferences.size() == 0)
472
 
                return;
473
 
 
474
 
        thd_log_info("Giving up thermal control \n");
475
 
 
476
 
        csys_fs sysfs("/sys/class/thermal/");
477
 
 
478
 
        DIR *dir;
479
 
        struct dirent *entry;
480
 
        const std::string base_path = "/sys/class/thermal/";
481
 
        int cnt = 0;
482
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
483
 
                while ((entry = readdir(dir)) != NULL) {
484
 
                        if (!strncmp(entry->d_name, "thermal_zone",
485
 
                                        strlen("thermal_zone"))) {
486
 
                                int i;
487
 
 
488
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
489
 
                                std::stringstream policy;
490
 
                                std::stringstream type;
491
 
                                std::string type_val;
492
 
 
493
 
                                type << "thermal_zone" << i << "/type";
494
 
                                if (sysfs.exists(type.str().c_str())) {
495
 
                                        sysfs.read(type.str(), type_val);
496
 
                                }
497
 
                                policy << "thermal_zone" << i << "/policy";
498
 
                                if (sysfs.exists(policy.str().c_str())) {
499
 
                                        sysfs.write(policy.str(), zone_preferences[cnt++]);
500
 
                                }
501
 
                        }
502
 
                }
503
 
                closedir(dir);
504
 
        }
505
 
}
506
 
 
507
 
void cthd_engine::process_terminate() {
508
 
        thd_log_warn("terminating on user request ..\n");
509
 
        giveup_thermal_control();
510
 
        exit(EXIT_SUCCESS);
511
 
}
512
 
 
513
 
void cthd_engine::thd_engine_poll_enable(int sensor_id) {
514
 
        send_message(POLL_ENABLE, (int) sizeof(sensor_id),
515
 
                        (unsigned char*) &sensor_id);
516
 
}
517
 
 
518
 
void cthd_engine::thd_engine_poll_disable(int sensor_id) {
519
 
        send_message(POLL_DISABLE, (int) sizeof(sensor_id),
520
 
                        (unsigned char*) &sensor_id);
521
 
}
522
 
 
523
 
void cthd_engine::thd_engine_reload_zones() {
524
 
        thd_log_warn(" Reloading zones\n");
525
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
526
 
                cthd_zone *zone = zones[i];
527
 
                delete zone;
528
 
        }
529
 
        zones.clear();
530
 
 
531
 
        int ret = read_thermal_zones();
532
 
        if (ret != THD_SUCCESS) {
533
 
                thd_log_error("No thermal sensors found\n");
534
 
                // This is a fatal error and daemon will exit
535
 
                return;
536
 
        }
537
 
}
538
 
 
539
 
// Add any tested platform ids in this table
540
 
static supported_ids_t id_table[] = { { 6, 0x2a }, // Sandybridge
541
 
                { 6, 0x2d }, // Sandybridge
542
 
                { 6, 0x3a }, // IvyBridge
543
 
                { 6, 0x3c }, { 6, 0x3e }, { 6, 0x3f }, { 6, 0x45 }, // Haswell ULT */
544
 
                { 6, 0x46 }, // Haswell ULT */
545
 
 
546
 
                { 0, 0 } // Last Invalid entry
547
 
};
548
 
 
549
 
int cthd_engine::check_cpu_id() {
550
 
#ifndef ANDROID
551
 
        // Copied from turbostat program
552
 
        unsigned int ebx, ecx, edx, max_level;
553
 
        unsigned int fms, family, model, stepping;
554
 
        genuine_intel = 0;
555
 
        int i = 0;
556
 
        bool valid = false;
557
 
 
558
 
        proc_list_matched = false;
559
 
        ebx = ecx = edx = 0;
560
 
 
561
 
        __cpuid(0, max_level, ebx, ecx, edx);
562
 
        if (ebx == 0x756e6547 && edx == 0x49656e69 && ecx == 0x6c65746e)
563
 
                genuine_intel = 1;
564
 
        if (genuine_intel == 0) {
565
 
                // Simply return without further capability check
566
 
                return THD_SUCCESS;
567
 
        }
568
 
        __cpuid(1, fms, ebx, ecx, edx);
569
 
        family = (fms >> 8) & 0xf;
570
 
        model = (fms >> 4) & 0xf;
571
 
        stepping = fms & 0xf;
572
 
        if (family == 6 || family == 0xf)
573
 
                model += ((fms >> 16) & 0xf) << 4;
574
 
 
575
 
        thd_log_warn(
576
 
                        "%d CPUID levels; family:model:stepping 0x%x:%x:%x (%d:%d:%d)\n",
577
 
                        max_level, family, model, stepping, family, model, stepping);
578
 
 
579
 
        while (id_table[i].family) {
580
 
                if (id_table[i].family == family && id_table[i].model == model) {
581
 
                        proc_list_matched = true;
582
 
                        valid = true;
583
 
                        break;
584
 
                }
585
 
                i++;
586
 
        }
587
 
        if (!valid) {
588
 
                thd_log_warn(" No support RAPL and Intel P state driver\n");
589
 
        }
590
 
 
591
 
        if (!(edx & (1 << 5))) {
592
 
                thd_log_warn("No MSR supported on processor \n");
593
 
        }
594
 
#endif
595
 
        return THD_SUCCESS;
596
 
}
597
 
 
598
 
void cthd_engine::thd_read_default_thermal_sensors() {
599
 
        DIR *dir;
600
 
        struct dirent *entry;
601
 
        const std::string base_path = "/sys/class/thermal/";
602
 
 
603
 
        thd_log_debug("thd_read_default_thermal_sensors \n");
604
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
605
 
                while ((entry = readdir(dir)) != NULL) {
606
 
                        if (!strncmp(entry->d_name, "thermal_zone",
607
 
                                        strlen("thermal_zone"))) {
608
 
                                int i;
609
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
610
 
                                cthd_sensor *sensor = new cthd_sensor(i,
611
 
                                                base_path + entry->d_name + "/", "");
612
 
                                if (sensor->sensor_update() != THD_SUCCESS)
613
 
                                        continue;
614
 
                                sensors.push_back(sensor);
615
 
                        }
616
 
                }
617
 
                closedir(dir);
618
 
        }
619
 
        sensor_count = sensors.size();
620
 
        thd_log_info("thd_read_default_thermal_sensors loaded %d sensors \n",
621
 
                        sensor_count);
622
 
}
623
 
 
624
 
void cthd_engine::thd_read_default_thermal_zones() {
625
 
        DIR *dir;
626
 
        struct dirent *entry;
627
 
        const std::string base_path = "/sys/class/thermal/";
628
 
 
629
 
        thd_log_debug("thd_read_default_thermal_zones \n");
630
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
631
 
                while ((entry = readdir(dir)) != NULL) {
632
 
                        if (!strncmp(entry->d_name, "thermal_zone",
633
 
                                        strlen("thermal_zone"))) {
634
 
                                int i;
635
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
636
 
                                cthd_sysfs_zone *zone = new cthd_sysfs_zone(i,
637
 
                                                "/sys/class/thermal/thermal_zone");
638
 
                                if (zone->zone_update() != THD_SUCCESS)
639
 
                                        continue;
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
 
                                        continue;
669
 
                                cdevs.push_back(cdev);
670
 
                        }
671
 
                }
672
 
                closedir(dir);
673
 
        }
674
 
        cdev_cnt = cdevs.size();
675
 
        thd_log_info("thd_read_default_cooling devices loaded %d cdevs \n",
676
 
                        cdev_cnt);
677
 
}
678
 
 
679
 
cthd_zone* cthd_engine::search_zone(std::string name) {
680
 
        cthd_zone *zone;
681
 
 
682
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
683
 
                zone = zones[i];
684
 
                if (!zone)
685
 
                        continue;
686
 
                if (zone->get_zone_type() == name)
687
 
                        return zone;
688
 
        }
689
 
 
690
 
        return NULL;
691
 
}
692
 
 
693
 
cthd_cdev* cthd_engine::search_cdev(std::string name) {
694
 
        cthd_cdev *cdev;
695
 
 
696
 
        for (unsigned int i = 0; i < cdevs.size(); ++i) {
697
 
                cdev = cdevs[i];
698
 
                if (!cdev)
699
 
                        continue;
700
 
                if (cdev->get_cdev_type() == name)
701
 
                        return cdev;
702
 
        }
703
 
 
704
 
        return NULL;
705
 
}
706
 
 
707
 
cthd_sensor* cthd_engine::search_sensor(std::string name) {
708
 
        cthd_sensor *sensor;
709
 
 
710
 
        for (unsigned int i = 0; i < sensors.size(); ++i) {
711
 
                sensor = sensors[i];
712
 
                if (!sensor)
713
 
                        continue;
714
 
                if (sensor->get_sensor_type() == name)
715
 
                        return sensor;
716
 
        }
717
 
 
718
 
        return NULL;
719
 
}
720
 
 
721
 
cthd_sensor* cthd_engine::get_sensor(int index) {
722
 
        if (index < (int) sensors.size())
723
 
                return sensors[index];
724
 
        else
725
 
                return NULL;
726
 
}
727
 
 
728
 
cthd_zone* cthd_engine::get_zone(int index) {
729
 
        if (index == -1)
730
 
                return NULL;
731
 
        if (index < (int) zones.size())
732
 
                return zones[index];
733
 
        else
734
 
                return NULL;
735
 
}
736
 
 
737
 
cthd_zone* cthd_engine::get_zone(std::string type) {
738
 
        cthd_zone *zone;
739
 
 
740
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
741
 
                zone = zones[i];
742
 
                if (zone->get_zone_type() == type)
743
 
                        return zone;
744
 
        }
745
 
 
746
 
        return NULL;
747
 
}