/ sys / OSThermalNotification.c
OSThermalNotification.c
  1  /*
  2   * Copyright (c) 2007 Apple Inc. All rights reserved.
  3   *
  4   * @APPLE_LICENSE_HEADER_START@
  5   * 
  6   * This file contains Original Code and/or Modifications of Original Code
  7   * as defined in and that are subject to the Apple Public Source License
  8   * Version 2.0 (the 'License'). You may not use this file except in
  9   * compliance with the License. Please obtain a copy of the License at
 10   * http://www.opensource.apple.com/apsl/ and read it before using this
 11   * file.
 12   * 
 13   * The Original Code and all software distributed under the License are
 14   * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
 15   * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
 16   * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
 17   * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
 18   * Please see the License for the specific language governing rights and
 19   * limitations under the License.
 20   * 
 21   * @APPLE_LICENSE_HEADER_END@
 22   */
 23  
 24  #include <libkern/OSThermalNotification.h>
 25  
 26  #include <TargetConditionals.h>
 27  
 28  #define OSThermalPressureLevelName		"com.apple.system.thermalpressurelevel"
 29  const char * const kOSThermalNotificationPressureLevelName = OSThermalPressureLevelName;
 30  
 31  #if TARGET_OS_IPHONE
 32  
 33  #include <dispatch/dispatch.h>
 34  #include <notify.h>
 35  
 36  #define OSThermalAlert      "com.apple.system.thermalalert"
 37  #define OSThermalDecision   "com.apple.system.thermaldecision"
 38  #define OSThermalStatusName "com.apple.system.thermalstatus"
 39  
 40  const char * const kOSThermalNotificationAlert    = OSThermalAlert;
 41  const char * const kOSThermalNotificationDecision = OSThermalDecision;
 42  const char * const kOSThermalNotificationName     = OSThermalStatusName;
 43  
 44  static const char * const kOSThermalMitigationNames[kOSThermalMitigationCount] = {
 45  	OSThermalStatusName,
 46  	"com.apple.system.thermalmitigation.70percenttorch",
 47  	"com.apple.system.thermalmitigation.70percentbacklight",
 48  	"com.apple.system.thermalmitigation.50percenttorch",
 49  	"com.apple.system.thermalmitigation.50percentbacklight",
 50  	"com.apple.system.thermalmitigation.disabletorch",
 51  	"com.apple.system.thermalmitigation.25percentbacklight",
 52  	"com.apple.system.thermalmitigation.disablemapshalo",
 53  	"com.apple.system.thermalmitigation.appterminate",
 54  	"com.apple.system.thermalmitigation.devicerestart",
 55  	"com.apple.system.thermalmitigation.thermaltableready"
 56  };
 57  
 58  static int tokens[kOSThermalMitigationCount];
 59  static dispatch_once_t predicates[kOSThermalMitigationCount];
 60  static bool thermalLevelsReady = false;
 61  
 62  OSThermalNotificationLevel _OSThermalNotificationLevelForBehavior(int behavior)
 63  {
 64  	uint64_t val = OSThermalNotificationLevelAny;
 65  	if (behavior >= 0 && behavior < kOSThermalMitigationCount) {
 66  		dispatch_once(&predicates[behavior], ^{
 67  			(void)notify_register_check(kOSThermalMitigationNames[behavior], &tokens[behavior]);
 68  		});
 69  		(void)notify_get_state(tokens[behavior], &val);
 70  	}
 71  	return (OSThermalNotificationLevel)val;
 72  }
 73  
 74  void _OSThermalNotificationSetLevelForBehavior(int level, int behavior)
 75  {
 76  	uint64_t val = (uint64_t)level;
 77  	if (behavior >= 0 && behavior < kOSThermalMitigationCount) {
 78  		dispatch_once(&predicates[behavior], ^{
 79  			(void)notify_register_check(kOSThermalMitigationNames[behavior], &tokens[behavior]);
 80  		});
 81  		(void)notify_set_state(tokens[behavior], val);
 82  
 83  		// Note:  
 84  		// - We are ready when we program in the appterminate value. 
 85  		// - Assumes that user programs kOSThermalMitigationNone level less than 
 86  		//   kOSThermalMitigationAppTerminate & kOSThermalMitigationDeviceRestart  
 87  		if (behavior == kOSThermalMitigationAppTerminate) {
 88  			dispatch_once(&predicates[kOSThermalMitigationThermalTableReady], ^{
 89  				(void)notify_register_check(kOSThermalMitigationNames[kOSThermalMitigationThermalTableReady], &tokens[kOSThermalMitigationThermalTableReady]);
 90  			});
 91  			(void)notify_set_state(tokens[kOSThermalMitigationThermalTableReady], kOSThermalMitigationCount);
 92  		}
 93  	}
 94  }
 95  
 96  
 97  OSThermalNotificationLevel OSThermalNotificationCurrentLevel(void)
 98  {
 99  	if (thermalLevelsReady) {
100  		return _OSThermalNotificationLevelForBehavior(kOSThermalMitigationNone);
101  	}
102  
103  	uint64_t tableReady = 0;
104  
105  	dispatch_once(&predicates[kOSThermalMitigationThermalTableReady], ^{
106  		(void)notify_register_check(kOSThermalMitigationNames[kOSThermalMitigationThermalTableReady], &tokens[kOSThermalMitigationThermalTableReady]);
107  	});
108  	(void)notify_get_state(tokens[kOSThermalMitigationThermalTableReady], &tableReady);
109  
110  	// If we are ready then optimize this so we don't call dispatch everytime.
111  	if (tableReady == kOSThermalMitigationCount) {
112  		thermalLevelsReady = true;
113  		return _OSThermalNotificationLevelForBehavior(kOSThermalMitigationNone); 
114  	}
115  	else {
116  		// Allow reset so we can dynamically change the table without thermal trap screen appearing. 
117  		thermalLevelsReady = false;
118  	}
119  
120  	// Not ready returns -1, which should not be equal or greater than any other thermal state. 
121  	return OSThermalNotificationLevelAny;
122  }
123  
124  #endif // TARGET_OS_IPHONE