]> git.saurik.com Git - apple/libc.git/blob - darwin/libproc.c
9879aaafe9a77c87ddd887fa4b7fd656fa4ff701
[apple/libc.git] / darwin / libproc.c
1 /*
2 * Copyright (c) 2006, 2010 Apple Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
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
11 * file.
12 *
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.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 #include <sys/cdefs.h>
25 #include <unistd.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <strings.h>
29 #include <sys/errno.h>
30 #include <sys/msgbuf.h>
31 #define CONFIG_EMBEDDED 1
32 #include <sys/process_policy.h>
33
34 #include "libproc_internal.h"
35
36 int __proc_info(int callnum, int pid, int flavor, uint64_t arg, void * buffer, int buffersize);
37 __private_extern__ int proc_setthreadname(void * buffer, int buffersize);
38 int __process_policy(int scope, int action, int policy, int policy_subtype, proc_policy_attribute_t * attrp, pid_t target_pid, uint64_t target_threadid);
39
40
41
42 int
43 proc_listpids(uint32_t type, uint32_t typeinfo, void *buffer, int buffersize)
44 {
45 int retval;
46
47 if ((type >= PROC_ALL_PIDS) || (type <= PROC_PPID_ONLY)) {
48 if ((retval = __proc_info(1, type, typeinfo,(uint64_t)0, buffer, buffersize)) == -1)
49 return(0);
50 } else {
51 errno = EINVAL;
52 retval = 0;
53 }
54 return(retval);
55 }
56
57
58 int
59 proc_listallpids(void * buffer, int buffersize)
60 {
61 int numpids;
62 numpids = proc_listpids(PROC_ALL_PIDS, (uint32_t)0, buffer, buffersize);
63
64 if (numpids == -1)
65 return(-1);
66 else
67 return(numpids/sizeof(int));
68 }
69
70 int
71 proc_listpgrppids(pid_t pgrpid, void * buffer, int buffersize)
72 {
73 int numpids;
74 numpids = proc_listpids(PROC_PGRP_ONLY, (uint32_t)pgrpid, buffer, buffersize);
75 if (numpids == -1)
76 return(-1);
77 else
78 return(numpids/sizeof(int));
79 }
80
81 int
82 proc_listchildpids(pid_t ppid, void * buffer, int buffersize)
83 {
84 int numpids;
85 numpids = proc_listpids(PROC_PPID_ONLY, (uint32_t)ppid, buffer, buffersize);
86 if (numpids == -1)
87 return(-1);
88 else
89 return(numpids/sizeof(int));
90 }
91
92
93 int
94 proc_pidinfo(int pid, int flavor, uint64_t arg, void *buffer, int buffersize)
95 {
96 int retval;
97
98 if ((retval = __proc_info(2, pid, flavor, arg, buffer, buffersize)) == -1)
99 return(0);
100
101 return(retval);
102 }
103
104
105 int
106 proc_pidfdinfo(int pid, int fd, int flavor, void * buffer, int buffersize)
107 {
108 int retval;
109
110 if ((retval = __proc_info(3, pid, flavor, (uint64_t)fd, buffer, buffersize)) == -1)
111 return(0);
112
113 return (retval);
114 }
115
116
117 int
118 proc_pidfileportinfo(int pid, uint32_t fileport, int flavor, void *buffer, int buffersize)
119 {
120 int retval;
121
122 if ((retval = __proc_info(6, pid, flavor, (uint64_t)fileport, buffer, buffersize)) == -1)
123 return (0);
124 return (retval);
125 }
126
127
128 int
129 proc_name(int pid, void * buffer, uint32_t buffersize)
130 {
131 int retval = 0, len;
132 struct proc_bsdinfo pbsd;
133
134
135 if (buffersize < sizeof(pbsd.pbi_name)) {
136 errno = ENOMEM;
137 return(0);
138 }
139
140 retval = proc_pidinfo(pid, PROC_PIDTBSDINFO, (uint64_t)0, &pbsd, sizeof(struct proc_bsdinfo));
141 if (retval != 0) {
142 if (pbsd.pbi_name[0]) {
143 bcopy(&pbsd.pbi_name, buffer, sizeof(pbsd.pbi_name));
144 } else {
145 bcopy(&pbsd.pbi_comm, buffer, sizeof(pbsd.pbi_comm));
146 }
147 len = strlen(buffer);
148 return(len);
149 }
150 return(0);
151 }
152
153 int
154 proc_regionfilename(int pid, uint64_t address, void * buffer, uint32_t buffersize)
155 {
156 int retval = 0, len;
157 struct proc_regionwithpathinfo reginfo;
158
159 if (buffersize < MAXPATHLEN) {
160 errno = ENOMEM;
161 return(0);
162 }
163
164 retval = proc_pidinfo(pid, PROC_PIDREGIONPATHINFO, (uint64_t)address, &reginfo, sizeof(struct proc_regionwithpathinfo));
165 if (retval != -1) {
166 len = strlen(&reginfo.prp_vip.vip_path[0]);
167 if (len != 0) {
168 if (len > MAXPATHLEN)
169 len = MAXPATHLEN;
170 bcopy(&reginfo.prp_vip.vip_path[0], buffer, len);
171 return(len);
172 }
173 return(0);
174 }
175 return(0);
176
177 }
178
179 int
180 proc_kmsgbuf(void * buffer, uint32_t buffersize)
181 {
182 int retval;
183
184 if ((retval = __proc_info(4, 0, 0, (uint64_t)0, buffer, buffersize)) == -1)
185 return(0);
186 return (retval);
187 }
188
189 int
190 proc_pidpath(int pid, void * buffer, uint32_t buffersize)
191 {
192 int retval, len;
193
194 if (buffersize < PROC_PIDPATHINFO_SIZE) {
195 errno = ENOMEM;
196 return(0);
197 }
198 if (buffersize > PROC_PIDPATHINFO_MAXSIZE) {
199 errno = EOVERFLOW;
200 return(0);
201 }
202
203 retval = __proc_info(2, pid, PROC_PIDPATHINFO, (uint64_t)0, buffer, buffersize);
204 if (retval != -1) {
205 len = strlen(buffer);
206 return(len);
207 }
208 return (0);
209 }
210
211
212 int
213 proc_libversion(int *major, int * minor)
214 {
215
216 if (major != NULL)
217 *major = 1;
218 if (minor != NULL)
219 *minor = 1;
220 return(0);
221 }
222
223 int
224 proc_setpcontrol(const int control)
225 {
226 int retval ;
227
228 if (control < PROC_SETPC_NONE || control > PROC_SETPC_TERMINATE)
229 return(EINVAL);
230
231 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_PCONTROL, (uint64_t)control, NULL, 0)) == -1)
232 return(errno);
233
234 return(0);
235 }
236
237
238 __private_extern__ int
239 proc_setthreadname(void * buffer, int buffersize)
240 {
241 int retval;
242
243 retval = __proc_info(5, getpid(), PROC_SELFSET_THREADNAME, (uint64_t)0, buffer, buffersize);
244
245 if (retval == -1)
246 return(errno);
247 else
248 return(0);
249 }
250
251 int
252 proc_track_dirty(pid_t pid, uint32_t flags)
253 {
254 if (__proc_info(8, pid, PROC_DIRTYCONTROL_TRACK, flags, NULL, 0) == -1) {
255 return errno;
256 }
257
258 return 0;
259 }
260
261 int
262 proc_set_dirty(pid_t pid, bool dirty)
263 {
264 if (__proc_info(8, pid, PROC_DIRTYCONTROL_SET, dirty, NULL, 0) == -1) {
265 return errno;
266 }
267
268 return 0;
269 }
270
271 int
272 proc_get_dirty(pid_t pid, uint32_t *flags)
273 {
274 int retval;
275
276 if (!flags) {
277 return EINVAL;
278 }
279
280 retval = __proc_info(8, pid, PROC_DIRTYCONTROL_GET, 0, NULL, 0);
281 if (retval == -1) {
282 return errno;
283 }
284
285 *flags = retval;
286
287 return 0;
288 }
289
290 int
291 proc_terminate(pid_t pid, int *sig)
292 {
293 int retval;
294
295 if (!sig) {
296 return EINVAL;
297 }
298
299 retval = __proc_info(7, pid, 0, 0, NULL, 0);
300 if (retval == -1) {
301 return errno;
302 }
303
304 *sig = retval;
305
306 return 0;
307 }
308
309 #if TARGET_OS_EMBEDDED
310
311 int
312 proc_setcpu_percentage(pid_t pid, int action, int percentage)
313 {
314 proc_policy_cpuusage_attr_t attr;
315
316 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
317 attr.ppattr_cpu_attr = action;
318 attr.ppattr_cpu_percentage = percentage;
319 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
320 return(0);
321 else
322 return(errno);
323 }
324
325 int
326 proc_setcpu_deadline(pid_t pid, int action, uint64_t deadline)
327 {
328 proc_policy_cpuusage_attr_t attr;
329
330 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
331 attr.ppattr_cpu_attr = action;
332 attr.ppattr_cpu_attr_deadline = deadline;
333 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
334 return(0);
335 else
336 return(errno);
337
338 }
339
340
341 int
342 proc_setcpu_percentage_withdeadline(pid_t pid, int action, int percentage, uint64_t deadline)
343 {
344 proc_policy_cpuusage_attr_t attr;
345
346 bzero(&attr, sizeof(proc_policy_cpuusage_attr_t));
347 attr.ppattr_cpu_attr = action;
348 attr.ppattr_cpu_percentage = percentage;
349 attr.ppattr_cpu_attr_deadline = deadline;
350 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, &attr, pid, (uint64_t)0) != -1)
351 return(0);
352 else
353 return(errno);
354 }
355
356 int
357 proc_clear_cpulimits(pid_t pid)
358 {
359 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_USAGE, PROC_POLICY_RUSAGE_CPU, NULL, pid, (uint64_t)0) != -1)
360 return(0);
361 else
362 return(errno);
363
364
365 }
366
367 int
368 proc_appstate(int pid, int * appstatep)
369 {
370 int state;
371
372 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_GET, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1) {
373 if (appstatep != NULL)
374 *appstatep = state;
375 return(0);
376 } else
377 return(errno);
378
379 }
380
381
382 int
383 proc_setappstate(int pid, int appstate)
384 {
385 int state = appstate;
386
387 switch (state) {
388 case PROC_APPSTATE_NONE:
389 case PROC_APPSTATE_ACTIVE:
390 case PROC_APPSTATE_INACTIVE:
391 case PROC_APPSTATE_BACKGROUND:
392 case PROC_APPSTATE_NONUI:
393 break;
394 default:
395 return(EINVAL);
396 }
397 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_STATE, (int *)&state, pid, (uint64_t)0) != -1)
398 return(0);
399 else
400 return(errno);
401 }
402
403 int
404 proc_devstatusnotify(int devicestatus)
405 {
406 int state = devicestatus;
407
408 switch (devicestatus) {
409 case PROC_DEVSTATUS_SHORTTERM:
410 case PROC_DEVSTATUS_LONGTERM:
411 break;
412 default:
413 return(EINVAL);
414 }
415
416 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_DEVSTATUS, (int *)&state, getpid(), (uint64_t)0) != -1) {
417 return(0);
418 } else
419 return(errno);
420
421 }
422
423 int
424 proc_pidbind(int pid, uint64_t threadid, int bind)
425 {
426 int state = bind;
427 pid_t passpid = pid;
428
429 switch (bind) {
430 case PROC_PIDBIND_CLEAR:
431 passpid = getpid(); /* ignore pid on clear */
432 break;
433 case PROC_PIDBIND_SET:
434 break;
435 default:
436 return(EINVAL);
437 }
438 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_APPLY, PROC_POLICY_APP_LIFECYCLE, PROC_POLICY_APPLIFE_PIDBIND, (int *)&state, passpid, threadid) != -1)
439 return(0);
440 else
441 return(errno);
442 }
443
444 #else /* TARGET_OS_EMBEDDED */
445
446 int
447 proc_clear_vmpressure(pid_t pid)
448 {
449 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_RESTORE, PROC_POLICY_RESOURCE_STARVATION, PROC_POLICY_RS_VIRTUALMEM, NULL, pid, (uint64_t)0) != -1)
450 return(0);
451 else
452 return(errno);
453 }
454
455 /* set the current process as one who can resume suspended processes due to low virtual memory. Need to be root */
456 int
457 proc_set_owner_vmpressure(void)
458 {
459 int retval;
460
461 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_VMRSRCOWNER, (uint64_t)0, NULL, 0)) == -1)
462 return(errno);
463
464 return(0);
465 }
466
467 /* mark yourself to delay idle sleep on disk IO */
468 int
469 proc_set_delayidlesleep(void)
470 {
471 int retval;
472
473 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)1, NULL, 0)) == -1)
474 return(errno);
475
476 return(0);
477 }
478
479 /* Reset yourself to delay idle sleep on disk IO, if already set */
480 int
481 proc_clear_delayidlesleep(void)
482 {
483 int retval;
484
485 if ((retval = __proc_info(5, getpid(), PROC_SELFSET_DELAYIDLESLEEP, (uint64_t)0, NULL, 0)) == -1)
486 return(errno);
487
488 return(0);
489 }
490
491 /* disable the launch time backgroudn policy and restore the process to default group */
492 int
493 proc_disable_apptype(pid_t pid, int apptype)
494 {
495 switch (apptype) {
496 case PROC_POLICY_OSX_APPTYPE_TAL:
497 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
498 break;
499 default:
500 return(EINVAL);
501
502 }
503
504 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_DISABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
505 return(0);
506 else
507 return(errno);
508
509 }
510
511 /* re-enable the launch time background policy if it had been disabled. */
512 int
513 proc_enable_apptype(pid_t pid, int apptype)
514 {
515 switch (apptype) {
516 case PROC_POLICY_OSX_APPTYPE_TAL:
517 case PROC_POLICY_OSX_APPTYPE_DASHCLIENT:
518 break;
519 default:
520 return(EINVAL);
521
522 }
523
524 if (__process_policy(PROC_POLICY_SCOPE_PROCESS, PROC_POLICY_ACTION_ENABLE, PROC_POLICY_APPTYPE, apptype, NULL, pid, (uint64_t)0) != -1)
525 return(0);
526 else
527 return(errno);
528
529 }
530
531 #endif /* TARGET_OS_EMBEDDED */
532