6 #include <sys/kern_memorystatus.h>
10 /* Trigger forced jetsam */
11 #define MEMORYSTATUS_CMD_TEST_JETSAM 1000
14 dirty_chunk(void *chunk
, int chunk_size
)
19 // Dirty every word in the chunk.
20 for (p
= chunk
; p
< (char *)chunk
+ (chunk_size
* 1024 * 1024); p
+= 4) {
28 printf("usage: %s [-re] [-l MB] [-w MB] [-m MB] [-o num] [-k pid] <chunk_size in MB> <interval in milliseconds>\n", pname
);
29 printf("\t-r: after reaching max, re-dirty it all when the user prompts to do so.\n");
30 printf("\t-l: program the task's physical footprint limit to this value (in MB).\n");
31 printf("\t-w: program the task's jetsam high watermark to this value (in MB).\n");
32 printf("\t-m: dirty no more than this amount (in MB).\n");
33 printf("\t-e: exit after reaching -m max dirty.\n");
34 printf("\t-o: oscillate at the max this number of times and then continue on up.\n");
35 printf("\t-k: trigger explicit jetsam kill of this pid (and then exit).\n");
38 int main(int argc
, char *argv
[])
44 int oscillations
= -1;
50 int high_watermark
= -1;
53 boolean_t redirty
= FALSE
;
54 boolean_t exit_after_max
= FALSE
;
56 int oscillation_cnt
= 0;
60 printf("pid: %d\n", getpid());
62 while ((ch
= getopt(argc
, argv
, "rem:l:w:k:o:")) != -1) {
71 high_watermark
= atoi(optarg
);
74 oscillations
= atoi(optarg
);
80 exit_after_max
= TRUE
;
83 victim
= atoi(optarg
);
98 * int memorystatus_control(uint32_t command, int32_t pid, uint32_t flags, user_addr_t buffer, size_t buffersize);
100 if ((r
= memorystatus_control(MEMORYSTATUS_CMD_TEST_JETSAM
, victim
, 0, 0, 0)) != 0) {
101 perror("memorystatus_control");
104 printf("killed process %d\n", victim
);
113 chunk_size
= atoi(argv
[0]);
114 interval
= atoi(argv
[1]);
118 if ((kr
= task_set_phys_footprint_limit(mach_task_self(), limit
, &old_limit
)) != KERN_SUCCESS
) {
119 fprintf(stderr
, "task_set_phys_footprint_limit() failed: %s\n", mach_error_string(kr
));
122 printf("phys footprint limit set to %d MB (was: %d MB)\n", limit
, old_limit
);
125 if (high_watermark
!= -1) {
128 * int memorystatus_control(uint32_t command, int32_t pid, uint32_t flags, user_addr_t buffer, size_t buffersize);
130 if ((r
= memorystatus_control(MEMORYSTATUS_CMD_SET_JETSAM_HIGH_WATER_MARK
, getpid(), high_watermark
, 0, 0)) != 0) {
131 perror("memorystatus_control");
134 printf("high watermark set to %d MB\n", high_watermark
);
137 printf("consuming memory in chunks of %d MB every %d milliseconds.\n", chunk_size
, interval
);
139 printf("total consumed: ");
143 * Estimate max number of chunks possible, using 4GB as absolute max amount of memory
146 max_chunks
= 4000 / chunk_size
;
147 if ((chunks
= calloc(max_chunks
, sizeof (*chunks
))) == NULL
) {
154 if ((chunks
[nchunks
] = malloc(chunk_size
* 1024 * 1024)) == NULL
) {
159 tot_mb
+= chunk_size
;
161 dirty_chunk(chunks
[nchunks
], chunk_size
);
165 putchar(0x8); putchar(0x8); putchar(0x8); putchar(0x8);
166 printf("%4d", tot_mb
);
169 if ((max
!= -1) && (tot_mb
> max
)) {
170 printf("\nMax reached.\n");
172 if (exit_after_max
) {
176 if ((oscillations
== -1) || (oscillation_cnt
< oscillations
)) {
181 printf("Press any key to re-dirty ('q' to quit)...");
183 if ((ch
= getchar()) == 'q') {
187 for (i
= 0; i
< nchunks
; i
++) {
188 dirty_chunk(chunks
[i
], chunk_size
);
194 * We've broken the limit of what we should be consuming; free the
195 * most recent three chunks and go round again.
198 free(chunks
[nchunks
]);
199 chunks
[nchunks
] = NULL
;
200 tot_mb
-= chunk_size
;
204 free(chunks
[nchunks
]);
205 chunks
[nchunks
] = NULL
;
206 tot_mb
-= chunk_size
;
208 free(chunks
[nchunks
]);
209 chunks
[nchunks
] = NULL
;
210 tot_mb
-= chunk_size
;
217 usleep(interval
* 1000);