I want to use Macbook air in clamshell mode without AC adapter connected. However, Mac OS will force system going to sleep when I close lid.
I found this part of XNU kernel from apple open source may relate to this behavior:
iokit/Kernel/IOPMrootDomain.cpp
...
6362 /*
6363 * Evaluate clamshell and SLEEP if appropiate
6364 */
6365 if (eval_clamshell && clamshellClosed)
6366 {
6367 if (shouldSleepOnClamshellClosed())
6368 privateSleepSystem (kIOPMSleepReasonClamshell);
6369 else
6370 evaluatePolicy( kStimulusDarkWakeEvaluate );
6371 }
...
3061 //******************************************************************************
3062 // sleepOnClamshellClosed
3063 //
3064 // contains the logic to determine if the system should sleep when the clamshell
3065 // is closed.
3066 //******************************************************************************
3067
3068 bool IOPMrootDomain::shouldSleepOnClamshellClosed( void )
3069 {
3070 if (!clamshellExists)
3071 return false;
3072
3073 DLOG("clamshell closed %d, disabled %d, desktopMode %d, ac %d sleepDisabled %d\n",
3074 clamshellClosed, clamshellDisabled, desktopMode, acAdaptorConnected, clamshellSleepDisabled);
3075
3076 return ( !clamshellDisabled && !(desktopMode && acAdaptorConnected) && !clamshellSleepDisabled );
3077 }
Of course, I can compile kernel but I doubt if it is latest Mavericks kernel. So I want to know if I can override kernel space function as we do it for user space function by inserting dynamic library.
Recompiling the xnu kernel is easier than you seem to think:
http://shantonu.blogspot.ca/2013/10/building-xnu-for-os-x-109-mavericks.html
Apple have been pretty slow to release source code for maintenance releases of OSX however, so you would have to delay updates 10.9.x until source becomes available.
Aside from that, you have a 2 obvious options:
In both cases, locate the
IOPMrootDomain::shouldSleepOnClamshellClosed
function in themach_kernel
disassembly. Figure out where it readsacAdaptorConnected
and replace those instructions with ones that make the code behave as ifacAdaptorConnected
were always true.You'll need to take care when patching at runtime. The method is private, so you can't directly get its address using the kext linker, so you'd need to get the address from elsewhere.
FWIW, I'm not 100% convinced this code is to blame for the behaviour you're seeing.
clamshellDisabled
should normally betrue
if an external display is attached. If you're specifically trying to use your Macbook with no screen attached, you can try generating a fakekIOPMDisableClamshell
power event, which should flip that flag.As an aside, it's somewhat disappointing that Apple has hardcoded such behaviour in the kernel - seems like the thing a simple userspace script should be deciding. :-(