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>
30 #include <dispatch/dispatch.h>
31 #include <dispatch/private.h>
33 const char *kOSMemoryNotificationName
= "com.apple.system.memorystatus";
35 struct _OSMemoryNotification
{
41 OSMemoryNotificationCreate(OSMemoryNotificationRef
*note
)
43 OSMemoryNotificationRef ref
= malloc(sizeof(struct _OSMemoryNotification
));
49 if (NOTIFY_STATUS_OK
!= notify_register_mach_port(kOSMemoryNotificationName
, &ref
->port
, 0, &ref
->token
))
58 OSMemoryNotificationDestroy(OSMemoryNotificationRef note
)
60 if (NOTIFY_STATUS_OK
!= notify_cancel(note
->token
))
63 if (KERN_SUCCESS
!= mach_port_deallocate(mach_task_self(), note
->port
))
72 OSMemoryNotificationWait(OSMemoryNotificationRef note
, OSMemoryNotificationLevel
*level
)
74 return OSMemoryNotificationTimedWait(note
, level
, NULL
);
77 static mach_msg_timeout_t
78 abs_to_timeout(const struct timeval
*abstime
)
80 struct timeval rel
, now
;
82 gettimeofday(&now
, NULL
);
84 rel
.tv_usec
= abstime
->tv_usec
- now
.tv_usec
;
85 rel
.tv_sec
= abstime
->tv_sec
- now
.tv_sec
;
86 if (rel
.tv_usec
< 0) {
87 rel
.tv_usec
+= 1000000;
90 if (((int)rel
.tv_sec
< 0) || ((rel
.tv_sec
== 0) && (rel
.tv_usec
== 0))) {
93 return rel
.tv_sec
* 1000 + rel
.tv_usec
/ 1000;
97 OSMemoryNotificationTimedWait(OSMemoryNotificationRef note
, OSMemoryNotificationLevel
*level
, const struct timeval
*abstime
)
99 dispatch_semaphore_t sema
= dispatch_semaphore_create(0);
100 dispatch_retain(sema
);
102 dispatch_source_t memoryNotificationSource
= dispatch_source_create(DISPATCH_SOURCE_TYPE_VM
, 0, DISPATCH_VM_PRESSURE
, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT
, 0));
103 dispatch_source_set_event_handler(memoryNotificationSource
, ^{
104 dispatch_semaphore_signal(sema
);
105 dispatch_release(sema
);
108 dispatch_resume(memoryNotificationSource
);
110 dispatch_time_t waitTime
= DISPATCH_TIME_FOREVER
;
112 mach_msg_timeout_t timeout
= abs_to_timeout(abstime
);
113 waitTime
= dispatch_time(DISPATCH_TIME_NOW
, timeout
* 1e6
);
116 long ret
= dispatch_semaphore_wait(sema
, waitTime
);
118 dispatch_release(sema
);
119 dispatch_release(memoryNotificationSource
);
126 *level
= OSMemoryNotificationLevelUrgent
;
132 OSMemoryNotificationLevel
OSMemoryNotificationCurrentLevel(void)
134 return OSMemoryNotificationLevelNormal
;