1 /* File created by Chris Youngworth, Apple Computer 2/11/99 */
7 #include <mach/mach_error.h>
8 #include <mach/mach_traps.h>
13 #include <mach/bootstrap.h>
14 #include <mach/mach_syscalls.h>
15 #include <mach/mig_errors.h>
16 #include <sys/param.h>
20 #include <sys/sysctl.h>
33 #include <default_pager/default_pager_types.h>
34 #include <default_pager_alerts_server.h>
35 #include <backing_store_alerts.h>
36 #include <backing_store_triggers_server.h>
42 int local_hi_water
= 0;
49 /* global parameters for application notification option */
50 mach_port_t trigger_port
= NULL
;
51 mach_port_t notify_port
= NULL
;
56 void setprof __P((struct kvmvars *kvp, int state));
57 void dumpstate __P((struct kvmvars *kvp));
58 void reset __P((struct kvmvars *kvp));
65 mach_msg_size_t max_size
,
67 mach_msg_options_t options
)
69 mig_reply_error_t
*bufRequest
= 0, *bufReply
= 0;
70 register mach_msg_return_t mr
;
71 register kern_return_t kr
;
73 if ((kr
= vm_allocate(mach_task_self(),
74 (vm_address_t
*)&bufRequest
,
75 max_size
+ MAX_TRAILER_SIZE
,
76 TRUE
)) != KERN_SUCCESS
)
78 if ((kr
= vm_protect(mach_task_self(),
79 (vm_address_t
)bufRequest
,
80 max_size
+ MAX_TRAILER_SIZE
,
81 FALSE
, VM_PROT_ALL
)) != KERN_SUCCESS
)
83 mlock(bufRequest
, max_size
+ MAX_TRAILER_SIZE
);
84 if ((kr
= vm_allocate(mach_task_self(),
85 (vm_address_t
*)&bufReply
,
86 max_size
+ MAX_TRAILER_SIZE
,
87 TRUE
)) != KERN_SUCCESS
)
89 if ((kr
= vm_protect(mach_task_self(),
90 (vm_address_t
)bufReply
,
91 max_size
+ MAX_TRAILER_SIZE
,
92 FALSE
, VM_PROT_ALL
)) != KERN_SUCCESS
)
94 mlock(bufReply
, max_size
+ MAX_TRAILER_SIZE
);
96 mr
= mach_msg_overwrite_trap(&bufRequest
->Head
, MACH_RCV_MSG
|options
,
97 0, max_size
, rcv_name
,
98 MACH_MSG_TIMEOUT_NONE
, MACH_PORT_NULL
,
99 (mach_msg_header_t
*) 0, 0);
100 if (mr
== MACH_MSG_SUCCESS
) {
101 /* we have a request message */
103 if(!(default_pager_alerts_server(
104 &bufRequest
->Head
, &bufReply
->Head
)))
105 backing_store_triggers_server(
106 &bufRequest
->Head
, &bufReply
->Head
);
108 if (!(bufReply
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
) &&
109 bufReply
->RetCode
!= KERN_SUCCESS
) {
110 if (bufReply
->RetCode
== MIG_NO_REPLY
)
112 * This return code is a little tricky--
113 * it appears that the demux routine found an
114 * error of some sort, but since that error
115 * would not normally get returned either to
116 * the local user or the remote one, we pretend it's
120 bufRequest
->Head
.msgh_remote_port
= MACH_PORT_NULL
;
121 mach_msg_destroy(&bufRequest
->Head
);
125 if (bufReply
->Head
.msgh_remote_port
== MACH_PORT_NULL
) {
126 /* no reply port, so destroy the reply */
127 if (bufReply
->Head
.msgh_bits
& MACH_MSGH_BITS_COMPLEX
)
128 mach_msg_destroy(&bufReply
->Head
);
137 (void)vm_deallocate(mach_task_self(),
138 (vm_address_t
) bufRequest
,
139 max_size
+ MAX_TRAILER_SIZE
);
140 (void)vm_deallocate(mach_task_self(),
141 (vm_address_t
) bufReply
,
142 max_size
+ MAX_TRAILER_SIZE
);
149 backing_store_triggers(dynamic_pager
, hi_wat
, flags
, port
)
150 mach_port_t dynamic_pager
;
155 if((hi_wat
+ size
) > low_water
)
156 return KERN_FAILURE
; /* let ipc system clean up port */
158 notify_high
= hi_wat
;
159 if(hi_water
< notify_high
) {
160 local_hi_water
= notify_high
;
162 local_hi_water
= hi_water
;
164 if(notify_high
> hi_water
) {
165 default_pager_space_alert(trigger_port
, HI_WAT_ALERT
);
172 default_pager_space_alert(alert_port
, flags
)
173 mach_port_t alert_port
;
178 off_t filesize
= size
;
181 if(flags
& HI_WAT_ALERT
) {
182 /* printf("HI WAT ALERT!!\n"); */
184 sprintf(subfile
, "%s%d", fileroot
, file_count
);
185 file_ptr
= fopen(subfile
, "w+");
186 fchmod(fileno(file_ptr
), (mode_t
)01600);
187 error
= fcntl(fileno(file_ptr
), F_SETSIZE
, &filesize
);
192 local_hi_water
= local_hi_water
>>2;
193 if(notify_high
>= (local_hi_water
)) {
195 /* notify monitoring app of */
196 /* backing store shortage */
197 backing_store_alert(notify_port
,
199 mach_port_deallocate(mach_task_self(),
205 macx_triggers(local_hi_water
,
206 low_water
, HI_WAT_ALERT
, alert_port
);
208 if(hi_water
< notify_high
) {
209 if(local_hi_water
< notify_high
) {
210 bs_recovery
= notify_high
- local_hi_water
;
212 local_hi_water
= notify_high
;
214 if(local_hi_water
< hi_water
) {
215 bs_recovery
= hi_water
- local_hi_water
;
217 local_hi_water
= hi_water
;
219 macx_swapon(subfile
, flags
, size
, priority
);
220 if(bs_recovery
<= size
) {
221 if((bs_recovery
!= 0) && (notify_port
)) {
222 backing_store_alert(notify_port
,
224 mach_port_deallocate(mach_task_self(),
232 bs_recovery
= bs_recovery
-size
;
235 macx_triggers(local_hi_water
,
236 low_water
, HI_WAT_ALERT
, alert_port
);
238 if(flags
& LO_WAT_ALERT
) {
239 /* Turn into a logged message printf("LO WAT ALERT!!\n"); */
240 sprintf(subfile
, "%s%d", fileroot
, file_count
);
241 if(hi_water
< notify_high
) {
242 local_hi_water
= notify_high
;
244 local_hi_water
= hi_water
;
246 if((bs_recovery
!= 0) && (notify_port
)) {
247 backing_store_alert(notify_port
, LO_WAT_ALERT
);
248 mach_port_deallocate(mach_task_self(), notify_port
);
254 if(macx_swapoff(subfile
, flags
) == 0) {
258 macx_triggers(local_hi_water
, low_water
, LO_WAT_ALERT
, alert_port
);
264 wait_on_paging_trigger(trigger_port
)
265 mach_port_t trigger_port
;
267 kern_return_t result
;
268 result
= server_alert_loop(4096, trigger_port
, MACH_MSG_OPTION_NONE
);
269 if (result
!= KERN_SUCCESS
) {
270 fprintf(stderr
, "dynamic_pager: default pager alert failed\n");
277 paging_setup(flags
, size
, priority
, low
, high
)
284 off_t filesize
= size
;
289 sprintf(subfile
, "%s%d", fileroot
, file_count
);
290 file_ptr
= fopen(subfile
, "w+");
291 fchmod(fileno(file_ptr
), (mode_t
)01600);
292 fcntl(fileno(file_ptr
), F_SETSIZE
, &filesize
);
295 macx_swapon(subfile
, flags
, size
, priority
);
297 mach_msg_type_name_t poly
;
301 if (mach_port_allocate(mach_task_self(),
302 MACH_PORT_RIGHT_RECEIVE
,
303 &trigger_port
) != KERN_SUCCESS
) {
304 fprintf(stderr
,"allocation of trigger port failed\n");
307 /* create a send right on our local port */
308 mach_port_extract_right(mach_task_self(), trigger_port
,
309 MACH_MSG_TYPE_MAKE_SEND
, &trigger_port
, &poly
);
310 macx_triggers(high
, low
, HI_WAT_ALERT
, trigger_port
);
313 low
, LO_WAT_ALERT
, trigger_port
);
315 /* register control port for applications wishing to */
316 /* get backing store notifications or change dynamic */
317 /* pager settings. */
318 set_dp_control_port(mach_host_self(), trigger_port
);
319 wait_on_paging_trigger(trigger_port
);
324 main(int argc
, char **argv
)
328 char default_filename
[] = "/private/var/vm/swapfile";
332 strcpy(fileroot
, default_filename
);
334 while ((ch
= getopt(argc
, argv
, "F:L:H:S:P:O:")) != EOF
) {
338 strncpy(fileroot
, optarg
, 500);
342 low_water
= atoi(optarg
);
345 hi_water
= atoi(optarg
);
351 priority
= atoi(optarg
);
355 (void)fprintf(stderr
,
356 "usage: dynamic_pager [-F filename] [-L low water alert trigger] [-H high water alert trigger] [-S file size] [-P priority]\n");
360 local_hi_water
= hi_water
;
361 if((low_water
!= 0) && (low_water
<= (size
+ hi_water
))) {
362 (void)fprintf(stderr
, "usage: low water trigger must be larger than size + hi_water\n");
367 paging_setup(0, size
, priority
, low_water
, hi_water
);