2 * Copyright (c) 2006 Apple Computer, Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
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
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.
21 * @APPLE_LICENSE_HEADER_END@
25 #include <libkern/OSMemoryNotification.h>
26 #include <mach/mach.h>
31 const char *kOSMemoryNotificationName
= "com.apple.system.memorystatus";
33 struct _OSMemoryNotification
{
39 OSMemoryNotificationCreate(OSMemoryNotificationRef
*note
)
41 OSMemoryNotificationRef ref
= malloc(sizeof(struct _OSMemoryNotification
));
47 if (NOTIFY_STATUS_OK
!= notify_register_mach_port(kOSMemoryNotificationName
, &ref
->port
, 0, &ref
->token
))
56 OSMemoryNotificationDestroy(OSMemoryNotificationRef note
)
58 if (NOTIFY_STATUS_OK
!= notify_cancel(note
->token
))
61 if (KERN_SUCCESS
!= mach_port_deallocate(mach_task_self(), note
->port
))
70 OSMemoryNotificationWait(OSMemoryNotificationRef note
, OSMemoryNotificationLevel
*level
)
73 return OSMemoryNotificationTimedWait(note
, level
, NULL
);
76 static mach_msg_timeout_t
77 abs_to_timeout(const struct timeval
*abstime
)
79 struct timeval rel
, now
;
81 gettimeofday(&now
, NULL
);
83 rel
.tv_usec
= abstime
->tv_usec
- now
.tv_usec
;
84 rel
.tv_sec
= abstime
->tv_sec
- now
.tv_sec
;
85 if (rel
.tv_usec
< 0) {
86 rel
.tv_usec
+= 1000000;
89 if (((int)rel
.tv_sec
< 0) || ((rel
.tv_sec
== 0) && (rel
.tv_usec
== 0))) {
92 return rel
.tv_sec
* 1000 + rel
.tv_usec
/ 1000;
96 OSMemoryNotificationTimedWait(OSMemoryNotificationRef note
, OSMemoryNotificationLevel
*level
, const struct timeval
*abstime
)
98 mach_msg_empty_rcv_t msg
= {{0}};
99 mach_msg_return_t ret
;
103 mach_msg_timeout_t timeout
= abs_to_timeout(abstime
);
108 ret
= mach_msg(&msg
.header
, MACH_RCV_MSG
| MACH_RCV_TIMEOUT
, 0, sizeof msg
, note
->port
, timeout
, MACH_PORT_NULL
);
110 if (MACH_RCV_TIMED_OUT
== ret
) {
114 ret
= mach_msg(&msg
.header
, MACH_RCV_MSG
, 0, sizeof msg
, note
->port
, MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
);
117 if (MACH_MSG_SUCCESS
!= ret
)
120 if (NOTIFY_STATUS_OK
!= notify_get_state(note
->token
, &val
))
123 *level
= (OSMemoryNotificationLevel
)val
;
128 OSMemoryNotificationLevel
OSMemoryNotificationCurrentLevel(void)
133 if (NOTIFY_STATUS_OK
!= notify_register_check(kOSMemoryNotificationName
, &token
))
134 return OSMemoryNotificationLevelAny
;
136 if (NOTIFY_STATUS_OK
!= notify_get_state(token
, &val
))
137 return OSMemoryNotificationLevelAny
;
139 if (NOTIFY_STATUS_OK
!= notify_cancel(token
))
140 return OSMemoryNotificationLevelAny
;
142 return (OSMemoryNotificationLevel
)val
;