]> git.saurik.com Git - apple/xnu.git/blame - osfmk/kern/bsd_kern.c
xnu-792.18.15.tar.gz
[apple/xnu.git] / osfmk / kern / bsd_kern.c
CommitLineData
1c79356b 1/*
91447636 2 * Copyright (c) 2000-2004 Apple Computer, Inc. All rights reserved.
1c79356b 3 *
8f6c56a5 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
1c79356b 5 *
8f6c56a5
A
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. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
8ad349bb 24 * limitations under the License.
8f6c56a5
A
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
1c79356b
A
27 */
28#include <mach/mach_types.h>
91447636
A
29
30#include <kern/kern_types.h>
31#include <kern/processor.h>
1c79356b 32#include <kern/thread.h>
1c79356b
A
33#include <kern/task.h>
34#include <kern/spl.h>
35#include <kern/lock.h>
91447636 36#include <kern/ast.h>
1c79356b
A
37#include <ipc/ipc_port.h>
38#include <ipc/ipc_object.h>
91447636 39#include <vm/vm_map.h>
89b3af67 40#include <vm/vm_kern.h>
91447636
A
41#include <vm/pmap.h>
42#include <vm/vm_protos.h> /* last */
1c79356b
A
43
44#undef thread_should_halt
45#undef ipc_port_release
1c79356b 46
1c79356b
A
47/* BSD KERN COMPONENT INTERFACE */
48
9bccf70c 49task_t bsd_init_task = TASK_NULL;
1c79356b 50char init_task_failure_data[1024];
55e303ae 51extern unsigned int not_in_kdp; /* Skip acquiring locks if we're in kdp */
1c79356b 52
91447636 53thread_t get_firstthread(task_t);
1c79356b 54int get_task_userstop(task_t);
91447636 55int get_thread_userstop(thread_t);
55e303ae 56boolean_t thread_should_abort(thread_t);
1c79356b 57boolean_t current_thread_aborted(void);
91447636 58void task_act_iterate_wth_args(task_t, void(*)(thread_t, void *), void *);
1c79356b 59void ipc_port_release(ipc_port_t);
1c79356b 60boolean_t is_thread_active(thread_t);
91447636
A
61kern_return_t get_signalact(task_t , thread_t *, int);
62int get_vmsubmap_entries(vm_map_t, vm_object_offset_t, vm_object_offset_t);
1c79356b 63
1c79356b
A
64/*
65 *
66 */
67void *get_bsdtask_info(task_t t)
68{
69 return(t->bsd_info);
70}
71
72/*
73 *
74 */
75void set_bsdtask_info(task_t t,void * v)
76{
77 t->bsd_info=v;
78}
79
80/*
81 *
82 */
91447636 83void *get_bsdthread_info(thread_t th)
1c79356b
A
84{
85 return(th->uthread);
86}
87
88/*
89 * XXX: wait for BSD to fix signal code
90 * Until then, we cannot block here. We know the task
91 * can't go away, so we make sure it is still active after
92 * retrieving the first thread for extra safety.
93 */
91447636 94thread_t get_firstthread(task_t task)
1c79356b 95{
91447636
A
96 thread_t thread = (thread_t)queue_first(&task->threads);
97
98 if (queue_end(&task->threads, (queue_entry_t)thread))
99 thread = THREAD_NULL;
1c79356b 100
1c79356b 101 if (!task->active)
91447636
A
102 return (THREAD_NULL);
103
104 return (thread);
1c79356b
A
105}
106
91447636
A
107kern_return_t
108get_signalact(
109 task_t task,
110 thread_t *result_out,
111 int setast)
1c79356b 112{
91447636
A
113 kern_return_t result = KERN_SUCCESS;
114 thread_t inc, thread = THREAD_NULL;
1c79356b
A
115
116 task_lock(task);
91447636 117
1c79356b
A
118 if (!task->active) {
119 task_unlock(task);
91447636
A
120
121 return (KERN_FAILURE);
1c79356b
A
122 }
123
91447636
A
124 for (inc = (thread_t)queue_first(&task->threads);
125 !queue_end(&task->threads, (queue_entry_t)inc); ) {
126 thread_mtx_lock(inc);
127 if (inc->active &&
128 (inc->state & (TH_ABORT|TH_ABORT_SAFELY)) != TH_ABORT) {
129 thread = inc;
130 break;
1c79356b 131 }
91447636
A
132 thread_mtx_unlock(inc);
133
134 inc = (thread_t)queue_next(&inc->task_threads);
135 }
136
137 if (result_out)
138 *result_out = thread;
139
140 if (thread) {
141 if (setast)
142 act_set_astbsd(thread);
143
144 thread_mtx_unlock(thread);
145 }
146 else
147 result = KERN_FAILURE;
148
1c79356b
A
149 task_unlock(task);
150
91447636 151 return (result);
1c79356b
A
152}
153
0b4e3aa0 154
91447636
A
155kern_return_t
156check_actforsig(
157 task_t task,
158 thread_t thread,
159 int setast)
0b4e3aa0 160{
91447636
A
161 kern_return_t result = KERN_FAILURE;
162 thread_t inc;
0b4e3aa0
A
163
164 task_lock(task);
91447636 165
0b4e3aa0
A
166 if (!task->active) {
167 task_unlock(task);
91447636
A
168
169 return (KERN_FAILURE);
0b4e3aa0
A
170 }
171
91447636
A
172 for (inc = (thread_t)queue_first(&task->threads);
173 !queue_end(&task->threads, (queue_entry_t)inc); ) {
174 if (inc == thread) {
175 thread_mtx_lock(inc);
176
177 if (inc->active &&
178 (inc->state & (TH_ABORT|TH_ABORT_SAFELY)) != TH_ABORT) {
179 result = KERN_SUCCESS;
0b4e3aa0 180 break;
91447636 181 }
0b4e3aa0 182
91447636
A
183 thread_mtx_unlock(inc);
184 break;
185 }
186
187 inc = (thread_t)queue_next(&inc->task_threads);
188 }
189
190 if (result == KERN_SUCCESS) {
191 if (setast)
192 act_set_astbsd(thread);
193
194 thread_mtx_unlock(thread);
195 }
196
197 task_unlock(task);
198
199 return (result);
0b4e3aa0
A
200}
201
1c79356b 202/*
91447636
A
203 * This is only safe to call from a thread executing in
204 * in the task's context or if the task is locked Otherwise,
205 * the map could be switched for the task (and freed) before
206 * we to return it here.
1c79356b
A
207 */
208vm_map_t get_task_map(task_t t)
209{
210 return(t->map);
211}
212
91447636
A
213vm_map_t get_task_map_reference(task_t t)
214{
215 vm_map_t m;
216
217 if (t == NULL)
218 return VM_MAP_NULL;
219
220 task_lock(t);
221 if (!t->active) {
222 task_unlock(t);
223 return VM_MAP_NULL;
224 }
225 m = t->map;
226 vm_map_reference_swap(m);
227 task_unlock(t);
228 return m;
229}
230
1c79356b
A
231/*
232 *
233 */
234ipc_space_t get_task_ipcspace(task_t t)
235{
236 return(t->itk_space);
237}
238
239int get_task_numacts(task_t t)
240{
55e303ae
A
241 return(t->thread_count);
242}
243
244/* does this machine need 64bit register set for signal handler */
245int is_64signalregset(void)
246{
247 task_t t = current_task();
248 if(t->taskFeatures[0] & tf64BitData)
249 return(1);
250 else
251 return(0);
1c79356b
A
252}
253
254/*
55e303ae 255 * The old map reference is returned.
1c79356b
A
256 */
257vm_map_t
258swap_task_map(task_t task,vm_map_t map)
259{
91447636 260 thread_t thread = current_thread();
1c79356b
A
261 vm_map_t old_map;
262
91447636 263 if (task != thread->task)
55e303ae
A
264 panic("swap_task_map");
265
1c79356b
A
266 task_lock(task);
267 old_map = task->map;
91447636 268 thread->map = task->map = map;
1c79356b 269 task_unlock(task);
89b3af67
A
270
271 inval_copy_windows(thread);
272
1c79356b
A
273 return old_map;
274}
275
1c79356b
A
276/*
277 *
278 */
279pmap_t get_task_pmap(task_t t)
280{
281 return(t->map->pmap);
282}
283
284/*
285 *
286 */
287pmap_t get_map_pmap(vm_map_t map)
288{
289 return(map->pmap);
290}
291/*
292 *
293 */
91447636 294task_t get_threadtask(thread_t th)
1c79356b
A
295{
296 return(th->task);
297}
298
299
300/*
301 *
302 */
303boolean_t is_thread_idle(thread_t th)
304{
305 return((th->state & TH_IDLE) == TH_IDLE);
306}
307
308/*
309 *
310 */
55e303ae 311boolean_t is_thread_running(thread_t th)
1c79356b
A
312{
313 return((th->state & TH_RUN) == TH_RUN);
314}
315
316/*
317 *
318 */
55e303ae 319thread_t
1c79356b 320getshuttle_thread(
55e303ae 321 thread_t th)
1c79356b 322{
55e303ae 323 return(th);
1c79356b
A
324}
325
326/*
327 *
328 */
55e303ae 329thread_t
1c79356b 330getact_thread(
55e303ae 331 thread_t th)
1c79356b 332{
55e303ae 333 return(th);
1c79356b
A
334}
335
336/*
337 *
338 */
91447636 339vm_map_offset_t
1c79356b
A
340get_map_min(
341 vm_map_t map)
342{
343 return(vm_map_min(map));
344}
345
346/*
347 *
348 */
91447636 349vm_map_offset_t
1c79356b
A
350get_map_max(
351 vm_map_t map)
352{
353 return(vm_map_max(map));
354}
91447636 355vm_map_size_t
1c79356b
A
356get_vmmap_size(
357 vm_map_t map)
358{
359 return(map->size);
360}
361
362int
363get_vmsubmap_entries(
364 vm_map_t map,
365 vm_object_offset_t start,
366 vm_object_offset_t end)
367{
368 int total_entries = 0;
369 vm_map_entry_t entry;
370
55e303ae
A
371 if (not_in_kdp)
372 vm_map_lock(map);
1c79356b
A
373 entry = vm_map_first_entry(map);
374 while((entry != vm_map_to_entry(map)) && (entry->vme_start < start)) {
375 entry = entry->vme_next;
376 }
377
378 while((entry != vm_map_to_entry(map)) && (entry->vme_start < end)) {
379 if(entry->is_sub_map) {
380 total_entries +=
381 get_vmsubmap_entries(entry->object.sub_map,
382 entry->offset,
383 entry->offset +
384 (entry->vme_end - entry->vme_start));
385 } else {
386 total_entries += 1;
387 }
388 entry = entry->vme_next;
389 }
55e303ae
A
390 if (not_in_kdp)
391 vm_map_unlock(map);
1c79356b
A
392 return(total_entries);
393}
394
395int
396get_vmmap_entries(
397 vm_map_t map)
398{
399 int total_entries = 0;
400 vm_map_entry_t entry;
401
55e303ae
A
402 if (not_in_kdp)
403 vm_map_lock(map);
1c79356b
A
404 entry = vm_map_first_entry(map);
405
406 while(entry != vm_map_to_entry(map)) {
407 if(entry->is_sub_map) {
408 total_entries +=
409 get_vmsubmap_entries(entry->object.sub_map,
410 entry->offset,
411 entry->offset +
412 (entry->vme_end - entry->vme_start));
413 } else {
414 total_entries += 1;
415 }
416 entry = entry->vme_next;
417 }
55e303ae
A
418 if (not_in_kdp)
419 vm_map_unlock(map);
1c79356b
A
420 return(total_entries);
421}
422
423/*
424 *
425 */
426/*
427 *
428 */
429int
430get_task_userstop(
431 task_t task)
432{
433 return(task->user_stop_count);
434}
435
436/*
437 *
438 */
439int
440get_thread_userstop(
91447636 441 thread_t th)
1c79356b
A
442{
443 return(th->user_stop_count);
444}
445
1c79356b
A
446/*
447 *
448 */
449boolean_t
450thread_should_abort(
55e303ae 451 thread_t th)
1c79356b 452{
91447636 453 return ((th->state & (TH_ABORT|TH_ABORT_SAFELY)) == TH_ABORT);
1c79356b
A
454}
455
456/*
9bccf70c
A
457 * This routine is like thread_should_abort() above. It checks to
458 * see if the current thread is aborted. But unlike above, it also
459 * checks to see if thread is safely aborted. If so, it returns
460 * that fact, and clears the condition (safe aborts only should
461 * have a single effect, and a poll of the abort status
462 * qualifies.
1c79356b
A
463 */
464boolean_t
465current_thread_aborted (
466 void)
467{
468 thread_t th = current_thread();
9bccf70c
A
469 spl_t s;
470
91447636
A
471 if ((th->state & (TH_ABORT|TH_ABORT_SAFELY)) == TH_ABORT &&
472 (th->options & TH_OPT_INTMASK) != THREAD_UNINT)
9bccf70c
A
473 return (TRUE);
474 if (th->state & TH_ABORT_SAFELY) {
475 s = splsched();
476 thread_lock(th);
477 if (th->state & TH_ABORT_SAFELY)
478 th->state &= ~(TH_ABORT|TH_ABORT_SAFELY);
479 thread_unlock(th);
480 splx(s);
481 }
482 return FALSE;
1c79356b
A
483}
484
485/*
486 *
487 */
488void
489task_act_iterate_wth_args(
91447636
A
490 task_t task,
491 void (*func_callback)(thread_t, void *),
492 void *func_arg)
1c79356b 493{
91447636 494 thread_t inc;
1c79356b
A
495
496 task_lock(task);
91447636
A
497
498 for (inc = (thread_t)queue_first(&task->threads);
499 !queue_end(&task->threads, (queue_entry_t)inc); ) {
500 (void) (*func_callback)(inc, func_arg);
501 inc = (thread_t)queue_next(&inc->task_threads);
502 }
503
1c79356b
A
504 task_unlock(task);
505}
506
507void
508ipc_port_release(
509 ipc_port_t port)
510{
511 ipc_object_release(&(port)->ip_object);
512}
513
1c79356b
A
514boolean_t
515is_thread_active(
55e303ae 516 thread_t th)
1c79356b
A
517{
518 return(th->active);
519}
520
9bccf70c
A
521void
522astbsd_on(void)
523{
524 boolean_t reenable;
1c79356b 525
9bccf70c
A
526 reenable = ml_set_interrupts_enabled(FALSE);
527 ast_on_fast(AST_BSD);
528 (void)ml_set_interrupts_enabled(reenable);
529}
89b3af67
A
530
531
532#include <sys/bsdtask_info.h>
533
534void
535fill_taskprocinfo(task_t task, struct proc_taskinfo_internal * ptinfo)
536{
537 vm_map_t map;
538 task_absolutetime_info_data_t tinfo;
539 thread_t thread;
540 int numrunning = 0;
541
542 map = (task == kernel_task)? kernel_map: task->map;
543
544 ptinfo->pti_virtual_size = map->size;
545 ptinfo->pti_resident_size = (mach_vm_size_t)(pmap_resident_count(map->pmap)
546 * PAGE_SIZE);
547
548 task_lock(task);
549
550 ptinfo->pti_policy = ((task != kernel_task)?
551 POLICY_TIMESHARE: POLICY_RR);
552
553 tinfo.threads_user = tinfo.threads_system = 0;
554 tinfo.total_user = task->total_user_time;
555 tinfo.total_system = task->total_system_time;
556
557 queue_iterate(&task->threads, thread, thread_t, task_threads) {
558 uint64_t tval;
559
560 if ((thread->state & TH_RUN) == TH_RUN)
561 numrunning++;
562 tval = timer_grab(&thread->user_timer);
563 tinfo.threads_user += tval;
564 tinfo.total_user += tval;
565
566 tval = timer_grab(&thread->system_timer);
567 tinfo.threads_system += tval;
568 tinfo.total_system += tval;
569 }
570
571 ptinfo->pti_total_system = tinfo.total_system;
572 ptinfo->pti_total_user = tinfo.total_user;
573 ptinfo->pti_threads_system = tinfo.threads_system;
574 ptinfo->pti_threads_user = tinfo.threads_user;
575
576 ptinfo->pti_faults = task->faults;
577 ptinfo->pti_pageins = task->pageins;
578 ptinfo->pti_cow_faults = task->cow_faults;
579 ptinfo->pti_messages_sent = task->messages_sent;
580 ptinfo->pti_messages_received = task->messages_received;
581 ptinfo->pti_syscalls_mach = task->syscalls_mach;
582 ptinfo->pti_syscalls_unix = task->syscalls_unix;
583 ptinfo->pti_csw = task->csw;
584 ptinfo->pti_threadnum = task->thread_count;
585 ptinfo->pti_numrunning = numrunning;
586 ptinfo->pti_priority = task->priority;
587
588 task_unlock(task);
589}
590
591int
592fill_taskthreadinfo(task_t task, uint64_t thaddr, struct proc_threadinfo_internal * ptinfo)
593{
594 thread_t thact;
595 int err=0, count;
596 thread_basic_info_data_t basic_info;
597 kern_return_t kret;
598
599 task_lock(task);
600
601 for (thact = (thread_t)queue_first(&task->threads);
602 !queue_end(&task->threads, (queue_entry_t)thact); ) {
603#if defined(__ppc__)
604 if (thact->machine.cthread_self == thaddr)
605#elif defined (__i386__)
606 if (thact->machine.pcb->cthread_self == thaddr)
607#else
608#error architecture not supported
609#endif
610 {
611
612 count = THREAD_BASIC_INFO_COUNT;
613 if ((kret = thread_info_internal(thact, THREAD_BASIC_INFO, &basic_info, &count)) != KERN_SUCCESS) {
614 err = 1;
615 goto out;
616 }
617#if 0
618 ptinfo->pth_user_time = timer_grab(&basic_info.user_time);
619 ptinfo->pth_system_time = timer_grab(&basic_info.system_time);
620#else
621 ptinfo->pth_user_time = ((basic_info.user_time.seconds * NSEC_PER_SEC) + (basic_info.user_time.microseconds * NSEC_PER_USEC));
622 ptinfo->pth_system_time = ((basic_info.system_time.seconds * NSEC_PER_SEC) + (basic_info.system_time.microseconds * NSEC_PER_USEC));
623
624#endif
625 ptinfo->pth_cpu_usage = basic_info.cpu_usage;
626 ptinfo->pth_policy = basic_info.policy;
627 ptinfo->pth_run_state = basic_info.run_state;
628 ptinfo->pth_flags = basic_info.flags;
629 ptinfo->pth_sleep_time = basic_info.sleep_time;
630 ptinfo->pth_curpri = thact->sched_pri;
631 ptinfo->pth_priority = thact->priority;
632 ptinfo->pth_maxpriority = thact->max_priority;
633
634 err = 0;
635 goto out;
636 }
637 thact = (thread_t)queue_next(&thact->task_threads);
638 }
639 err = 1;
640
641out:
642 task_unlock(task);
643 return(err);
644}
645
646int
647fill_taskthreadlist(task_t task, void * buffer, int thcount)
648{
649 int numthr=0;
650 thread_t thact;
651 uint64_t * uptr;
652 uint64_t thaddr;
653
654 uptr = (uint64_t *)buffer;
655
656 task_lock(task);
657
658 for (thact = (thread_t)queue_first(&task->threads);
659 !queue_end(&task->threads, (queue_entry_t)thact); ) {
660#if defined(__ppc__)
661 thaddr = thact->machine.cthread_self;
662#elif defined (__i386__)
663 thaddr = thact->machine.pcb->cthread_self;
664#else
665#error architecture not supported
666#endif
667 *uptr++ = thaddr;
668 numthr++;
669 if (numthr >= thcount)
670 goto out;
671 thact = (thread_t)queue_next(&thact->task_threads);
672 }
673
674out:
675 task_unlock(task);
676 return(numthr * sizeof(uint64_t));
677
678}
679
680int
681get_numthreads(task_t task)
682{
683 return(task->thread_count);
684}
685