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

« back to all changes in this revision

Viewing changes to .pc/0011-pic-fixes.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 <locale>
38
 
#include "thd_engine.h"
39
 
#include "thd_cdev_therm_sys_fs.h"
40
 
#include "thd_zone_therm_sys_fs.h"
41
 
 
42
 
static void *cthd_engine_thread(void *arg);
43
 
 
44
 
cthd_engine::cthd_engine() :
45
 
                cdev_cnt(0), zone_count(0), sensor_count(0), parse_thermal_zone_success(
46
 
                                false), parse_thermal_cdev_success(false), poll_timeout_msec(
47
 
                                -1), wakeup_fd(0), control_mode(COMPLEMENTRY), write_pipe_fd(0), preference(
48
 
                                0), status(true), thz_last_time(0), terminate(false), genuine_intel(
49
 
                                0), has_invariant_tsc(0), has_aperf(0), proc_list_matched(
50
 
                                false), poll_interval_sec(0), poll_sensor_mask(0) {
51
 
        thd_engine = pthread_t();
52
 
        thd_attr = pthread_attr_t();
53
 
        thd_cond_var = pthread_cond_t();
54
 
        thd_cond_mutex = pthread_mutex_t();
55
 
}
56
 
 
57
 
cthd_engine::~cthd_engine() {
58
 
        unsigned int i;
59
 
 
60
 
        for (i = 0; i < sensors.size(); ++i) {
61
 
                delete sensors[i];
62
 
        }
63
 
        sensors.clear();
64
 
        for (i = 0; i < zones.size(); ++i) {
65
 
                delete zones[i];
66
 
        }
67
 
        zones.clear();
68
 
        for (i = 0; i < cdevs.size(); ++i) {
69
 
                delete cdevs[i];
70
 
        }
71
 
        cdevs.clear();
72
 
}
73
 
 
74
 
void cthd_engine::thd_engine_thread() {
75
 
        unsigned int i;
76
 
        int n;
77
 
 
78
 
        thd_log_info("thd_engine_thread begin\n");
79
 
        for (;;) {
80
 
                if (terminate)
81
 
                        break;
82
 
                n = poll(poll_fds, THD_NUM_OF_POLL_FDS, poll_timeout_msec);
83
 
                thd_log_debug("poll exit %d \n", n);
84
 
                if (n < 0) {
85
 
                        thd_log_warn("Write to pipe failed \n");
86
 
                        continue;
87
 
                }
88
 
                if (n == 0) {
89
 
                        if (!status) {
90
 
                                thd_log_warn("Thermal Daemon is disabled \n");
91
 
                                continue;
92
 
                        }
93
 
                        // Polling mode enabled. Trigger a temp change message
94
 
                        for (i = 0; i < zones.size(); ++i) {
95
 
                                cthd_zone *zone = zones[i];
96
 
                                zone->zone_temperature_notification(0, 0);
97
 
                        }
98
 
                }
99
 
                if (poll_fds[0].revents & POLLIN) {
100
 
                        // Kobj uevent
101
 
                        if (kobj_uevent.check_for_event()) {
102
 
                                time_t tm;
103
 
 
104
 
                                time(&tm);
105
 
                                thd_log_debug("kobj uevent for thermal\n");
106
 
                                if ((tm - thz_last_time) >= thz_notify_debounce_interval) {
107
 
                                        for (i = 0; i < zones.size(); ++i) {
108
 
                                                cthd_zone *zone = zones[i];
109
 
                                                zone->zone_temperature_notification(0, 0);
110
 
                                        }
111
 
                                } else {
112
 
                                        thd_log_debug("IGNORE THZ kevent\n");
113
 
                                }
114
 
                                thz_last_time = tm;
115
 
                        }
116
 
                }
117
 
                if (poll_fds[wakeup_fd].revents & POLLIN) {
118
 
                        message_capsul_t msg;
119
 
 
120
 
                        thd_log_debug("wakeup fd event\n");
121
 
                        int result = read(poll_fds[wakeup_fd].fd, &msg,
122
 
                                        sizeof(message_capsul_t));
123
 
                        if (result < 0) {
124
 
                                thd_log_warn("read on wakeup fd failed\n");
125
 
                                poll_fds[wakeup_fd].revents = 0;
126
 
                                continue;
127
 
                        }
128
 
                        if (proc_message(&msg) < 0) {
129
 
                                thd_log_debug("Terminating thread..\n");
130
 
                        }
131
 
                }
132
 
        }
133
 
        thd_log_debug("thd_engine_thread_end\n");
134
 
}
135
 
 
136
 
bool cthd_engine::set_preference(const int pref) {
137
 
        return true;
138
 
}
139
 
 
140
 
int cthd_engine::thd_engine_start(bool ignore_cpuid_check) {
141
 
        int ret;
142
 
        int wake_fds[2];
143
 
 
144
 
        if (ignore_cpuid_check) {
145
 
                thd_log_debug("Ignore CPU ID check for MSRs \n");
146
 
                proc_list_matched = true;
147
 
        } else
148
 
                check_cpu_id();
149
 
 
150
 
        // Pipe is used for communication between two processes
151
 
        ret = pipe(wake_fds);
152
 
        if (ret) {
153
 
                thd_log_error("Thermal sysfs: pipe creation failed %d:\n", ret);
154
 
                return THD_FATAL_ERROR;
155
 
        }
156
 
        fcntl(wake_fds[0], F_SETFL, O_NONBLOCK);
157
 
        fcntl(wake_fds[1], F_SETFL, O_NONBLOCK);
158
 
        write_pipe_fd = wake_fds[1];
159
 
        wakeup_fd = THD_NUM_OF_POLL_FDS - 1;
160
 
 
161
 
        memset(poll_fds, 0, sizeof(poll_fds));
162
 
        poll_fds[wakeup_fd].fd = wake_fds[0];
163
 
        poll_fds[wakeup_fd].events = POLLIN;
164
 
        poll_fds[wakeup_fd].revents = 0;
165
 
 
166
 
        poll_timeout_msec = -1;
167
 
        if (poll_interval_sec) {
168
 
                thd_log_warn("Polling mode is enabled: %d\n", poll_interval_sec);
169
 
                poll_timeout_msec = poll_interval_sec * 1000;
170
 
        }
171
 
 
172
 
        ret = read_thermal_sensors();
173
 
        if (ret != THD_SUCCESS) {
174
 
                thd_log_error("Thermal sysfs Error in reading sensors\n");
175
 
                // This is a fatal error and daemon will exit
176
 
                return THD_FATAL_ERROR;
177
 
        }
178
 
 
179
 
        ret = read_cooling_devices();
180
 
        if (ret != THD_SUCCESS) {
181
 
                thd_log_error("Thermal sysfs Error in reading cooling devs\n");
182
 
                // This is a fatal error and daemon will exit
183
 
                return THD_FATAL_ERROR;
184
 
        }
185
 
 
186
 
        ret = read_thermal_zones();
187
 
        if (ret != THD_SUCCESS) {
188
 
                thd_log_error("No thermal sensors found\n");
189
 
                // This is a fatal error and daemon will exit
190
 
                return THD_FATAL_ERROR;
191
 
        }
192
 
 
193
 
        // Check if polling is disabled and sensors don't support
194
 
        // async mode, in that enable force polling
195
 
        if (!poll_interval_sec) {
196
 
                unsigned int i;
197
 
                for (i = 0; i < zones.size(); ++i) {
198
 
                        cthd_zone *zone = zones[i];
199
 
                        if (!zone->zone_active_status())
200
 
                                continue;
201
 
                        if (!zone->check_sensor_async_status()) {
202
 
                                thd_log_warn(
203
 
                                                "Polling will be enabled as some sensors are not capable to notify asynchnously \n");
204
 
                                poll_timeout_msec = def_poll_interval;
205
 
                                break;
206
 
                        }
207
 
                }
208
 
                if (i == zones.size()) {
209
 
                        thd_log_info("Proceed without polling mode! \n");
210
 
                }
211
 
        }
212
 
 
213
 
        poll_fds[0].fd = kobj_uevent.kobj_uevent_open();
214
 
        if (poll_fds[0].fd < 0) {
215
 
                thd_log_warn("Invalid kobj_uevent handle\n");
216
 
                goto skip_kobj;
217
 
        }
218
 
        thd_log_info("FD = %d\n", poll_fds[0].fd);
219
 
        kobj_uevent.register_dev_path(
220
 
                        (char *) "/devices/virtual/thermal/thermal_zone");
221
 
        poll_fds[0].events = POLLIN;
222
 
        poll_fds[0].revents = 0;
223
 
        skip_kobj:
224
 
#ifndef DISABLE_PTHREAD
225
 
        // condition variable
226
 
        pthread_cond_init(&thd_cond_var, NULL);
227
 
        pthread_mutex_init(&thd_cond_mutex, NULL);
228
 
        // Create thread
229
 
        pthread_attr_init(&thd_attr);
230
 
        pthread_attr_setdetachstate(&thd_attr, PTHREAD_CREATE_DETACHED);
231
 
        ret = pthread_create(&thd_engine, &thd_attr, cthd_engine_thread,
232
 
                        (void*) this);
233
 
#else
234
 
        {
235
 
                pid_t childpid;
236
 
 
237
 
                if((childpid = fork()) == - 1)
238
 
                {
239
 
                        perror("fork");
240
 
                        exit(EXIT_FAILURE);
241
 
                }
242
 
 
243
 
                if(childpid == 0)
244
 
                {
245
 
                        /* Child process closes up input side of pipe */
246
 
                        close(wake_fds[1]);
247
 
                        cthd_engine_thread((void*)this);
248
 
                }
249
 
                else
250
 
                {
251
 
                        /* Parent process closes up output side of pipe */
252
 
                        close(wake_fds[0]);
253
 
                }
254
 
        }
255
 
#endif
256
 
        preference = thd_pref.get_preference();
257
 
        thd_log_info("Current user preference is %d\n", preference);
258
 
 
259
 
        if (control_mode == EXCLUSIVE) {
260
 
                thd_log_info("Control is taken over from kernel\n");
261
 
                takeover_thermal_control();
262
 
        }
263
 
        return ret;
264
 
}
265
 
 
266
 
int cthd_engine::thd_engine_stop() {
267
 
        return THD_SUCCESS;
268
 
}
269
 
 
270
 
static void *cthd_engine_thread(void *arg) {
271
 
        cthd_engine *obj = (cthd_engine*) arg;
272
 
 
273
 
        obj->thd_engine_thread();
274
 
 
275
 
        return NULL;
276
 
}
277
 
 
278
 
void cthd_engine::send_message(message_name_t msg_id, int size,
279
 
                unsigned char *msg) {
280
 
        message_capsul_t msg_cap;
281
 
 
282
 
        memset(&msg_cap, 0, sizeof(message_capsul_t));
283
 
 
284
 
        msg_cap.msg_id = msg_id;
285
 
        msg_cap.msg_size = (size > MAX_MSG_SIZE) ? MAX_MSG_SIZE : size;
286
 
        if (msg)
287
 
                memcpy(msg_cap.msg, msg, msg_cap.msg_size);
288
 
        int result = write(write_pipe_fd, &msg_cap, sizeof(message_capsul_t));
289
 
        if (result < 0)
290
 
                thd_log_warn("Write to pipe failed \n");
291
 
}
292
 
 
293
 
void cthd_engine::process_pref_change() {
294
 
        int new_pref;
295
 
 
296
 
        thd_pref.refresh();
297
 
        new_pref = thd_pref.get_preference();
298
 
        if (new_pref == PREF_DISABLED) {
299
 
                status = false;
300
 
                return;
301
 
        }
302
 
        status = true;
303
 
        if (preference != new_pref) {
304
 
                thd_log_warn("Preference changed \n");
305
 
        }
306
 
        preference = new_pref;
307
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
308
 
                cthd_zone *zone = zones[i];
309
 
                zone->update_zone_preference();
310
 
        }
311
 
 
312
 
        if (control_mode == EXCLUSIVE) {
313
 
                thd_log_info("Control is taken over from kernel\n");
314
 
                takeover_thermal_control();
315
 
        }
316
 
}
317
 
 
318
 
void cthd_engine::thd_engine_terminate() {
319
 
        send_message(TERMINATE, 0, NULL);
320
 
        sleep(1);
321
 
        process_terminate();
322
 
}
323
 
 
324
 
int cthd_engine::thd_engine_set_user_max_temp(const char *zone_type,
325
 
                const char *user_set_point) {
326
 
        std::string str(user_set_point);
327
 
        cthd_zone *zone;
328
 
 
329
 
        thd_log_debug("thd_engine_set_user_set_point %s\n", user_set_point);
330
 
 
331
 
        std::locale loc;
332
 
        if (std::isdigit(str[0], loc) == 0) {
333
 
                thd_log_warn("thd_engine_set_user_set_point Invalid set point\n");
334
 
                return THD_ERROR;
335
 
        }
336
 
 
337
 
        zone = get_zone(zone_type);
338
 
        if (!zone) {
339
 
                thd_log_warn("thd_engine_set_user_set_point Invalid zone\n");
340
 
                return THD_ERROR;
341
 
        }
342
 
        return zone->update_max_temperature(atoi(user_set_point));
343
 
}
344
 
 
345
 
void cthd_engine::thermal_zone_change(message_capsul_t *msg) {
346
 
 
347
 
        thermal_zone_notify_t *pmsg = (thermal_zone_notify_t*) msg->msg;
348
 
        for (unsigned i = 0; i < zones.size(); ++i) {
349
 
                cthd_zone *zone = zones[i];
350
 
                if (zone->zone_active_status())
351
 
                        zone->zone_temperature_notification(pmsg->type, pmsg->data);
352
 
                else {
353
 
                        thd_log_debug("zone is not active\n");
354
 
                }
355
 
        }
356
 
}
357
 
 
358
 
void cthd_engine::poll_enable_disable(bool status, message_capsul_t *msg) {
359
 
        unsigned int *sensor_id = (unsigned int*) msg->msg;
360
 
 
361
 
        if (status) {
362
 
                poll_sensor_mask |= (1 << (*sensor_id));
363
 
                poll_timeout_msec = def_poll_interval;
364
 
                thd_log_debug("thd_engine polling enabled via %u \n", *sensor_id);
365
 
        } else {
366
 
                poll_sensor_mask &= ~(1 << (*sensor_id));
367
 
                if (!poll_sensor_mask) {
368
 
                        poll_timeout_msec = -1;
369
 
                        thd_log_debug("thd_engine polling last disabled via %u \n",
370
 
                                        *sensor_id);
371
 
                }
372
 
        }
373
 
}
374
 
 
375
 
int cthd_engine::proc_message(message_capsul_t *msg) {
376
 
        int ret = 0;
377
 
 
378
 
        thd_log_debug("Receieved message %d\n", msg->msg_id);
379
 
        switch (msg->msg_id) {
380
 
        case WAKEUP:
381
 
                break;
382
 
        case TERMINATE:
383
 
                thd_log_warn("Terminating ...\n");
384
 
 
385
 
                ret = -1;
386
 
                terminate = true;
387
 
                break;
388
 
        case PREF_CHANGED:
389
 
                process_pref_change();
390
 
                break;
391
 
        case THERMAL_ZONE_NOTIFY:
392
 
                if (!status) {
393
 
                        thd_log_warn("Thermal Daemon is disabled \n");
394
 
                        break;
395
 
                }
396
 
                thermal_zone_change(msg);
397
 
                break;
398
 
        case CALIBRATE: {
399
 
                //TO DO
400
 
        }
401
 
                break;
402
 
        case RELOAD_ZONES:
403
 
                thd_engine_reload_zones();
404
 
                break;
405
 
        case POLL_ENABLE:
406
 
                if (!poll_interval_sec) {
407
 
                        poll_enable_disable(true, msg);
408
 
                }
409
 
                break;
410
 
        case POLL_DISABLE:
411
 
                if (!poll_interval_sec) {
412
 
                        poll_enable_disable(false, msg);
413
 
                }
414
 
                break;
415
 
        default:
416
 
                break;
417
 
        }
418
 
 
419
 
        return ret;
420
 
}
421
 
 
422
 
cthd_cdev *cthd_engine::thd_get_cdev_at_index(int index) {
423
 
        for (int i = 0; i < cdev_cnt; ++i) {
424
 
                if (cdevs[i]->thd_cdev_get_index() == index)
425
 
                        return cdevs[i];
426
 
        }
427
 
        return NULL;
428
 
}
429
 
 
430
 
void cthd_engine::takeover_thermal_control() {
431
 
        csys_fs sysfs("/sys/class/thermal/");
432
 
 
433
 
        DIR *dir;
434
 
        struct dirent *entry;
435
 
        const std::string base_path = "/sys/class/thermal/";
436
 
 
437
 
        thd_log_info("Taking over thermal control \n");
438
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
439
 
                while ((entry = readdir(dir)) != NULL) {
440
 
                        if (!strncmp(entry->d_name, "thermal_zone",
441
 
                                        strlen("thermal_zone"))) {
442
 
                                int i;
443
 
 
444
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
445
 
                                std::stringstream policy;
446
 
                                std::stringstream type;
447
 
                                std::string type_val;
448
 
                                std::string curr_policy;
449
 
 
450
 
                                type << "thermal_zone" << i << "/type";
451
 
                                if (sysfs.exists(type.str().c_str())) {
452
 
                                        sysfs.read(type.str(), type_val);
453
 
                                }
454
 
                                policy << "thermal_zone" << i << "/policy";
455
 
                                if (sysfs.exists(policy.str().c_str())) {
456
 
                                        sysfs.read(policy.str(), curr_policy);
457
 
                                        zone_preferences.push_back(curr_policy);
458
 
                                        sysfs.write(policy.str(), "user_space");
459
 
                                }
460
 
                        }
461
 
                }
462
 
                closedir(dir);
463
 
        }
464
 
}
465
 
 
466
 
void cthd_engine::giveup_thermal_control() {
467
 
        if (control_mode != EXCLUSIVE)
468
 
                return;
469
 
 
470
 
        if (zone_preferences.size() == 0)
471
 
                return;
472
 
 
473
 
        thd_log_info("Giving up thermal control \n");
474
 
 
475
 
        csys_fs sysfs("/sys/class/thermal/");
476
 
 
477
 
        DIR *dir;
478
 
        struct dirent *entry;
479
 
        const std::string base_path = "/sys/class/thermal/";
480
 
        int cnt = 0;
481
 
        if ((dir = opendir(base_path.c_str())) != NULL) {
482
 
                while ((entry = readdir(dir)) != NULL) {
483
 
                        if (!strncmp(entry->d_name, "thermal_zone",
484
 
                                        strlen("thermal_zone"))) {
485
 
                                int i;
486
 
 
487
 
                                i = atoi(entry->d_name + strlen("thermal_zone"));
488
 
                                std::stringstream policy;
489
 
                                std::stringstream type;
490
 
                                std::string type_val;
491
 
 
492
 
                                type << "thermal_zone" << i << "/type";
493
 
                                if (sysfs.exists(type.str().c_str())) {
494
 
                                        sysfs.read(type.str(), type_val);
495
 
                                }
496
 
                                policy << "thermal_zone" << i << "/policy";
497
 
                                if (sysfs.exists(policy.str().c_str())) {
498
 
                                        sysfs.write(policy.str(), zone_preferences[cnt++]);
499
 
                                }
500
 
                        }
501
 
                }
502
 
                closedir(dir);
503
 
        }
504
 
}
505
 
 
506
 
void cthd_engine::process_terminate() {
507
 
        thd_log_warn("terminating on user request ..\n");
508
 
        giveup_thermal_control();
509
 
        exit(EXIT_SUCCESS);
510
 
}
511
 
 
512
 
void cthd_engine::thd_engine_poll_enable(int sensor_id) {
513
 
        send_message(POLL_ENABLE, (int) sizeof(sensor_id),
514
 
                        (unsigned char*) &sensor_id);
515
 
}
516
 
 
517
 
void cthd_engine::thd_engine_poll_disable(int sensor_id) {
518
 
        send_message(POLL_DISABLE, (int) sizeof(sensor_id),
519
 
                        (unsigned char*) &sensor_id);
520
 
}
521
 
 
522
 
void cthd_engine::thd_engine_reload_zones() {
523
 
        thd_log_warn(" Reloading zones\n");
524
 
        for (unsigned int i = 0; i < zones.size(); ++i) {
525
 
                cthd_zone *zone = zones[i];
526
 
                delete zone;
527
 
        }
528
 
        zones.clear();
529
 
 
530
 
        int ret = read_thermal_zones();
531
 
        if (ret != THD_SUCCESS) {
532
 
                thd_log_error("No thermal sensors found\n");
533
 
                // This is a fatal error and daemon will exit
534
 
                return;
535
 
        }
536
 
}
537
 
 
538
 
// Add any tested platform ids in this table
539
 
static supported_ids_t id_table[] = { { 6, 0x2a }, // Sandybridge
540
 
                { 6, 0x2d }, // Sandybridge
541
 
                { 6, 0x3a }, // IvyBridge
542
 
                { 6, 0x3c }, { 6, 0x3e }, { 6, 0x3f }, { 6, 0x45 }, // Haswell ULT */
543
 
                { 6, 0x46 }, // Haswell ULT */
544
 
 
545
 
                { 0, 0 } // Last Invalid entry
546
 
};
547
 
 
548
 
int cthd_engine::check_cpu_id() {
549
 
#ifndef ANDROID
550
 
        // Copied from turbostat program
551
 
        unsigned int ebx, ecx, edx, max_level;
552
 
        unsigned int fms, family, model, stepping;
553
 
        genuine_intel = 0;
554
 
        int i = 0;
555
 
        bool valid = false;
556
 
 
557
 
        proc_list_matched = false;
558
 
        ebx = ecx = edx = 0;
559
 
 
560
 
        asm("cpuid": "=a"(max_level), "=b"(ebx), "=c"(ecx), "=d"(edx): "a"(0));
561
 
 
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
 
        asm("cpuid": "=a"(fms), "=c"(ecx), "=d"(edx): "a"(1): "ebx");
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
 
}