]> git.saurik.com Git - apple/xnu.git/commitdiff
xnu-2050.24.15.tar.gz mac-os-x-1084 v2050.24.15
authorApple <opensource@apple.com>
Mon, 5 Aug 2013 16:46:03 +0000 (16:46 +0000)
committerApple <opensource@apple.com>
Mon, 5 Aug 2013 16:46:03 +0000 (16:46 +0000)
56 files changed:
bsd/hfs/hfs_vnops.c
bsd/kern/kern_event.c
bsd/kern/kern_exit.c
bsd/kern/kern_fork.c
bsd/kern/policy_check.c
bsd/kern/trace.codes
bsd/net/if_vlan.c
bsd/net/pf.c
bsd/netinet/tcp_ledbat.c
bsd/nfs/nfs_node.c
bsd/sys/cprotect.h
bsd/sys/vnode_internal.h
bsd/vfs/vfs_lookup.c
bsd/vfs/vfs_subr.c
bsd/vfs/vfs_syscalls.c
bsd/vfs/vfs_vnops.c
bsd/vfs/vfs_xattr.c
config/MasterVersion
iokit/IOKit/IOService.h
iokit/IOKit/pwr_mgt/IOPMlog.h
iokit/Kernel/IOPMrootDomain.cpp
iokit/Kernel/IOPlatformExpert.cpp
iokit/Kernel/IOServicePM.cpp
iokit/Kernel/IOServicePMPrivate.h
iokit/Kernel/IOTimerEventSource.cpp
iokit/Kernel/IOWorkLoop.cpp
osfmk/device/iokit_rpc.c
osfmk/i386/Diagnostics.c
osfmk/i386/Diagnostics.h
osfmk/i386/cpu_data.h
osfmk/i386/cpu_topology.h
osfmk/i386/fpu.c
osfmk/i386/machine_routines.c
osfmk/i386/machine_routines.h
osfmk/i386/pal_routines.h
osfmk/i386/pmCPU.c
osfmk/i386/proc_reg.h
osfmk/kern/host.c
osfmk/kern/host.h
osfmk/kern/machine.h
osfmk/kern/processor_data.h
osfmk/kern/sched_prim.c
osfmk/kern/task.c
osfmk/kern/task.h
osfmk/kern/thread.c
osfmk/kern/thread.h
osfmk/kern/thread_call.c
osfmk/kern/thread_call.h
osfmk/kern/timer_call.c
osfmk/kern/timer_call.h
osfmk/mach/host_info.h
osfmk/mach/machine/sdt.h
osfmk/mach/task_info.h
security/mac_framework.h
security/mac_policy.h
security/mac_vfs.c

index 1d0497a0f6ba1cce55743c67df4fe7f79ccfe69f..fad99d0a4fe1afaf63ff5df22ae7e38fdc964c40 100644 (file)
@@ -5630,11 +5630,29 @@ restart:
                 * do a lookup on /tmp/b, you'd acquire an entirely different record's resource
                 * fork.
                 * 
-                * As a result, we use the fileid, which should be invariant for the lifetime
-                * of the cnode (possibly barring calls to exchangedata).
+                * As a result, we use the fileid, which should be invariant for the lifetime
+                * of the cnode (possibly barring calls to exchangedata).
+                *
+                * Addendum: We can't do the above for HFS standard since we aren't guaranteed to
+                * have thread records for files.  They were only required for directories.  So
+                * we need to do the lookup with the catalog name. This is OK since hardlinks were
+                * never allowed on HFS standard.
                 */
 
-               error = cat_idlookup (hfsmp, cp->c_attr.ca_fileid, 0, 1, NULL, NULL, &rsrcfork);
+               if (hfsmp->hfs_flags & HFS_STANDARD) {
+                       /* 
+                        * HFS standard only:
+                        * 
+                        * Get the resource fork for this item via catalog lookup
+                        * since HFS standard was case-insensitive only. We don't want the 
+                        * descriptor; just the fork data here.
+                        */
+                       error = cat_lookup (hfsmp, descptr, 1, (struct cat_desc*)NULL, 
+                                       (struct cat_attr*)NULL, &rsrcfork, NULL);
+               }
+               else {
+                       error = cat_idlookup (hfsmp, cp->c_fileid, 0, 1, NULL, NULL, &rsrcfork);
+               }
 
                hfs_systemfile_unlock(hfsmp, lockflags);
                if (error) {
index ba269074ac91fb5abf3b93b41e22bfc83f711fb7..0e2705e5acf621d0276f1e77b1426ce25de876f0 100644 (file)
@@ -548,6 +548,24 @@ filt_proc(struct knote *kn, long hint)
                 */
                event = (u_int)hint & NOTE_PCTRLMASK;
 
+               /*
+                * termination lifecycle events can happen while a debugger
+                * has reparented a process, in which case notifications
+                * should be quashed except to the tracing parent. When
+                * the debugger reaps the child (either via wait4(2) or
+                * process exit), the child will be reparented to the original
+                * parent and these knotes re-fired.
+                */
+               if (event & NOTE_EXIT) {
+                       if ((kn->kn_ptr.p_proc->p_oppid != 0)
+                               && (kn->kn_kq->kq_p->p_pid != kn->kn_ptr.p_proc->p_ppid)) {
+                               /*
+                                * This knote is not for the current ptrace(2) parent, ignore.
+                                */
+                               return 0;
+                       }
+               }                                       
+
                /*
                 * if the user is interested in this event, record it.
                 */
index e585c0d279deb5ce7fbc1a9ff2ffd6199c6fad54..fa45facf32a0afd72addaf47f575044da45b591a 100644 (file)
@@ -153,7 +153,7 @@ void vfork_exit(proc_t p, int rv);
 void vproc_exit(proc_t p);
 __private_extern__ void munge_user64_rusage(struct rusage *a_rusage_p, struct user64_rusage *a_user_rusage_p);
 __private_extern__ void munge_user32_rusage(struct rusage *a_rusage_p, struct user32_rusage *a_user_rusage_p);
-static int reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int droplock);
+static int reap_child_locked(proc_t parent, proc_t child, int deadparent, int reparentedtoinit, int locked, int droplock);
 
 /*
  * Things which should have prototypes in headers, but don't
@@ -652,6 +652,7 @@ proc_exit(proc_t p)
        /* wait till parentrefs are dropped and grant no more */
        proc_childdrainstart(p);
        while ((q = p->p_children.lh_first) != NULL) {
+               int reparentedtoinit = (q->p_listflag & P_LIST_DEADPARENT) ? 1 : 0;
                q->p_listflag |= P_LIST_DEADPARENT;
                if (q->p_stat == SZOMB) {
                        if (p != q->p_pptr)
@@ -670,7 +671,7 @@ proc_exit(proc_t p)
                         * and the proc struct cannot be used for wakeups as well. 
                         * It is safe to use q here as this is system reap
                         */
-                       (void)reap_child_locked(p, q, 1, 1, 0);
+                       (void)reap_child_locked(p, q, 1, reparentedtoinit, 1, 0);
                } else {
                        proc_reparentlocked(q, initproc, 0, 1);
                        /*
@@ -794,10 +795,6 @@ proc_exit(proc_t p)
        set_bsdtask_info(task, NULL);
 
        knote_hint = NOTE_EXIT | (p->p_xstat & 0xffff);
-       if (p->p_oppid != 0) {
-               knote_hint |= NOTE_EXIT_REPARENTED;
-       }
-
        proc_knote(p, knote_hint);
 
        /* mark the thread as the one that is doing proc_exit
@@ -836,7 +833,7 @@ proc_exit(proc_t p)
                p->p_listflag |= P_LIST_DEADPARENT;
                proc_list_unlock();
        }
-       if ((p->p_listflag & P_LIST_DEADPARENT) == 0) {
+       if ((p->p_listflag & P_LIST_DEADPARENT) == 0 || p->p_oppid) {
                if (pp != initproc) {
                        proc_lock(pp);
                        pp->si_pid = p->p_pid;
@@ -899,7 +896,7 @@ proc_exit(proc_t p)
                 * and the proc struct cannot be used for wakeups as well. 
                 * It is safe to use p here as this is system reap
                 */
-               (void)reap_child_locked(pp, p, 1, 1, 1);
+               (void)reap_child_locked(pp, p, 1, 0, 1, 1);
                /* list lock dropped by reap_child_locked */
        }
        if (uth->uu_lowpri_window) {
@@ -934,7 +931,7 @@ proc_exit(proc_t p)
  *             1                       Process was reaped
  */
 static int
-reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int droplock)
+reap_child_locked(proc_t parent, proc_t child, int deadparent, int reparentedtoinit, int locked, int droplock)
 {
        proc_t trace_parent = PROC_NULL;        /* Traced parent process, if tracing */
 
@@ -949,41 +946,62 @@ reap_child_locked(proc_t parent, proc_t child, int deadparent, int locked, int d
         * ptraced can simply be reaped, refer to radar 5677288
         *      p_oppid                  -> ptraced
         *      trace_parent == initproc -> away from launchd
-        *      P_LIST_DEADPARENT        -> came to launchd by reparenting
+        *      reparentedtoinit         -> came to launchd by reparenting
         */
-       if (child->p_oppid && (trace_parent = proc_find(child->p_oppid)) 
-                       && !((trace_parent == initproc) && (child->p_lflag & P_LIST_DEADPARENT))) {
+       if (child->p_oppid) {
+               int knote_hint;
+               pid_t oppid;
+
                proc_lock(child);
+               oppid = child->p_oppid;
                child->p_oppid = 0;
+               knote_hint = NOTE_EXIT | (child->p_xstat & 0xffff);
                proc_unlock(child);
-               if (trace_parent != initproc) {
-                       /* 
-                        * proc internal fileds  and p_ucred usage safe 
-                        * here as child is dead and is not reaped or 
-                        * reparented yet 
-                        */
-                       proc_lock(trace_parent);
-                       trace_parent->si_pid = child->p_pid;
-                       trace_parent->si_status = child->p_xstat;
-                       trace_parent->si_code = CLD_CONTINUED;
-                       trace_parent->si_uid = kauth_cred_getruid(child->p_ucred);
-                       proc_unlock(trace_parent);
-               }
-               proc_reparentlocked(child, trace_parent, 1, 0);
-               psignal(trace_parent, SIGCHLD);
-               proc_list_lock();
-               wakeup((caddr_t)trace_parent);
-               child->p_listflag &= ~P_LIST_WAITING;
-               wakeup(&child->p_stat);
-               proc_list_unlock();
-               proc_rele(trace_parent);
-               if ((locked == 1) && (droplock == 0))
+
+               if ((trace_parent = proc_find(oppid))
+                       && !((trace_parent == initproc) && reparentedtoinit)) {
+                               
+                       if (trace_parent != initproc) {
+                               /* 
+                                * proc internal fileds  and p_ucred usage safe 
+                                * here as child is dead and is not reaped or 
+                                * reparented yet 
+                                */
+                               proc_lock(trace_parent);
+                               trace_parent->si_pid = child->p_pid;
+                               trace_parent->si_status = child->p_xstat;
+                               trace_parent->si_code = CLD_CONTINUED;
+                               trace_parent->si_uid = kauth_cred_getruid(child->p_ucred);
+                               proc_unlock(trace_parent);
+                       }
+                       proc_reparentlocked(child, trace_parent, 1, 0);
+                       
+                       /* resend knote to original parent (and others) after reparenting */
+                       proc_knote(child, knote_hint);
+                       
+                       psignal(trace_parent, SIGCHLD);
                        proc_list_lock();
-               return (0);
-       }
-       
-       if (trace_parent != PROC_NULL) {
-               proc_rele(trace_parent);
+                       wakeup((caddr_t)trace_parent);
+                       child->p_listflag &= ~P_LIST_WAITING;
+                       wakeup(&child->p_stat);
+                       proc_list_unlock();
+                       proc_rele(trace_parent);
+                       if ((locked == 1) && (droplock == 0))
+                               proc_list_lock();
+                       return (0);
+               }
+
+               /*
+                * If we can't reparent (e.g. the original parent exited while child was being debugged, or
+                * original parent is the same as the debugger currently exiting), we still need to satisfy
+                * the knote lifecycle for other observers on the system. While the debugger was attached,
+                * the NOTE_EXIT would not have been broadcast during initial child termination.
+                */
+               proc_knote(child, knote_hint);
+
+               if (trace_parent != PROC_NULL) {
+                       proc_rele(trace_parent);
+               }
        }
        
        proc_knote(child, NOTE_REAP);
@@ -1148,6 +1166,8 @@ loop1:
 
 
                if (p->p_stat == SZOMB) {
+                       int reparentedtoinit = (p->p_listflag & P_LIST_DEADPARENT) ? 1 : 0;
+
                        proc_list_unlock();
 #if CONFIG_MACF
                        if ((error = mac_proc_check_wait(q, p)) != 0)
@@ -1208,7 +1228,7 @@ loop1:
                        }
                        
                        /* Clean up */
-                       (void)reap_child_locked(q, p, 0, 0, 0);
+                       (void)reap_child_locked(q, p, 0, reparentedtoinit, 0, 0);
 
                        return (0);
                }
@@ -1410,7 +1430,7 @@ loop1:
 
                        /* Prevent other process for waiting for this event? */
                        if (!(uap->options & WNOWAIT)) {
-                               (void) reap_child_locked(q, p, 0, 0, 0);
+                               (void) reap_child_locked(q, p, 0, 0, 0, 0);
                                return (0);
                        }
                        goto out;
@@ -1789,7 +1809,7 @@ vproc_exit(proc_t p)
                         * and the proc struct cannot be used for wakeups as well. 
                         * It is safe to use q here as this is system reap
                         */
-                       (void)reap_child_locked(p, q, 1, 1, 0);
+                       (void)reap_child_locked(p, q, 1, 0, 1, 0);
                } else {
                        proc_reparentlocked(q, initproc, 0, 1);
                        /*
@@ -1967,7 +1987,7 @@ vproc_exit(proc_t p)
                 * and the proc struct cannot be used for wakeups as well. 
                 * It is safe to use p here as this is system reap
                 */
-               (void)reap_child_locked(pp, p, 0, 1, 1);
+               (void)reap_child_locked(pp, p, 0, 0, 1, 1);
                /* list lock dropped by reap_child_locked */
        }
        proc_rele(pp);
index 37d02887f64fd3d094b83ba9c8a8a3d04f54b83d..2f09ba8eed297bf3f50b492a6272e59df3d710a9 100644 (file)
@@ -109,6 +109,7 @@ extern void dtrace_lazy_dofs_duplicate(proc_t, proc_t);
 #include <kern/kalloc.h>
 #include <kern/mach_param.h>
 #include <kern/task.h>
+#include <kern/thread.h>
 #include <kern/thread_call.h>
 #include <kern/zalloc.h>
 
@@ -812,6 +813,12 @@ fork_create_child(task_t parent_task, proc_t child_proc, int inherit_memory, int
                task_deallocate(child_task);
                child_task = NULL;
        }
+
+       /*
+        * Tag thread as being the first thread in its task.
+        */
+       thread_set_tag(child_thread, THREAD_TAG_MAINTHREAD);
+
 bad:
        thread_yield_internal(1);
 
index 09c7928335bd2c7119f207e1f70623b7151ab1e6..270a1bbc2c7348418efc08a0feb965744b9177e7 100644 (file)
@@ -463,7 +463,7 @@ static struct mac_policy_ops policy_ops = {
        CHECK_SET_VOID_HOOK(thread_label_init)
        CHECK_SET_VOID_HOOK(thread_label_destroy)
        .mpo_reserved18 = common_void_hook,
-       .mpo_reserved19 = common_void_hook,
+       CHECK_SET_VOID_HOOK(vnode_notify_open)
        .mpo_reserved20 = common_void_hook,
        .mpo_reserved21 = common_void_hook,
        .mpo_reserved22 = common_void_hook,
index 5ccd2bbff573afacc485aebd59b638eaef0e7428..af5a27b19a90a6b12868f274960f158f11428bdc 100644 (file)
 0x5040010      CQ_psema
 0x5040014      CQ_plock
 0x5040018      CG_action
+0x5070004      PM_SetParent
+0x5070008      PM_AddChild
+0x507000c      PM_RemoveChild
+0x5070010      PM_CtrlDriver
+0x5070014      PM_CtrlDriverErr1
+0x5070018      PM_CtrlDriverErr2
+0x507001c      PM_CtrlDriverErr3
+0x5070020      PM_CtrlDriverErr4
+0x5070024      PM_InterestDriver
+0x5070028      PM_InterestDriverAckErr1
+0x507002c      PM_ChildAck
+0x5070030      PM_InterestDriverAck
+0x5070034      PM_InterestDriverAckErr2
+0x5070038      PM_InterestDriverAckErr3
+0x507003c      PM_CtrlDriverAckErr4
+0x5070040      PM_CtrlDriverAck
+0x5070044      PM_DomainWillChange
+0x5070048      PM_DomainDidChange
+0x507004c      PM_RequestDomainState
+0x5070050      PM_MakeUsable
+0x5070054      PM_ChangeStateTo
+0x5070058      PM_ChangeStateToPriv
+0x507005c      PM_SetAggressiveness
+0x5070060      PM_CriticalTemp
+0x5070064      PM_OverrideOn
+0x5070068      PM_OverrideOff
+0x5070074      PM_ChangeDone
+0x5070078      PM_CtrlDriverTardy
+0x507007c      PM_InterestDriverTardy
+0x5070080      PM_StartAckTimer
+0x5070084      PM_StartParentChange
+0x5070088      PM_AmendParentChange
+0x507008c      PM_StartDeviceChange
+0x5070090      PM_RequestDenied
+0x5070094      PM_CtrlDriverErr5
+0x5070098      PM_ProgramHardware
+0x507009c      PM_InformWillChange
+0x50700a0      PM_InformDidChange
+0x50700a4      PM_RemoveDriver
+0x50700a8      PM_SetIdleTimer
+0x50700ac      PM_SystemWake
+0x50700b4      PM_ClientAck
+0x50700b8      PM_ClientTardy
+0x50700bc      PM_ClientCancel
+0x50700c0      PM_ClientNotify
+0x50700c4      PM_AppNotify
+0x50700d4      PM_IdleCancel
+0x50700d8      PM_SystemTracePoint
 0x5080004      IOSERVICE_BUSY
 0x5080008      IOSERVICE_NONBUSY
 0x508000c      IOSERVICE_MODULESTALL
 0x5080048       IOSERVICE_KEXTD_ALIVE
 0x508004C       IOSERVICE_KEXTD_READY
 0x5080050       IOSERVICE_REGISTRY_QUIET
-0x5100004      PM_SetParent
-0x5100008      PM_AddChild
-0x510000c      PM_RemoveChild
-0x5100010      PM_CtrlDriver
-0x5100014      PM_CtrlDrvrE1
-0x5100018      PM_CtrlDrvrE2
-0x510001c      PM_CtrlDrvrE3
-0x5100020      PM_CtrlDrvrE4
-0x5100024      PM_IntDriver
-0x5100028      PM_AckE1
-0x510002c      PM_ChildAck
-0x5100030      PM_DriverAck
-0x5100034      PM_AckE2
-0x5100038      PM_AckE3
-0x510003c      PM_AckE4
-0x5100040      PM_DrvrAckSPwr
-0x5100044      PM_WillChange
-0x5100048      PM_DidChange
-0x510004c      PM_ReqstDomain
-0x5100050      PM_MakeUsable
-0x5100054      PM_ChangeTo
-0x5100058      PM_ChngeToPriv
-0x510005c      PM_SetAggrssvs
-0x5100060      PM_CritclTemp
-0x5100064      PM_OverrideOn
-0x5100068      PM_OverrideOff
-0x510006c      PM_EnqueueErr
-0x5100070      PM_CollapseQ
-0x5100074      PM_ChangeDone
-0x5100078      PM_CtrlDrvTrdy
-0x510007c      PM_IntDrvrTrdy
-0x5100080      PM_StartAckTmr
-0x5100084      PM_ParentChnge
-0x5100088      PM_AmndPrnChng
-0x510008c      PM_DeviceChnge
-0x5100090      PM_ReqDenied
-0x5100094      PM_CtrlDrvrE45
-0x5100098      PM_PrgrmHrdwre
-0x510009c      PM_InfDrvrPre
-0x51000a0      PM_InfDrvrPost
-0x51000a4      PM_RemoveDrivr
-0x51000a8      PM_IdlTimerPrd
-0x51000ac      PM_SystemWake
-0x51000b0      PM_AckE5
-0x51000b4      PM_ClientAck
-0x51000b8      PM_ClientTardy
-0x51000bc      PM_ClientCancl
-0x51000c0      PM_ClientNotfy
-0x51000c4      PM_AppNotify
 0x5230000      HID_Unexpected
 0x5230004      HID_KeyboardLEDThreadTrigger
 0x5230008      HID_KeyboardLEDThreadActive
index c1a5f0a20c4ef38fa23731662854ebc77f45e22b..273feea939a33c46657b979616d70cfa7f1ffa76 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003-2012 Apple Inc. All rights reserved.
+ * Copyright (c) 2003-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -1401,9 +1401,6 @@ vlan_config(struct ifnet * ifp, struct ifnet * p, int tag)
            vlan_lock();
            goto signal_done;
        }
-       /* mark the parent interface up */
-       ifnet_set_flags(p, IFF_UP, IFF_UP);
-       (void)ifnet_ioctl(p, 0, SIOCSIFFLAGS, (caddr_t)NULL);
     }
 
     /* configure parent to receive our multicast addresses */
@@ -1462,6 +1459,11 @@ vlan_config(struct ifnet * ifp, struct ifnet * p, int tag)
     if (ifv != NULL) {
        ifvlan_release(ifv);
     }
+    if (first_vlan) {
+       /* mark the parent interface up */
+       ifnet_set_flags(p, IFF_UP, IFF_UP);
+       (void)ifnet_ioctl(p, 0, SIOCSIFFLAGS, (caddr_t)NULL);
+    }
     return 0;
 
  signal_done:
index b13db985e4fa6cf1b83a39de53b60b991553298f..50fc5bd03935bed0ff4565ff82b807d79d8b22e1 100644 (file)
@@ -5105,7 +5105,6 @@ pf_test_dummynet(struct pf_rule **rm, int direction, struct pfi_kif *kif,
        int                      asd = 0;
        int                      match = 0;
        u_int8_t                 icmptype = 0, icmpcode = 0;
-       union pf_state_xport    nxport, sxport, dxport;
        struct ip_fw_args       dnflow;
        struct pf_rule          *prev_matching_rule = fwa ? fwa->fwa_pf_rule : NULL;
        int                     found_prev_rule = (prev_matching_rule) ? 0 : 1;
@@ -5115,39 +5114,31 @@ pf_test_dummynet(struct pf_rule **rm, int direction, struct pfi_kif *kif,
        if (!DUMMYNET_LOADED)
                return (PF_PASS);
        
-       if (TAILQ_EMPTY(pf_main_ruleset.rules[PF_RULESET_DUMMYNET].active.ptr)) {
+       if (TAILQ_EMPTY(pf_main_ruleset.rules[PF_RULESET_DUMMYNET].active.ptr))
                return (PF_PASS);
-       }
+       
        bzero(&dnflow, sizeof(dnflow));
 
        hdrlen = 0;
-       sxport.spi = 0;
-       dxport.spi = 0;
-       nxport.spi = 0;
 
        /* Fragments don't gave protocol headers */
        if (!(pd->flags & PFDESC_IP_FRAG))      
                switch (pd->proto) {
                case IPPROTO_TCP:
                        dnflow.fwa_id.flags = pd->hdr.tcp->th_flags;
-                       dnflow.fwa_id.dst_port = pd->hdr.tcp->th_dport;
-                       dnflow.fwa_id.src_port = pd->hdr.tcp->th_sport;
-                       sxport.port = pd->hdr.tcp->th_sport;
-                       dxport.port = pd->hdr.tcp->th_dport;
+                       dnflow.fwa_id.dst_port = ntohs(pd->hdr.tcp->th_dport);
+                       dnflow.fwa_id.src_port = ntohs(pd->hdr.tcp->th_sport);
                        hdrlen = sizeof (*th);
                        break;
                case IPPROTO_UDP:
-                       dnflow.fwa_id.dst_port = pd->hdr.udp->uh_dport;
-                       dnflow.fwa_id.src_port = pd->hdr.udp->uh_sport;
-                       sxport.port = pd->hdr.udp->uh_sport;
-                       dxport.port = pd->hdr.udp->uh_dport;
+                       dnflow.fwa_id.dst_port = ntohs(pd->hdr.udp->uh_dport);
+                       dnflow.fwa_id.src_port = ntohs(pd->hdr.udp->uh_sport);
                        hdrlen = sizeof (*pd->hdr.udp);
                        break;
 #if INET
                case IPPROTO_ICMP:
-                       if (pd->af != AF_INET)
+                       if (af != AF_INET)
                                break;
-                       sxport.port = dxport.port = pd->hdr.icmp->icmp_id;
                        hdrlen = ICMP_MINLEN;
                        icmptype = pd->hdr.icmp->icmp_type;
                        icmpcode = pd->hdr.icmp->icmp_code;
@@ -5155,24 +5146,18 @@ pf_test_dummynet(struct pf_rule **rm, int direction, struct pfi_kif *kif,
 #endif /* INET */
 #if INET6
                case IPPROTO_ICMPV6:
-                       if (pd->af != AF_INET6)
+                       if (af != AF_INET6)
                                break;
-                       sxport.port = dxport.port = pd->hdr.icmp6->icmp6_id;
                        hdrlen = sizeof (*pd->hdr.icmp6);
                        icmptype = pd->hdr.icmp6->icmp6_type;
                        icmpcode = pd->hdr.icmp6->icmp6_code;
                        break;
 #endif /* INET6 */
                case IPPROTO_GRE:
-                       if (pd->proto_variant == PF_GRE_PPTP_VARIANT) {
-                               sxport.call_id = dxport.call_id =
-                                   pd->hdr.grev1->call_id;
+                       if (pd->proto_variant == PF_GRE_PPTP_VARIANT)
                                hdrlen = sizeof (*pd->hdr.grev1);
-                       }
                        break;
                case IPPROTO_ESP:
-                       sxport.spi = 0;
-                       dxport.spi = pd->hdr.esp->spi;
                        hdrlen = sizeof (*pd->hdr.esp);
                        break;
                }
@@ -5298,10 +5283,21 @@ pf_test_dummynet(struct pf_rule **rm, int direction, struct pfi_kif *kif,
                
                dnflow.fwa_cookie = r->dnpipe;
                dnflow.fwa_pf_rule = r;
-               dnflow.fwa_id.addr_type = (af == AF_INET) ? 4 : 6;
                dnflow.fwa_id.proto = pd->proto;
                dnflow.fwa_flags = r->dntype;
-               
+               switch (af) {
+                       case AF_INET:
+                               dnflow.fwa_id.addr_type = 4;
+                               dnflow.fwa_id.src_ip = ntohl(saddr->v4.s_addr);
+                               dnflow.fwa_id.dst_ip = ntohl(daddr->v4.s_addr);
+                               break;
+                       case AF_INET6:
+                               dnflow.fwa_id.addr_type = 6;
+                               dnflow.fwa_id.src_ip6 = saddr->v6;
+                               dnflow.fwa_id.dst_ip6 = saddr->v6;
+                               break;
+                       }
+
                if (fwa != NULL) {
                        dnflow.fwa_oif = fwa->fwa_oif;
                        dnflow.fwa_oflags = fwa->fwa_oflags;
index 1d1d5e5e7ab28f8d870efed24058b7600a58cf68..d13dc50bf428edddd5469a03ee8b3fcff4122dcb 100644 (file)
@@ -108,15 +108,15 @@ SYSCTL_INT(_net_inet_tcp, OID_AUTO, bg_target_qdelay, CTLFLAG_RW | CTLFLAG_LOCKE
  * max_allowed_cwnd = allowed_increase + (tether * flight_size)
  * cwnd = min(cwnd, max_allowed_cwnd)
  *
- * 'Allowed_increase' parameter is set to 2. If the flight size is zero, then
- * we want the congestion window to be at least 2 packets to reduce the
- * delay induced by delayed ack. This helps when the receiver is acking every
- * other packet.
+ * 'Allowed_increase' parameter is set to 8. If the flight size is zero, then
+ * we want the congestion window to be at least 8 packets to reduce the
+ * delay induced by delayed ack. This helps when the receiver is acking 
+ * more than 2 packets at a time (stretching acks for better performance).
  * 
  * 'Tether' is also set to 2. We do not want this to limit the growth of cwnd
  * during slow-start.
  */ 
-int allowed_increase = 2;
+int allowed_increase = 8;
 SYSCTL_INT(_net_inet_tcp, OID_AUTO, bg_allowed_increase, CTLFLAG_RW | CTLFLAG_LOCKED, 
        &allowed_increase, 1, "Additive constant used to calculate max allowed congestion window");
 
index 7fc9ddaef8c8eed4132aa73247b0fae0666a2170..9563cc5de1b4aad486ae4617d4b3673521f09937 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2011 Apple Inc. All rights reserved.
+ * Copyright (c) 2000-2013 Apple Inc. All rights reserved.
  *
  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
  * 
@@ -72,6 +72,7 @@
 #include <sys/proc.h>
 #include <sys/kauth.h>
 #include <sys/mount_internal.h>
+#include <sys/vnode_internal.h>
 #include <sys/vnode.h>
 #include <sys/ubc.h>
 #include <sys/malloc.h>
@@ -132,6 +133,48 @@ nfs_hash(u_char *fhp, int fhsize)
        return (fhsum);
 }
 
+       
+int nfs_case_insensitive(mount_t);
+
+int
+nfs_case_insensitive(mount_t mp)
+{
+       struct nfsmount *nmp = VFSTONFS(mp);
+       int answer = 0;
+       int skip = 0;
+       
+       if (nmp == NULL) {
+               return (0);
+       }
+       
+       if (nmp->nm_vers == NFS_VER2) {
+               /* V2 has no way to know */
+               return (0);
+       }
+
+       lck_mtx_lock(&nmp->nm_lock);
+       if (nmp->nm_vers == NFS_VER3) {
+               if (!(nmp->nm_state & NFSSTA_GOTPATHCONF)) {
+                       /* We're holding the node lock so we just return 
+                        * with answer as case sensitive. Is very rare
+                        * for file systems not to be homogenous w.r.t. pathconf
+                        */
+                       skip = 1;
+               } 
+       } else if (!(nmp->nm_fsattr.nfsa_flags & NFS_FSFLAG_HOMOGENEOUS)) {
+               /* no pathconf info cached */
+               skip = 1;
+       }
+
+       if (!skip && NFS_BITMAP_ISSET(nmp->nm_fsattr.nfsa_bitmap, NFS_FATTR_CASE_INSENSITIVE))
+               answer = 1;
+
+       lck_mtx_unlock(&nmp->nm_lock);
+
+       return (answer);
+}
+
+       
 /*
  * Look up a vnode/nfsnode by file handle.
  * Callers must check for mount points!!
@@ -234,6 +277,84 @@ loop:
                } else {
                        if (dnp && cnp && (flags & NG_MAKEENTRY))
                                cache_enter(NFSTOV(dnp), vp, cnp);
+                       /*
+                        * Update the vnode if the name/and or the parent has
+                        * changed. We need to do this so that if getattrlist is
+                        * called asking for ATTR_CMN_NAME, that the "most"
+                        * correct name is being returned if we're not making an
+                        * entry. In addition for monitored vnodes we need to
+                        * kick the vnode out of the name cache. We do this so
+                        * that if there are hard links in the same directory
+                        * the link will not be found and a lookup will get us
+                        * here to return the name of the current link. In
+                        * addition by removing the name from the name cache the
+                        * old name will not be found after a rename done on
+                        * another client or the server.  The principle reason
+                        * to do this is because Finder is asking for
+                        * notifications on a directory.  The directory changes,
+                        * Finder gets notified, reads the directory (which we
+                        * have purged) and for each entry returned calls
+                        * getattrlist with the name returned from
+                        * readdir. gettattrlist has to call namei/lookup to
+                        * resolve the name, because its not in the cache we end
+                        * up here. We need to update the name so Finder will
+                        * get the name it called us with.
+                        *
+                        * We had an imperfect solution with respect to case
+                        * sensitivity.  There is a test that is run in
+                        * FileBuster that does renames from some name to
+                        * another name differing only in case. It then reads
+                        * the directory looking for the new name, after it
+                        * finds that new name, it ask gettattrlist to verify
+                        * that the name is the new name.  Usually that works,
+                        * but renames generate fsevents and fseventsd will do a
+                        * lookup on the name via lstat. Since that test renames
+                        * old name to new name back and forth there is a race
+                        * that an fsevent will be behind and will access the
+                        * file by the old name, on a case insensitive file
+                        * system that will work. Problem is if we do a case
+                        * sensitive compare, we're going to change the name,
+                        * which the test's getattrlist verification step is
+                        * going to fail. So we will check the case sensitivity
+                        * of the file system and do the appropriate compare. In
+                        * a rare instance for non homogeneous file systems
+                        * w.r.t. pathconf we will use case sensitive compares.
+                        * That could break if the file system is actually case
+                        * insensitive.
+                        *
+                        * Note that V2 does not know the case, so we just
+                        * assume case sensitivity. 
+                        *
+                        * This is clearly not perfect due to races, but this is
+                        * as good as its going to get. You can defeat the
+                        * handling of hard links simply by doing:
+                        *
+                        *      while :; do ls -l > /dev/null; done
+                        *
+                        * in a terminal window. Even a single ls -l can cause a
+                        * race.
+                        *
+                        * <rant>What we really need is for the caller, that
+                        * knows the name being used is valid since it got it
+                        * from a readdir to use that name and not ask for the
+                        * ATTR_CMN_NAME</rant>
+                        */
+                       if (dnp && cnp && (vp != NFSTOV(dnp))) {
+                               int update_flags = vnode_ismonitored((NFSTOV(dnp))) ? VNODE_UPDATE_CACHE : 0;
+                               int (*cmp)(const char *s1, const char *s2, size_t n);
+
+                               cmp = nfs_case_insensitive(mp) ? strncasecmp : strncmp;
+
+                               if (vp->v_name && cnp->cn_namelen && (*cmp)(cnp->cn_nameptr, vp->v_name, cnp->cn_namelen))
+                                       update_flags |= VNODE_UPDATE_NAME;
+                               if ((vp->v_name == NULL && cnp->cn_namelen != 0) || (vp->v_name != NULL && cnp->cn_namelen == 0))
+                                       update_flags |= VNODE_UPDATE_NAME;
+                               if (vnode_parent(vp) != NFSTOV(dnp))
+                                       update_flags |= VNODE_UPDATE_PARENT;
+                               if (update_flags)
+                                       vnode_update_identity(vp, NFSTOV(dnp), cnp->cn_nameptr, cnp->cn_namelen, 0, update_flags);
+                       }
+
                        *npp = np;
                }
                FSDBG_BOT(263, dnp, *npp, 0xcace0000, error);
index eb0a134fdff7fca6d8ec54373325449543adf2eb..0dda075ac9e7ec31c1a60f7c4990558ca6aed8ea 100644 (file)
@@ -65,9 +65,6 @@ extern "C" {
 #define CP_READ_ACCESS         0x1
 #define CP_WRITE_ACCESS 0x2
 
-/* 
- * Check for this version when deciding to enable features
- */
 #define CONTENT_PROTECTION_XATTR_NAME  "com.apple.system.cprotect"
 #define CP_NEW_MAJOR_VERS 4
 #define CP_PREV_MAJOR_VERS 2
index e846ac6799e6958482d15222a90947111f56ec98..af27d9513328d0024335834a7060c0fcd00031ce 100644 (file)
@@ -456,6 +456,7 @@ errno_t  vnode_makenamedstream(vnode_t, vnode_t *, const char *, int, vfs_contex
 errno_t  vnode_removenamedstream(vnode_t, vnode_t, const char *, int, vfs_context_t);
 errno_t  vnode_flushnamedstream(vnode_t vp, vnode_t svp, vfs_context_t context);
 errno_t  vnode_relenamedstream(vnode_t vp, vnode_t svp, vfs_context_t context);
+errno_t  vnode_verifynamedstream (vnode_t vp, vfs_context_t ctx);
 #endif
 
 
index 2c225cf19aec346b9d448bf60731e6dccee172b0..02e1576c1e256e409ba0b236faf0fd2e82848b50 100644 (file)
@@ -645,7 +645,19 @@ lookup_handle_found_vnode(struct nameidata *ndp, struct componentname *cnp, int
                }
                ndp->ni_flag &= ~(NAMEI_TRAILINGSLASH);
        } 
-       
+
+#if NAMEDSTREAMS
+       /* 
+        * Deny namei/lookup requests to resolve paths that point to shadow files.
+        * Access to shadow files must be conducted by explicit calls to VNOP_LOOKUP
+        * directly, and not use lookup/namei
+        */
+       if (vnode_isshadow (dp)) {
+               error = ENOENT;
+               goto out;
+       }
+#endif
+
 nextname:
        /*
         * Not a symbolic link.  If more pathname,
index 1c8bfc50e4f34e5a86b5c7028150f8b0be00c7b5..84fa6ff284e7e2437a5dcb265c1d5a9397c3ffa2 100644 (file)
@@ -5460,7 +5460,23 @@ vn_authorize_open_existing(vnode_t vp, struct componentname *cnp, int fmode, vfs
                        action |= KAUTH_VNODE_WRITE_DATA;
                }
        }
-       return (vnode_authorize(vp, NULL, action, ctx));
+       error = vnode_authorize(vp, NULL, action, ctx);
+
+#if NAMEDSTREAMS
+       if (error == EACCES) {
+               /*
+                * Shadow files may exist on-disk with a different UID/GID
+                * than that of the current context.  Verify that this file
+                * is really a shadow file.  If it was created successfully
+                * then it should be authorized.
+                */
+               if (vnode_isshadow(vp) && vnode_isnamedstream (vp)) {
+                       error = vnode_verifynamedstream(vp, ctx);
+               }
+       }
+#endif
+       
+       return error;
 }
 
 int
index 36c3c5e3fc722dfaeeef8d83baf79c503ca3d7d1..7e68e298263a111d3dddaae150a76812db5d1470 100644 (file)
@@ -8120,9 +8120,12 @@ vn_open_with_vp(vnode_t vp, int fmode, vfs_context_t ctx)
                return error;
        }
 
-       /* call out to allow 3rd party notification of open. 
+       /* Call out to allow 3rd party notification of open. 
         * Ignore result of kauth_authorize_fileop call.
         */
+#if CONFIG_MACF
+       mac_vnode_notify_open(ctx, vp, fmode);
+#endif
        kauth_authorize_fileop(vfs_context_ucred(ctx), KAUTH_FILEOP_OPEN, 
                               (uintptr_t)vp, 0);
 
index 47552a0d8e0a33eb23083bcee7560767b6e26a5b..671a51fc39e21f8f07280d378065ef391515d9e6 100644 (file)
@@ -177,9 +177,12 @@ vn_open_auth_finish(vnode_t vp, int fmode, vfs_context_t ctx)
                goto bad;
        }
 
-       /* call out to allow 3rd party notification of open. 
+       /* Call out to allow 3rd party notification of open. 
         * Ignore result of kauth_authorize_fileop call.
         */
+#if CONFIG_MACF
+       mac_vnode_notify_open(ctx, vp, fmode);
+#endif
        kauth_authorize_fileop(vfs_context_ucred(ctx), KAUTH_FILEOP_OPEN, 
                                                   (uintptr_t)vp, 0);
 
index 94715ae558c70306078e6cb4cd901eb8fa3bfe78..c4587268f33c66361a746039de82c9e54f6a9ddb 100644 (file)
@@ -627,6 +627,54 @@ out:
        return (error);
 }
 
+/* 
+ * Verify that the vnode 'vp' is a vnode that lives in the shadow
+ * directory.  We can't just query the parent pointer directly since
+ * the shadowfile is hooked up to the actual file it's a stream for.
+ */
+errno_t vnode_verifynamedstream(vnode_t vp, vfs_context_t context) {
+       int error;
+       struct vnode *shadow_dvp = NULL;
+       struct vnode *shadowfile = NULL;
+       struct componentname cn;
+       char tmpname[80];
+
+
+       /* Get the shadow directory vnode */
+       error = get_shadow_dir(&shadow_dvp, context);
+       if (error) {
+               return error;
+       }
+
+       /* Re-generate the shadow name in the buffer */
+       MAKE_SHADOW_NAME (vp, tmpname);
+
+       /* Look up item in shadow dir */
+       bzero(&cn, sizeof(cn));
+       cn.cn_nameiop = LOOKUP;
+       cn.cn_flags = ISLASTCN | CN_ALLOWRSRCFORK;
+       cn.cn_context = context;
+       cn.cn_pnbuf = tmpname;
+       cn.cn_pnlen = sizeof(tmpname);
+       cn.cn_nameptr = cn.cn_pnbuf;
+       cn.cn_namelen = strlen(tmpname);
+
+       if (VNOP_LOOKUP (shadow_dvp, &shadowfile, &cn, context) == 0) {
+               /* is the pointer the same? */
+               if (shadowfile == vp) {
+                       error = 0;      
+               }
+               else {
+                       error = EPERM;
+               }
+               /* drop the iocount acquired */
+               vnode_put (shadowfile);
+       }       
+
+       /* Drop iocount on shadow dir */
+       vnode_put (shadow_dvp);
+       return error;
+}      
 
 static int
 getshadowfile(vnode_t vp, vnode_t *svpp, int makestream, size_t *rsrcsize,
index 84a48a01744768ffdf2716fc1d3f72ead054be63..80a99e0df34efe60ffb4b01e60a1c1c4eac022c4 100644 (file)
@@ -1,4 +1,4 @@
-12.3.0
+12.4.0
 
 # The first line of this file contains the master version number for the kernel.
 # All other instances of the kernel version in xnu are derived from this file.
index 9c68d22a526b46c8acda91ea12e93eb0249b4ea8..f3d1bed4a817ca5885b3739f0bdb95d5fa04e712 100644 (file)
@@ -1744,6 +1744,7 @@ public:
 protected:
     bool tellClientsWithResponse( int messageType );
     void tellClients( int messageType );
+    void PMDebug( uint32_t event, uintptr_t param1, uintptr_t param2 );
 
 private:
 #ifndef __LP64__
index b9d50eda5ba5519e69055b7c9b6a759b627742b9..2f82c1b4ee3a60d5c7e8c5941d70db433cec19dd 100644 (file)
  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
  */
 enum PMLogEnum {
-    kPMLogSetParent = 1,            //  1      0x05100004
-    kPMLogAddChild,                 //  2      0x05100008
-    kPMLogRemoveChild,              //  3      0x0510000c
-    kPMLogControllingDriver,        //  4      0x05100010
-    kPMLogControllingDriverErr1,    //  5      0x05100014 - bad power state array version
-    kPMLogControllingDriverErr2,    //  6      0x05100018 - power states already registered
-    kPMLogControllingDriverErr3,    //  7      0x0510001c
-    kPMLogControllingDriverErr4,    //  8      0x05100020 - power driver is invalid
-    kPMLogInterestedDriver,         //  9      0x05100024
-    kPMLogAcknowledgeErr1,          // 10      0x05100028 - unknown entity called acknowledgePowerChange
-    kPMLogChildAcknowledge,         // 11      0x0510002c
-    kPMLogDriverAcknowledge,        // 12      0x05100030 - interested driver acknowledges
-    kPMLogAcknowledgeErr2,          // 13      0x05100034 - object has already acked
-    kPMLogAcknowledgeErr3,          // 14      0x05100038 - not expecting any acks
-    kPMLogAcknowledgeErr4,          // 15      0x0510003c - not expecting acknowledgeSetPowerState
-    kPMLogDriverAcknowledgeSet,     // 16      0x05100040 - controlling driver acknowledges
-    kPMLogWillChange,               // 17      0x05100044
-    kPMLogDidChange,                // 18      0x05100048
-    kPMLogRequestDomain,            // 19      0x0510004c
-    kPMLogMakeUsable,               // 20      0x05100050
-    kPMLogChangeStateTo,            // 21      0x05100054
-    kPMLogChangeStateToPriv,        // 22      0x05100058
-    kPMLogSetAggressiveness,        // 23      0x0510005c
-    kPMLogCriticalTemp,             // 24      0x05100060
-    kPMLogOverrideOn,               // 25      0x05100064
-    kPMLogOverrideOff,              // 26      0x05100068
-    kPMLogEnqueueErr,               // 27      0x0510006c - NOT USED
-    kPMLogCollapseQueue,            // 28      0x05100070 - NOT USED
-    kPMLogChangeDone,               // 29      0x05100074
-    kPMLogCtrlDriverTardy,          // 30      0x05100078 - controlling driver didn't acknowledge
-    kPMLogIntDriverTardy,           // 31      0x0510007c - interested driver didn't acknowledge
-    kPMLogStartAckTimer,            // 32      0x05100080
-    kPMLogStartParentChange,        // 33      0x05100084
-    kPMLogAmendParentChange,        // 34      0x05100088
-    kPMLogStartDeviceChange,        // 35      0x0510008c
-    kPMLogRequestDenied,            // 36      0x05100090 - parent denied domain state change request
-    kPMLogControllingDriverErr5,    // 37      0x05100094 - too few power states
-    kPMLogProgramHardware,          // 38      0x05100098
-    kPMLogInformDriverPreChange,    // 39      0x0510009c
-    kPMLogInformDriverPostChange,   // 40      0x051000a0
-    kPMLogRemoveDriver,             // 41      0x051000a4 - NOT USED
-    kPMLogSetIdleTimerPeriod,       // 42      0x051000a8
-    kPMLogSystemWake,               // 43      0x051000ac
-    kPMLogAcknowledgeErr5,          // 44      0x051000b0
-    kPMLogClientAcknowledge,        // 45      0x051000b4
-    kPMLogClientTardy,              // 46      0x051000b8 - application didn't acknowledge
-    kPMLogClientCancel,             // 47      0x051000bc - NOT USED
-    kPMLogClientNotify,             // 48      0x051000c0 - client sent a notification
-    kPMLogAppNotify,                // 49      0x051000c4 - application sent a notification
-    kPMLogSetClockGating,           // 50      0x051000c8 - NOT USED
-    kPMLogSetPowerGating,           // 51      0x051000cc - NOT USED
-    kPMLogSetPinGroup,              // 52      0x051000d0 - NOT USED
-    kPMLogIdleCancel,               // 53      0x051000d4 - device unidle during change
+    kPMLogSetParent = 1,            //  1      0x05070004
+    kPMLogAddChild,                 //  2      0x05070008
+    kPMLogRemoveChild,              //  3      0x0507000c
+    kPMLogControllingDriver,        //  4      0x05070010
+    kPMLogControllingDriverErr1,    //  5      0x05070014 - bad power state array version
+    kPMLogControllingDriverErr2,    //  6      0x05070018 - power states already registered
+    kPMLogControllingDriverErr3,    //  7      0x0507001c
+    kPMLogControllingDriverErr4,    //  8      0x05070020 - power driver is invalid
+    kPMLogInterestedDriver,         //  9      0x05070024
+    kPMLogAcknowledgeErr1,          // 10      0x05070028 - unknown entity called acknowledgePowerChange
+    kPMLogChildAcknowledge,         // 11      0x0507002c
+    kPMLogDriverAcknowledge,        // 12      0x05070030 - interested driver acknowledges
+    kPMLogAcknowledgeErr2,          // 13      0x05070034 - object has already acked
+    kPMLogAcknowledgeErr3,          // 14      0x05070038 - not expecting any acks
+    kPMLogAcknowledgeErr4,          // 15      0x0507003c - not expecting acknowledgeSetPowerState
+    kPMLogDriverAcknowledgeSet,     // 16      0x05070040 - controlling driver acknowledges
+    kPMLogWillChange,               // 17      0x05070044
+    kPMLogDidChange,                // 18      0x05070048
+    kPMLogRequestDomain,            // 19      0x0507004c
+    kPMLogMakeUsable,               // 20      0x05070050
+    kPMLogChangeStateTo,            // 21      0x05070054
+    kPMLogChangeStateToPriv,        // 22      0x05070058
+    kPMLogSetAggressiveness,        // 23      0x0507005c
+    kPMLogCriticalTemp,             // 24      0x05070060
+    kPMLogOverrideOn,               // 25      0x05070064
+    kPMLogOverrideOff,              // 26      0x05070068
+    kPMLogEnqueueErr,               // 27      0x0507006c - NOT USED
+    kPMLogCollapseQueue,            // 28      0x05070070 - NOT USED
+    kPMLogChangeDone,               // 29      0x05070074
+    kPMLogCtrlDriverTardy,          // 30      0x05070078 - controlling driver didn't acknowledge
+    kPMLogIntDriverTardy,           // 31      0x0507007c - interested driver didn't acknowledge
+    kPMLogStartAckTimer,            // 32      0x05070080
+    kPMLogStartParentChange,        // 33      0x05070084
+    kPMLogAmendParentChange,        // 34      0x05070088
+    kPMLogStartDeviceChange,        // 35      0x0507008c
+    kPMLogRequestDenied,            // 36      0x05070090 - parent denied domain state change request
+    kPMLogControllingDriverErr5,    // 37      0x05070094 - too few power states
+    kPMLogProgramHardware,          // 38      0x05070098
+    kPMLogInformDriverPreChange,    // 39      0x0507009c
+    kPMLogInformDriverPostChange,   // 40      0x050700a0
+    kPMLogRemoveDriver,             // 41      0x050700a4 - NOT USED
+    kPMLogSetIdleTimerPeriod,       // 42      0x050700a8
+    kPMLogSystemWake,               // 43      0x050700ac
+    kPMLogAcknowledgeErr5,          // 44      0x050700b0
+    kPMLogClientAcknowledge,        // 45      0x050700b4
+    kPMLogClientTardy,              // 46      0x050700b8 - application didn't acknowledge
+    kPMLogClientCancel,             // 47      0x050700bc - NOT USED
+    kPMLogClientNotify,             // 48      0x050700c0 - client sent a notification
+    kPMLogAppNotify,                // 49      0x050700c4 - application sent a notification
+    kPMLogSetClockGating,           // 50      0x050700c8 - NOT USED
+    kPMLogSetPowerGating,           // 51      0x050700cc - NOT USED
+    kPMLogSetPinGroup,              // 52      0x050700d0 - NOT USED
+    kPMLogIdleCancel,               // 53      0x050700d4 - device unidle during change
+    kPMLogSleepWakeTracePoint,      // 54   0x050700d8 - kIOPMTracePoint markers
     kIOPMlogLastEvent
 };
index dd6d10f2a0ca565d9000d7e62703459b5615dd5d..b3d6e1f44ca63de9a97a031d3221c3932f101cc3 100644 (file)
@@ -2229,7 +2229,7 @@ void IOPMrootDomain::powerChangeDone( unsigned long previousPowerState )
 #endif
 
             // log system wake
-            getPlatform()->PMLog(kIOPMrootDomainClass, kPMLogSystemWake, 0, 0);
+            PMDebug(kPMLogSystemWake, 0, 0);
             lowBatteryCondition = false;
             lastSleepReason = 0;
             
@@ -6654,6 +6654,7 @@ void IOPMrootDomain::tracePoint( uint8_t point )
 {
     if (systemBooting) return;
 
+    PMDebug(kPMLogSleepWakeTracePoint, point, 0);
     pmTracer->tracePoint(point);
 
 #if    HIBERNATION
@@ -6663,8 +6664,10 @@ void IOPMrootDomain::tracePoint( uint8_t point )
 
 void IOPMrootDomain::tracePoint( uint8_t point, uint8_t data )
 {
-    if (!systemBooting)
-        pmTracer->tracePoint(point, data);
+    if (systemBooting) return;
+
+    PMDebug(kPMLogSleepWakeTracePoint, point, data);
+    pmTracer->tracePoint(point, data);
 }
 
 void IOPMrootDomain::traceDetail( uint32_t detail )
index e7f39347403068941d3adb6b380082353ba7f806..29c286ea64f52d01e1487ed952e9dea009dd8231 100644 (file)
@@ -373,48 +373,14 @@ void IOPlatformExpert::
 PMLog(const char *who, unsigned long event,
       unsigned long param1, unsigned long param2)
 {
-    UInt32 debugFlags = gIOKitDebug;
-    UInt32 traceFlags = gIOKitTrace;
-    uintptr_t   name = 0;
-    UInt32 i = 0;
-
-    if (debugFlags & kIOLogPower) {
-
        clock_sec_t nows;
        clock_usec_t nowus;
        clock_get_system_microtime(&nows, &nowus);
        nowus += (nows % 1000) * 1000000;
 
-        kprintf("pm%u %p %.30s %d %lx %lx\n",
+    kprintf("pm%u %p %.30s %d %lx %lx\n",
                nowus, current_thread(), who,   // Identity
                (int) event, (long) param1, (long) param2);                     // Args
-
-       if (traceFlags & kIOTracePowerMgmt) {
-           static const UInt32 sStartStopBitField[] = 
-               { 0x00000000, 0x00000040 }; // Only Program Hardware so far
-
-           // Arcane formula from Hacker's Delight by Warren
-           // abs(x)  = ((int) x >> 31) ^ (x + ((int) x >> 31))
-           UInt32 sgnevent = ((long) event >> 31);
-           UInt32 absevent = sgnevent ^ (event + sgnevent);
-           UInt32 code = IODBG_POWER(absevent);
-
-           UInt32 bit = 1 << (absevent & 0x1f);
-           if (absevent < sizeof(sStartStopBitField) * 8
-           && (sStartStopBitField[absevent >> 5] & bit) ) {
-               // Or in the START or END bits, Start = 1 & END = 2
-               //      If sgnevent ==  0 then START -  0 => START
-               // else if sgnevent == -1 then START - -1 => END
-               code |= DBG_FUNC_START - sgnevent;
-           }
-
-        // Get first 8 characters of the name
-        while ( i < sizeof(uintptr_t) && who[i] != 0) 
-        {    ((char *)&name)[sizeof(uintptr_t)-i-1]=who[i]; i++; }
-           // Record the timestamp. 
-           IOTimeStampConstant(code, name, event, param1, param2);
-       }
-    }
 }
 
 
index e46b02482e361a4a208f32ee7c247c7512d4c1ae..97711e1c8d28683e2e58d025290ceb51f9a9d0e2 100644 (file)
@@ -38,6 +38,7 @@
 #include <IOKit/IOEventSource.h>
 #include <IOKit/IOWorkLoop.h>
 #include <IOKit/IOCommand.h>
+#include <IOKit/IOTimeStamp.h>
 
 #include <IOKit/pwr_mgt/IOPMlog.h>
 #include <IOKit/pwr_mgt/IOPMinformee.h>
@@ -153,8 +154,12 @@ do {                                  \
 #define kIOPMTardyAckPSCKey         "IOPMTardyAckPowerStateChange"
 #define kPwrMgtKey                  "IOPowerManagement"
 
-#define OUR_PMLog(t, a, b) \
-    do { gPlatform->PMLog( fName, t, a, b); } while(0)
+#define OUR_PMLog(t, a, b) do {          \
+    if (gIOKitDebug & kIOLogPower)       \
+        pwrMgt->pmPrint(t, a, b);        \
+    if (gIOKitTrace & kIOTracePowerMgmt) \
+        pwrMgt->pmTrace(t, a, b);        \
+    } while(0)
 
 #define NS_TO_MS(nsec)              ((int)((nsec) / 1000000ULL))
 #define NS_TO_US(nsec)              ((int)((nsec) / 1000ULL))
@@ -675,6 +680,11 @@ void IOService::PMfree ( void )
     }
 }
 
+void IOService::PMDebug( uint32_t event, uintptr_t param1, uintptr_t param2 )
+{
+    OUR_PMLog(event, param1, param2);
+}
+
 //*********************************************************************************
 // [public] joinPMtree
 //
@@ -4130,7 +4140,7 @@ void IOService::all_done ( void )
 #if PM_VARS_SUPPORT
             fPMVars->myCurrentState = fCurrentPowerState;
 #endif
-            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, 0);
+            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
             PM_ACTION_2(actionPowerChangeDone,
                 fHeadNotePowerState, fHeadNoteChangeFlags);
             callAction = true;
@@ -4180,7 +4190,7 @@ void IOService::all_done ( void )
 #endif
             fMaxPowerState = fControllingDriver->maxCapabilityForDomainState(fHeadNoteDomainFlags);
 
-            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, 0);
+            OUR_PMLog(kPMLogChangeDone, fCurrentPowerState, prevPowerState);
             PM_ACTION_2(actionPowerChangeDone,
                 fHeadNotePowerState, fHeadNoteChangeFlags);
             callAction = true;
@@ -7987,6 +7997,51 @@ bool IOServicePM::serialize( OSSerialize * s ) const
     return (kIOReturnSuccess == ret);
 }
 
+void IOServicePM::pmPrint(
+    uint32_t        event,
+    uintptr_t       param1,
+    uintptr_t       param2 ) const
+{
+    gPlatform->PMLog(Name, event, param1, param2);
+}
+
+void IOServicePM::pmTrace(
+    uint32_t        event,
+    uintptr_t       param1,
+    uintptr_t       param2 ) const
+{
+    const char *  who = Name;
+    uint64_t    regId = Owner->getRegistryEntryID();
+    uintptr_t    name = 0;
+
+    static const uint32_t sStartStopBitField[] =
+    { 0x00000000, 0x00000040 }; // Only Program Hardware so far
+
+    // Arcane formula from Hacker's Delight by Warren
+    // abs(x)  = ((int) x >> 31) ^ (x + ((int) x >> 31))
+    uint32_t sgnevent = ((int) event >> 31);
+    uint32_t absevent = sgnevent ^ (event + sgnevent);
+    uint32_t code     = IODBG_POWER(absevent);
+
+    uint32_t bit = 1 << (absevent & 0x1f);
+    if ((absevent < (sizeof(sStartStopBitField) * 8)) &&
+        (sStartStopBitField[absevent >> 5] & bit))
+    {
+        // Or in the START or END bits, Start = 1 & END = 2
+        //      If sgnevent ==  0 then START -  0 => START
+        // else if sgnevent == -1 then START - -1 => END
+        code |= DBG_FUNC_START - sgnevent;
+    }
+
+    // Copy the first characters of the name into an uintptr_t
+    for (uint32_t i = 0; (i < sizeof(uintptr_t) && who[i] != 0); i++)
+    {
+        ((char *) &name)[sizeof(uintptr_t) - i - 1] = who[i];
+    }
+
+    IOTimeStampConstant(code, name, (uintptr_t) regId, param1, param2);
+}
+
 PMEventDetails* PMEventDetails::eventDetails(uint32_t   type,
                                              const char *ownerName,
                                              uintptr_t  ownerUnique,
index bdb74358bad7dcc57ba4ac3c09cf3666bab3e287..47f99ea4501b83e98ccf953d65165afda5e40858 100644 (file)
@@ -347,6 +347,10 @@ private:
     // Serialize IOServicePM state for debug output.
     IOReturn gatedSerialize( OSSerialize * s );
     virtual bool serialize( OSSerialize * s ) const;
+    
+    // PM log and trace
+    void pmPrint( uint32_t event, uintptr_t param1, uintptr_t param2 ) const;
+    void pmTrace( uint32_t event, uintptr_t param1, uintptr_t param2 ) const;
 };
 
 #define fOwner                      pwrMgt->Owner
index c71feccf0ca8671127a9c85afa0505932709d023..e42fa436c09a9124f0a267ef168de7b776359c08 100644 (file)
@@ -42,6 +42,10 @@ __END_DECLS
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/IOKitDebug.h>
 
+#if CONFIG_DTRACE
+#include <mach/sdt.h>
+#endif
+
 #define super IOEventSource
 OSDefineMetaClassAndStructors(IOTimerEventSource, IOEventSource)
 OSMetaClassDefineReservedUnused(IOTimerEventSource, 0);
@@ -117,6 +121,9 @@ void IOTimerEventSource::timeout(void *self)
                                                                                         (uintptr_t) doit, (uintptr_t) me->owner);
                                
                 (*doit)(me->owner, me);
+#if CONFIG_DTRACE
+               DTRACE_TMR3(iotescallout__expire, Action, doit, OSObject, me->owner, void, me->workLoop);
+#endif
                 
                                if (trace)
                        IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION),
@@ -156,6 +163,9 @@ void IOTimerEventSource::timeoutAndRelease(void * self, void * c)
                                                                                         (uintptr_t) doit, (uintptr_t) me->owner);
                                
                 (*doit)(me->owner, me);
+#if CONFIG_DTRACE
+               DTRACE_TMR3(iotescallout__expire, Action, doit, OSObject, me->owner, void, me->workLoop);
+#endif
                 
                                if (trace)
                        IOTimeStampEndConstant(IODBG_TIMES(IOTIMES_ACTION),
index d2c28b04391aa89c968d6a38801f766e2d89c4e1..047a01fe81e9b1e71cd5163c74a82cb3abe73620 100644 (file)
@@ -34,6 +34,7 @@
 #include <IOKit/IOTimeStamp.h>
 #include <IOKit/IOKitDebug.h>
 #include <libkern/OSDebug.h>
+#include <kern/thread.h>
 
 #define super OSObject
 
@@ -177,6 +178,7 @@ bool IOWorkLoop::init()
             return false;
     }
 
+    (void) thread_set_tag(workThread, THREAD_TAG_IOWORKLOOP);
     return true;
 }
 
index 1b6c4d4ec264f403f92d1176ab0bac82c8d46ef6..978cb5ead5e936f48f2fef7bb888a05d4ac5bbaa 100644 (file)
@@ -436,6 +436,8 @@ iokit_no_senders( mach_no_senders_notification_t * notification )
                        /* port unlocked */
                        if ( notify != IP_NULL)
                                ipc_port_release_sonce(notify);
+               } else {
+                       ip_unlock(port);
                }
            }
             iokit_remove_reference( obj );
index d290456ce8b3a7fc88572063ad7eaf5bbc234a14..0921ad5759efc3632ef730b8b10f414c37fe7733 100644 (file)
 diagWork        dgWork;
 uint64_t        lastRuptClear = 0ULL;
 
+void cpu_powerstats(void *);
+
+typedef struct {
+       uint64_t caperf;
+       uint64_t cmperf;
+       uint64_t ccres[3];
+       uint64_t crtimes[4];
+       uint64_t citimes[4];
+       uint64_t crtime_total;
+       uint64_t citime_total;
+} core_energy_stat_t;
+
+typedef struct {
+       uint64_t pkg_cres[2][4];
+       uint64_t pkg_power_unit;
+       uint64_t pkg_energy;
+       uint32_t ncpus;
+       core_energy_stat_t cest[];
+} pkg_energy_statistics_t;
+
 
 int 
 diagCall64(x86_saved_state_t * state)
@@ -84,6 +104,7 @@ diagCall64(x86_saved_state_t * state)
        uint64_t        currNap, durNap;
        x86_saved_state64_t     *regs;
        boolean_t       diagflag;
+       uint32_t        rval = 0;
 
        assert(is_saved_state64(state));
        regs = saved_state64(state);
@@ -93,8 +114,6 @@ diagCall64(x86_saved_state_t * state)
        switch (selector) {     /* Select the routine */
        case dgRuptStat:        /* Suck Interruption statistics */
                (void) ml_set_interrupts_enabled(TRUE);
-               if (diagflag == 0)
-                       break;
                data = regs->rsi; /* Get the number of processors */
 
                if (data == 0) { /* If no location is specified for data, clear all
@@ -107,7 +126,8 @@ diagCall64(x86_saved_state_t * state)
                        }
 
                        lastRuptClear = mach_absolute_time();   /* Get the time of clear */
-                       return 1;       /* Normal return */
+                       rval = 1;       /* Normal return */
+                       break;
                }
 
                (void) copyout((char *) &real_ncpus, data, sizeof(real_ncpus)); /* Copy out number of
@@ -132,8 +152,63 @@ diagCall64(x86_saved_state_t * state)
                        curpos = curpos + (256 * sizeof(uint32_t) + 8); /* Point to next out put
                                                                         * slot */
                }
-               return 1;
+               rval = 1;
                break;
+       case dgPowerStat:
+       {
+               uint32_t c2l = 0, c2h = 0, c3l = 0, c3h = 0, c6l = 0, c6h = 0, c7l = 0, c7h = 0;
+               uint32_t pkg_unit_l = 0, pkg_unit_h = 0, pkg_ecl = 0, pkg_ech = 0;
+
+               pkg_energy_statistics_t pkes;
+               core_energy_stat_t cest;
+
+               bzero(&pkes, sizeof(pkes));
+               bzero(&cest, sizeof(cest));
+
+               rdmsr_carefully(MSR_IA32_PKG_C2_RESIDENCY, &c2l, &c2h);
+               rdmsr_carefully(MSR_IA32_PKG_C3_RESIDENCY, &c3l, &c3h);
+               rdmsr_carefully(MSR_IA32_PKG_C6_RESIDENCY, &c6l, &c6h);
+               rdmsr_carefully(MSR_IA32_PKG_C7_RESIDENCY, &c7l, &c7h);
+
+               pkes.pkg_cres[0][0] = ((uint64_t)c2h << 32) | c2l;
+               pkes.pkg_cres[0][1] = ((uint64_t)c3h << 32) | c3l;
+               pkes.pkg_cres[0][2] = ((uint64_t)c6h << 32) | c6l;
+               pkes.pkg_cres[0][3] = ((uint64_t)c7h << 32) | c7l;
+
+               rdmsr_carefully(MSR_IA32_PKG_POWER_SKU_UNIT, &pkg_unit_l, &pkg_unit_h);
+               rdmsr_carefully(MSR_IA32_PKG_ENERGY_STATUS, &pkg_ecl, &pkg_ech);
+
+               pkes.pkg_power_unit = ((uint64_t)pkg_unit_h << 32) | pkg_unit_l;
+               pkes.pkg_energy = ((uint64_t)pkg_ech << 32) | pkg_ecl;
+
+               pkes.ncpus = real_ncpus;
+
+               (void) ml_set_interrupts_enabled(TRUE);
+
+               copyout(&pkes, regs->rsi, sizeof(pkes));
+               curpos = regs->rsi + sizeof(pkes);
+
+               mp_cpus_call(CPUMASK_ALL, ASYNC, cpu_powerstats, NULL);
+               
+               for (i = 0; i < real_ncpus; i++) {
+                       cest.caperf = cpu_data_ptr[i]->cpu_aperf;
+                       cest.cmperf = cpu_data_ptr[i]->cpu_mperf;
+                       cest.ccres[0] = cpu_data_ptr[i]->cpu_c3res;
+                       cest.ccres[1] = cpu_data_ptr[i]->cpu_c6res;
+                       cest.ccres[2] = cpu_data_ptr[i]->cpu_c7res;
+
+                       bcopy(&cpu_data_ptr[i]->cpu_rtimes[0], &cest.crtimes[0], sizeof(cest.crtimes));
+                       bcopy(&cpu_data_ptr[i]->cpu_itimes[0], &cest.citimes[0], sizeof(cest.citimes));
+                       cest.citime_total = cpu_data_ptr[i]->cpu_itime_total;
+                       cest.crtime_total = cpu_data_ptr[i]->cpu_rtime_total;
+
+                       copyout(&cest, curpos, sizeof(cest));
+                       curpos += sizeof(cest);
+               }
+               rval = 1;
+       }
+               break;
+
 #if    DEBUG
        case dgGzallocTest:
        {
@@ -155,14 +230,40 @@ diagCall64(x86_saved_state_t * state)
                if (diagflag == 0)
                        break;
 
-               return pmap_permissions_verify(kernel_pmap, kernel_map, 0, ~0ULL);
+               rval = pmap_permissions_verify(kernel_pmap, kernel_map, 0, ~0ULL);
        }
                break;
 #endif /* __x86_64__*/
 
        default:                /* Handle invalid ones */
-               return 0;       /* Return an exception */
+               rval = 0;       /* Return an exception */
        }
 
-       return 1;               /* Normal non-ast check return */
+       regs->rax = rval;
+
+       return rval;            /* Normal non-ast check return */
+}
+
+void cpu_powerstats(__unused void *arg) {
+       cpu_data_t *cdp = current_cpu_datap();
+       int cnum = cdp->cpu_number;
+       uint32_t cl = 0, ch = 0, mpl = 0, mph = 0, apl = 0, aph = 0;
+
+       rdmsr_carefully(MSR_IA32_MPERF, &mpl, &mph);
+       rdmsr_carefully(MSR_IA32_APERF, &apl, &aph);
+
+       cdp->cpu_mperf = ((uint64_t)mph << 32) | mpl;
+       cdp->cpu_aperf = ((uint64_t)aph << 32) | apl;
+
+       if (cnum & 1)
+               return;
+
+       rdmsr_carefully(MSR_IA32_CORE_C3_RESIDENCY, &cl, &ch);
+       cdp->cpu_c3res = ((uint64_t)ch << 32) | cl;
+
+       rdmsr_carefully(MSR_IA32_CORE_C6_RESIDENCY, &cl, &ch);
+       cdp->cpu_c6res = ((uint64_t)ch << 32) | cl;
+
+       rdmsr_carefully(MSR_IA32_CORE_C7_RESIDENCY, &cl, &ch);
+       cdp->cpu_c7res = ((uint64_t)ch << 32) | cl;
 }
index e2c264a8b68fade7e61ec6c2e8f3721613b88e90..2ce145e27d4c1417c5baa055ed81032f0b2840b2 100644 (file)
@@ -59,14 +59,14 @@ int diagCall64(x86_saved_state_t *regs);
 #define dgBootScreen 7
 #define dgFlush 8
 #define dgAlign 9
-#define dgprw 10
+#define dgGzallocTest 10
 #define dgmck 11
 #define dg64 12
 #define dgProbeRead 13
 #define dgCPNull 14
 #define dgPerfMon 15
 #define dgMapPage 16
-#define dgGzallocTest 17
+#define dgPowerStat 17
 #define dgBind 18
 #define dgAcntg 20
 #define dgKlra 21
index 3473fbd3ac0bba2b84f8f2823d2b8603b002094a..a501be695463c62018672e0884ea3344ea62a3a3 100644 (file)
@@ -239,6 +239,16 @@ typedef struct cpu_data
        uint64_t                cpu_pmap_pcid_preserves;
 #endif
 #endif /* x86_64 */
+       uint64_t                cpu_aperf;
+       uint64_t                cpu_mperf;
+       uint64_t                cpu_c3res;
+       uint64_t                cpu_c6res;
+       uint64_t                cpu_c7res;
+       uint64_t                cpu_itime_total;
+       uint64_t                cpu_rtime_total;
+       uint64_t                cpu_rtimes[4];
+       uint64_t                cpu_itimes[4];
+       uint64_t                cpu_ixtime;
        uint64_t                cpu_max_observed_int_latency;
        int                     cpu_max_observed_int_latency_vector;
        uint64_t                debugger_entry_time;
index 77445d9b15905b7aa0f07fb5eda5eb1e3923b420..ff109f927ec23efa3db25e3df467d39a40c97239 100644 (file)
@@ -207,6 +207,7 @@ typedef struct x86_pkg
     void               *pmStats;       /* Power Management stats for package*/
     void               *pmState;       /* Power Management state for package*/
     struct mca_state   *mca_state;     /* MCA state for memory errors */
+    uint32_t           num_idle;
 } x86_pkg_t;
 
 extern x86_pkg_t       *x86_pkgs;      /* root of all CPU packages */
index 84f860b5ba988adf5794eac10602c9608df91e84..1119a0a7335d4ec9dc2a34a1d06678153288151e 100644 (file)
@@ -562,7 +562,7 @@ fpu_set_fxstate(
                iavx->fp_save_layout = thread_is_64bit(thr_act) ? XSAVE64 : XSAVE32;
                /* Sanitize XSAVE header */
                bzero(&iavx->_xh.xhrsvd[0], sizeof(iavx->_xh.xhrsvd));
-               if (state_size == sizeof(struct x86_avx_thread_state))
+               if (fpu_nyreg)
                        iavx->_xh.xsbv = (XFEM_YMM | XFEM_SSE | XFEM_X87);
                else
                        iavx->_xh.xsbv = (XFEM_SSE | XFEM_X87);
index 22eae015943d27947ef6bd4f438510ba4da5d3b3..e008a9a612b502df51ecd7a52e958dfac6bb644a 100644 (file)
@@ -248,6 +248,15 @@ boolean_t ml_at_interrupt_context(void)
        return get_interrupt_level() != 0;
 }
 
+void ml_get_power_state(boolean_t *icp, boolean_t *pidlep) {
+       *icp = (get_interrupt_level() != 0);
+       /* These will be technically inaccurate for interrupts that occur
+        * successively within a single "idle exit" event, but shouldn't
+        * matter statistically.
+        */
+       *pidlep = (current_cpu_datap()->lcpu.package->num_idle == topoParms.nLThreadsPerPackage);
+}
+
 /* Generate a fake interrupt */
 void ml_cause_interrupt(void)
 {
index 65e28b742c796dba0513e9a49e83f471a58e9546..d800625f75cc41946e4f9b1d00c5d7a7e3b07fee 100644 (file)
@@ -312,6 +312,7 @@ boolean_t ml_fpu_avx_enabled(void);
 void interrupt_latency_tracker_setup(void);
 void interrupt_reset_latency_stats(void);
 void interrupt_populate_latency_stats(char *, unsigned);
+void ml_get_power_state(boolean_t *, boolean_t *);
 
 #endif /* XNU_KERNEL_PRIVATE */
 #endif /* _I386_MACHINE_ROUTINES_H_ */
index dc59735b966604cc48b900021c2a7b3d39a096c8..7e0112fbb99f49d82627ff112fe0d313d1e64111 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * Copyright (c) 2009 Apple Inc. All rights reserved.
  *
@@ -154,14 +155,18 @@ void pal_efi_hibernate_prepare(void);
 /* Include a PAL-specific header, too, for xnu-internal overrides */
 #include <i386/pal_native.h>
 
+extern boolean_t virtualized;
+#define PAL_VIRTUALIZED_PROPERTY_VALUE 4
 
 /* Allow for tricky IOKit property matching */
 #define PAL_AICPM_PROPERTY_NAME "intel_cpupm_matching"
 static inline void 
 pal_get_resource_property(const char **property_name, int *property_value)
 {
-       *property_name = PAL_AICPM_PROPERTY_NAME;
-       *property_value = PAL_AICPM_PROPERTY_VALUE;
+        *property_name = PAL_AICPM_PROPERTY_NAME;
+        *property_value = PAL_AICPM_PROPERTY_VALUE;
+        if (virtualized)
+                *property_value = PAL_VIRTUALIZED_PROPERTY_VALUE;
 }
 
 /* assembly function to update TSC / timebase info */
index b22749df79e3ce64935e3ba068baf6815d4611f2..ec5ae7f784206d05d1ecfce567334d1fe0f1ddfc 100644 (file)
@@ -76,6 +76,14 @@ power_management_init(void)
        (*pmDispatch->cstateInit)();
 }
 
+#define CPU_ACTIVE_STAT_BIN_1 (500000)
+#define CPU_ACTIVE_STAT_BIN_2 (2000000)
+#define CPU_ACTIVE_STAT_BIN_3 (5000000)
+
+#define CPU_IDLE_STAT_BIN_1 (500000)
+#define CPU_IDLE_STAT_BIN_2 (2000000)
+#define CPU_IDLE_STAT_BIN_3 (5000000)
+
 /*
  * Called when the CPU is idle.  It calls into the power management kext
  * to determine the best way to idle the CPU.
@@ -84,14 +92,31 @@ void
 machine_idle(void)
 {
     cpu_data_t         *my_cpu         = current_cpu_datap();
+    uint64_t           ctime, rtime, itime;
 
     if (my_cpu == NULL)
        goto out;
 
+       ctime = mach_absolute_time();
+
     my_cpu->lcpu.state = LCPU_IDLE;
     DBGLOG(cpu_handle, cpu_number(), MP_IDLE);
     MARK_CPU_IDLE(cpu_number());
 
+       rtime = ctime - my_cpu->cpu_ixtime;
+
+       my_cpu->cpu_rtime_total += rtime;
+
+       if (rtime < CPU_ACTIVE_STAT_BIN_1)
+               my_cpu->cpu_rtimes[0]++;
+       else if (rtime < CPU_ACTIVE_STAT_BIN_2)
+               my_cpu->cpu_rtimes[1]++;
+       else if (rtime < CPU_ACTIVE_STAT_BIN_3)
+               my_cpu->cpu_rtimes[2]++;
+       else
+               my_cpu->cpu_rtimes[3]++;
+
+
     if (pmInitDone) {
        /*
         * Handle case where ml_set_maxbusdelay() or ml_set_maxintdelay()
@@ -129,8 +154,24 @@ machine_idle(void)
      */
     MARK_CPU_ACTIVE(cpu_number());
     DBGLOG(cpu_handle, cpu_number(), MP_UNIDLE);
+
+       uint64_t ixtime = my_cpu->cpu_ixtime = mach_absolute_time();
+       itime = ixtime - ctime;
+
     my_cpu->lcpu.state = LCPU_RUN;
 
+       if (itime < CPU_IDLE_STAT_BIN_1)
+               my_cpu->cpu_itimes[0]++;
+       else if (itime < CPU_IDLE_STAT_BIN_2)
+               my_cpu->cpu_itimes[1]++;
+       else if (itime < CPU_IDLE_STAT_BIN_3)
+               my_cpu->cpu_itimes[2]++;
+       else
+               my_cpu->cpu_itimes[3]++;
+
+       my_cpu->cpu_itime_total += itime;
+
+
     /*
      * Re-enable interrupts.
      */
@@ -362,7 +403,7 @@ pmCPUExitHalt(int cpu)
 kern_return_t
 pmCPUExitHaltToOff(int cpu)
 {
-    kern_return_t      rc      = KERN_INVALID_ARGUMENT;
+    kern_return_t      rc      = KERN_SUCCESS;
 
     if (pmInitDone
        && pmDispatch != NULL
@@ -890,3 +931,14 @@ pmsBuild(__unused pmsDef *pd, __unused uint32_t pdsize,
 {
     return(KERN_SUCCESS);
 }
+
+void machine_track_platform_idle(boolean_t entry) {
+       cpu_data_t              *my_cpu         = current_cpu_datap();
+
+       if (entry) {
+               (void)__sync_fetch_and_add(&my_cpu->lcpu.package->num_idle, 1);
+       }
+       else {
+               (void)__sync_fetch_and_sub(&my_cpu->lcpu.package->num_idle, 1);
+       }
+}
index 755be1c694db2720b9e6dd437e5e8ea91b53b834..6438d9372edc71931b152e829f80467de1b8b79f 100644 (file)
@@ -535,6 +535,9 @@ __END_DECLS
 
 #define MSR_PLATFORM_INFO                      0xce
 
+#define MSR_IA32_MPERF                         0xE7
+#define MSR_IA32_APERF                         0xE8
+
 #define MSR_PMG_CST_CONFIG_CONTROL             0xe2
 
 #define MSR_IA32_BBL_CR_CTL                    0x119
@@ -585,6 +588,14 @@ __END_DECLS
 #define MSR_IA32_MTRR_FIX4K_F0000              0x26e
 #define MSR_IA32_MTRR_FIX4K_F8000              0x26f
 
+#define MSR_IA32_PKG_C3_RESIDENCY              0x3F8
+#define MSR_IA32_PKG_C6_RESIDENCY              0x3F9
+#define MSR_IA32_PKG_C7_RESIDENCY              0x3FA
+
+#define MSR_IA32_CORE_C3_RESIDENCY             0x3FC
+#define MSR_IA32_CORE_C6_RESIDENCY             0x3FD
+#define MSR_IA32_CORE_C7_RESIDENCY             0x3FE
+
 #define MSR_IA32_MC0_CTL                       0x400
 #define MSR_IA32_MC0_STATUS                    0x401
 #define MSR_IA32_MC0_ADDR                      0x402
@@ -604,8 +615,9 @@ __END_DECLS
 
 #define MSR_IA32_DS_AREA                       0x600
 
-#define MSR_IA32_PACKAGE_POWER_SKU_UNIT                0x606
-#define MSR_IA32_PACKAGE_ENERY_STATUS          0x611
+#define MSR_IA32_PKG_POWER_SKU_UNIT            0x606
+#define MSR_IA32_PKG_C2_RESIDENCY              0x60D
+#define MSR_IA32_PKG_ENERGY_STATUS             0x611
 #define MSR_IA32_PRIMARY_PLANE_ENERY_STATUS    0x639
 #define MSR_IA32_SECONDARY_PLANE_ENERY_STATUS  0x641
 #define MSR_IA32_TSC_DEADLINE                  0x6e0
index dc55ce790528b48f9fead704f62c23f512cd94df..75b1e5f830a76f4f50c304184e109849c0ecc2b3 100644 (file)
@@ -438,6 +438,26 @@ MACRO_END
                return (KERN_SUCCESS);
        }
 
+       case HOST_EXPIRED_TASK_INFO:
+       {
+               if (*count < TASK_POWER_INFO_COUNT) {
+                       return (KERN_FAILURE);
+               }
+
+               task_power_info_t tinfo = (task_power_info_t)info;
+
+               tinfo->task_interrupt_wakeups = dead_task_statistics.task_interrupt_wakeups;
+               tinfo->task_platform_idle_wakeups = dead_task_statistics.task_platform_idle_wakeups;
+
+               tinfo->task_timer_wakeups_bin_1 = dead_task_statistics.task_timer_wakeups_bin_1;
+               tinfo->task_timer_wakeups_bin_2 = dead_task_statistics.task_timer_wakeups_bin_2;
+
+               tinfo->total_user = dead_task_statistics.total_user_time;
+               tinfo->total_system = dead_task_statistics.total_system_time;
+
+               return (KERN_SUCCESS);
+       }
+
        default:
                return (KERN_INVALID_ARGUMENT);
        }
index 24b052648d59c1f8225fb31cbfbc9241c6a3aec1..59458f00cc2b846b3888aba15c4e189d19cad02a 100644 (file)
@@ -91,6 +91,17 @@ extern host_data_t   realhost;
 
 extern vm_extmod_statistics_data_t host_extmod_statistics;
 
+typedef struct {
+       uint64_t total_user_time;
+       uint64_t total_system_time;
+       uint64_t task_interrupt_wakeups;
+       uint64_t task_platform_idle_wakeups;
+       uint64_t task_timer_wakeups_bin_1;
+       uint64_t task_timer_wakeups_bin_2;
+} expired_task_statistics_t;
+
+extern expired_task_statistics_t dead_task_statistics;
+
 #endif /* MACH_KERNEL_PRIVATE */
 
 /*
index 106a9b41d792370324509feb34c273b4fc3e9d82..6d46f2c6e38939da46f88775e4f16eb221d3ea4b 100644 (file)
@@ -90,6 +90,8 @@ extern thread_t               machine_processor_shutdown(
 
 extern void machine_idle(void);
 
+extern void machine_track_platform_idle(boolean_t);
+
 extern void machine_signal_idle(
                                        processor_t         processor);
 
index 7b01b11a465bef656a6d3a2f0ea8b25f5466d1c4..5a83c61c8dd1e49d5a4a93c4177d0eab61c68ac8 100644 (file)
@@ -87,6 +87,7 @@ struct processor_data {
        void                                    *free_pages;
 
        struct processor_sched_statistics sched_stats;
+       uint64_t        timer_call_ttd; /* current timer call time-to-deadline */
 };
 
 typedef struct processor_data  processor_data_t;
index 5f4803119455b6a24e442ad9217f5fb42717f26a..eebc19bf5b613150da8e046c0e9f90d0460240a7 100644 (file)
@@ -165,6 +165,14 @@ uint32_t   sched_fixed_shift;
 
 static boolean_t sched_traditional_use_pset_runqueue = FALSE;
 
+/* Defaults for timer deadline profiling */
+#define TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT 2000000 /* Timers with deadlines <=
+                                                        * 2ms */
+#define TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT 5000000 /* Timers with deadlines
+                                                          <= 5ms */
+uint64_t timer_deadline_tracking_bin_1;
+uint64_t timer_deadline_tracking_bin_2;
+
 __attribute__((always_inline))
 static inline run_queue_t runq_for_processor(processor_t processor)
 {
@@ -309,6 +317,9 @@ sched_realtime_init(void)  __attribute__((section("__TEXT, initcode")));
 static void
 sched_realtime_timebase_init(void);
 
+static void
+sched_timer_deadline_tracking_init(void);
+
 #if defined(CONFIG_SCHED_TRADITIONAL)
 static void
 sched_traditional_tick_continue(void);
@@ -563,6 +574,7 @@ sched_init(void)
        SCHED(fairshare_init)();
        sched_realtime_init();
        ast_init();
+       sched_timer_deadline_tracking_init();
        
        SCHED(pset_init)(&pset0);
        SCHED(processor_init)(master_processor);
@@ -858,6 +870,7 @@ thread_unblock(
        wait_result_t   wresult)
 {
        boolean_t               result = FALSE;
+       thread_t                cthread = current_thread();
 
        /*
         *      Set wait_result.
@@ -924,6 +937,43 @@ thread_unblock(
        thread->computation_metered = 0;
        thread->reason = AST_NONE;
 
+       /* Obtain power-relevant interrupt and "platform-idle exit" statistics.
+        * We also account for "double hop" thread signaling via
+        * the thread callout infrastructure.
+        * DRK: consider removing the callout wakeup counters in the future
+        * they're present for verification at the moment.
+        */
+       boolean_t aticontext, pidle;
+       ml_get_power_state(&aticontext, &pidle);
+       if (__improbable(aticontext)) {
+               ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
+               uint64_t ttd = PROCESSOR_DATA(current_processor(), timer_call_ttd);
+               if (ttd) {
+                       if (ttd <= timer_deadline_tracking_bin_1)
+                               thread->thread_timer_wakeups_bin_1++;
+                       else
+                               if (ttd <= timer_deadline_tracking_bin_2)
+                                       thread->thread_timer_wakeups_bin_2++;
+               }
+               if (pidle) {
+                       ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
+               }
+       } else if (thread_get_tag_internal(cthread) & THREAD_TAG_CALLOUT) {
+               if (cthread->callout_woken_from_icontext) {
+                       ledger_credit(thread->t_ledger, task_ledgers.interrupt_wakeups, 1);
+                       thread->thread_callout_interrupt_wakeups++;
+                       if (cthread->callout_woken_from_platform_idle) {
+                               ledger_credit(thread->t_ledger, task_ledgers.platform_idle_wakeups, 1);
+                               thread->thread_callout_platform_idle_wakeups++;
+                       }
+               }
+       }
+       
+       if (thread_get_tag_internal(thread) & THREAD_TAG_CALLOUT) {
+                       thread->callout_woken_from_icontext = aticontext;
+                       thread->callout_woken_from_platform_idle = pidle;
+       }
+
        /* Event should only be triggered if thread is not already running */
        if (result == FALSE) {
                KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE,
@@ -4039,8 +4089,12 @@ processor_idle(
                IDLE_KERNEL_DEBUG_CONSTANT(
                        MACHDBG_CODE(DBG_MACH_SCHED,MACH_IDLE) | DBG_FUNC_NONE, (uintptr_t)thread_tid(thread), rt_runq.count, SCHED(processor_runq_count)(processor), -1, 0);
 
+               machine_track_platform_idle(TRUE);
+
                machine_idle();
 
+               machine_track_platform_idle(FALSE);
+
                (void)splsched();
 
                IDLE_KERNEL_DEBUG_CONSTANT(
@@ -4506,3 +4560,9 @@ thread_runnable(
        return ((thread->state & (TH_RUN|TH_WAIT)) == TH_RUN);
 }
 #endif /* DEBUG */
+
+static void
+sched_timer_deadline_tracking_init(void) {
+       nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_1_DEFAULT, &timer_deadline_tracking_bin_1);
+       nanoseconds_to_absolutetime(TIMER_DEADLINE_TRACKING_BIN_2_DEFAULT, &timer_deadline_tracking_bin_2);
+}
index 1378bf4150bc3c606fd76dda90ebeb7483e30b68..324195b3dff01507e636f3eedcd3e00bc25d9b1c 100644 (file)
@@ -157,8 +157,12 @@ lck_mtx_t  task_watch_mtx;
 zinfo_usage_store_t tasks_tkm_private;
 zinfo_usage_store_t tasks_tkm_shared;
 
+/* A container to accumulate statistics for expired tasks */
+expired_task_statistics_t                dead_task_statistics;
+lck_spin_t                dead_task_statistics_lock;
+
 static ledger_template_t task_ledger_template = NULL;
-struct _task_ledger_indices task_ledgers = {-1, -1, -1, -1, -1};
+struct _task_ledger_indices task_ledgers = {-1, -1, -1, -1, -1, -1, -1};
 void init_task_ledgers(void);
 
 
@@ -292,7 +296,7 @@ task_init(void)
 
        vm_map_deallocate(kernel_task->map);
        kernel_task->map = kernel_map;
-
+       lck_spin_init(&dead_task_statistics_lock, &task_lck_grp, &task_lck_attr);
 }
 
 /*
@@ -371,10 +375,15 @@ init_task_ledgers(void)
            "bytes");
        task_ledgers.wired_mem = ledger_entry_add(t, "wired_mem", "physmem",
            "bytes");
+       task_ledgers.platform_idle_wakeups = ledger_entry_add(t, "platform_idle_wakeups", "power",
+           "count");
+       task_ledgers.interrupt_wakeups = ledger_entry_add(t, "interrupt_wakeups", "power",
+           "count");
 
        if ((task_ledgers.cpu_time < 0) || (task_ledgers.tkm_private < 0) ||
            (task_ledgers.tkm_shared < 0) || (task_ledgers.phys_mem < 0) ||
-           (task_ledgers.wired_mem < 0)) {
+           (task_ledgers.wired_mem < 0) || (task_ledgers.platform_idle_wakeups < 0) ||
+           (task_ledgers.interrupt_wakeups < 0)) {
                panic("couldn't create entries for task ledger template");
        }
 
@@ -556,6 +565,7 @@ task_create_internal(
        }
 
        bzero(&new_task->extmod_statistics, sizeof(new_task->extmod_statistics));
+       new_task->task_timer_wakeups_bin_1 = new_task->task_timer_wakeups_bin_2 = 0;
        
        lck_mtx_lock(&tasks_threads_lock);
        queue_enter(&tasks, new_task, task_t, tasks);
@@ -580,7 +590,7 @@ void
 task_deallocate(
        task_t          task)
 {
-       ledger_amount_t credit, debit;
+       ledger_amount_t credit, debit, interrupt_wakeups, platform_idle_wakeups;
 
        if (task == TASK_NULL)
            return;
@@ -607,6 +617,23 @@ task_deallocate(
        vm_map_deallocate(task->map);
        is_release(task->itk_space);
 
+       ledger_get_entries(task->ledger, task_ledgers.interrupt_wakeups,
+                          &interrupt_wakeups, &debit);
+       ledger_get_entries(task->ledger, task_ledgers.platform_idle_wakeups,
+                          &platform_idle_wakeups, &debit);
+
+       /* Accumulate statistics for dead tasks */
+       lck_spin_lock(&dead_task_statistics_lock);
+       dead_task_statistics.total_user_time += task->total_user_time;
+       dead_task_statistics.total_system_time += task->total_system_time;
+
+       dead_task_statistics.task_interrupt_wakeups += interrupt_wakeups;
+       dead_task_statistics.task_platform_idle_wakeups += platform_idle_wakeups;
+
+       dead_task_statistics.task_timer_wakeups_bin_1 += task->task_timer_wakeups_bin_1;
+       dead_task_statistics.task_timer_wakeups_bin_2 += task->task_timer_wakeups_bin_2;
+
+       lck_spin_unlock(&dead_task_statistics_lock);
        lck_mtx_destroy(&task->lock, &task_lck_grp);
 
 #if CONFIG_MACF_MACH
@@ -2030,6 +2057,60 @@ task_info(
                error = task_affinity_info(task, task_info_out, task_info_count);
                break;
        }
+
+       case TASK_POWER_INFO:
+       {
+               task_power_info_t       info;
+               thread_t                        thread;
+               ledger_amount_t         tmp;
+
+               if (*task_info_count < TASK_POWER_INFO_COUNT) {
+                       error = KERN_INVALID_ARGUMENT;
+                       break;
+               }
+
+               info = (task_power_info_t)task_info_out;
+
+               ledger_get_entries(task->ledger, task_ledgers.interrupt_wakeups,
+                       (ledger_amount_t *)&info->task_interrupt_wakeups, &tmp);
+               ledger_get_entries(task->ledger, task_ledgers.platform_idle_wakeups,
+                       (ledger_amount_t *)&info->task_platform_idle_wakeups, &tmp);
+
+               info->task_timer_wakeups_bin_1 = task->task_timer_wakeups_bin_1;
+               info->task_timer_wakeups_bin_2 = task->task_timer_wakeups_bin_2;
+
+               info->total_user = task->total_user_time;
+               info->total_system = task->total_system_time;
+
+               queue_iterate(&task->threads, thread, thread_t, task_threads) {
+                       uint64_t        tval;
+                       spl_t           x;
+
+                       if ((task == kernel_task) && (thread->priority == IDLEPRI) && (thread->sched_pri == IDLEPRI))
+                               continue;
+                       x = splsched();
+                       thread_lock(thread);
+
+                       info->task_timer_wakeups_bin_1 += thread->thread_timer_wakeups_bin_1;
+                       info->task_timer_wakeups_bin_2 += thread->thread_timer_wakeups_bin_2;
+
+                       tval = timer_grab(&thread->user_timer);
+                       info->total_user += tval;
+
+                       tval = timer_grab(&thread->system_timer);
+                       if (thread->precise_user_kernel_time) {
+                               info->total_system += tval;
+                       } else {
+                               /* system_timer may represent either sys or user */
+                               info->total_user += tval;
+                       }
+
+                       thread_unlock(thread);
+                       splx(x);
+               }
+               break;
+       }
+
        default:
                error = KERN_INVALID_ARGUMENT;
        }
index 7d2c981ce121f40d3c0f1d22f862a42916e787a3..9b6e4a1f6d3d4bea9cb27877b8556ea6caaa6229 100644 (file)
@@ -362,6 +362,10 @@ struct task {
 
        vm_extmod_statistics_data_t     extmod_statistics;
        natural_t       proc_terminate; /* the process is marked for proc_terminate */
+
+       /* Statistics accumulated for terminated threads from this task */
+       uint32_t        task_timer_wakeups_bin_1;
+       uint32_t        task_timer_wakeups_bin_2;
 };
 
 #define task_lock(task)                lck_mtx_lock(&(task)->lock)
@@ -555,6 +559,8 @@ struct _task_ledger_indices {
        int tkm_shared;
        int phys_mem;
        int wired_mem;
+       int platform_idle_wakeups;
+       int interrupt_wakeups;
 };
 extern struct _task_ledger_indices task_ledgers;
 
index 2738d385001223c9161c64b61e30fcb4068189fb..92840195a4e72c9e758376364b2b55d532154a87 100644 (file)
@@ -506,6 +506,8 @@ thread_terminate_daemon(void)
                task->syscalls_unix += thread->syscalls_unix;
                task->syscalls_mach += thread->syscalls_mach;
 
+               task->task_timer_wakeups_bin_1 += thread->thread_timer_wakeups_bin_1;
+               task->task_timer_wakeups_bin_2 += thread->thread_timer_wakeups_bin_2;
                queue_remove(&task->threads, thread, thread_t, task_threads);
                task->thread_count--;
 
@@ -1701,6 +1703,15 @@ thread_tid(
        return (thread != THREAD_NULL? thread->thread_id: 0);
 }
 
+uint16_t
+thread_set_tag(thread_t th, uint16_t tag) {
+       return thread_set_tag_internal(th, tag);
+}
+uint16_t
+thread_get_tag(thread_t th) {
+       return thread_get_tag_internal(th);
+}
+
 uint64_t
 thread_dispatchqaddr(
        thread_t                thread)
index b497fa3facfd3e7999dd50c42d37bc9e5726bf38..89ac1937bf42283f6621455303729a165442f968 100644 (file)
@@ -149,6 +149,7 @@ struct thread {
 #define TH_OPT_SYSTEM_CRITICAL 0x10            /* Thread must always be allowed to run - even under heavy load */
 #define TH_OPT_PROC_CPULIMIT   0x20            /* Thread has a task-wide CPU limit applied to it */
 #define TH_OPT_PRVT_CPULIMIT   0x40            /* Thread has a thread-private CPU limit applied to it */
+#define TH_OPT_IDLE_THREAD             0x0080          /* Thread is a per-processor idle thread */
 
        /* Data updated during assert_wait/thread_wakeup */
        decl_simple_lock_data(,sched_lock)      /* scheduling lock (thread_lock()) */
@@ -427,6 +428,15 @@ struct thread {
        task_watch_t *  taskwatch;              /* task watch */
        integer_t               saved_importance;               /* saved task-relative importance */
 #endif /* CONFIG_EMBEDDED */
+       uint32_t                        thread_callout_interrupt_wakeups;
+       uint32_t                        thread_callout_platform_idle_wakeups;
+       uint32_t                        thread_timer_wakeups_bin_1;
+       uint32_t                        thread_timer_wakeups_bin_2;
+       uint16_t                        thread_tag;
+       uint16_t                        callout_woken_from_icontext:1,
+                                       callout_woken_from_platform_idle:1,
+                                       thread_bitfield_unused:14;
+
 };
 
 #define ith_state              saved.receive.state
@@ -645,6 +655,13 @@ extern void                funnel_lock(
 extern void            funnel_unlock(
                                                struct funnel_lock      *lock);
 
+static inline uint16_t thread_set_tag_internal(thread_t thread, uint16_t tag) {
+       return __sync_fetch_and_or(&thread->thread_tag, tag);
+}
+static inline uint16_t thread_get_tag_internal(thread_t thread) {
+       return thread->thread_tag;
+}
+
 #else  /* MACH_KERNEL_PRIVATE */
 
 __BEGIN_DECLS
@@ -687,6 +704,16 @@ __BEGIN_DECLS
 
 #ifdef XNU_KERNEL_PRIVATE
 
+/*
+ * Thread tags; for easy identification.
+ */
+#define        THREAD_TAG_MAINTHREAD 0x1
+#define        THREAD_TAG_CALLOUT 0x2
+#define        THREAD_TAG_IOWORKLOOP 0x4
+
+uint16_t       thread_set_tag(thread_t, uint16_t);
+uint16_t       thread_get_tag(thread_t);
+
 extern kern_return_t    thread_state_initialize(
                                                        thread_t                                thread);
 
index 7d43919ae6cbb3610b92fa80cd5c518c7c1cd62c..36cb66a8e88d1b0168754e746d705dae404aacb9 100644 (file)
@@ -46,7 +46,9 @@
 #include <libkern/OSAtomic.h>
 
 #include <sys/kdebug.h>
-
+#if CONFIG_DTRACE
+#include <mach/sdt.h>
+#endif
 
 static zone_t                  thread_call_zone;
 static struct wait_queue       daemon_wqueue;
@@ -889,11 +891,13 @@ thread_call_enter1_delayed(
        boolean_t               result = TRUE;
        thread_call_group_t     group;
        spl_t                   s;
+       uint64_t                abstime;
 
        group = thread_call_get_group(call);
 
        s = splsched();
        thread_call_lock_spin();
+       abstime =  mach_absolute_time();
 
        result = _delayed_call_enqueue(call, group, deadline);
 
@@ -902,6 +906,10 @@ thread_call_enter1_delayed(
 
        call->tc_call.param1 = param1;
 
+       call->ttd = (deadline > abstime) ? (deadline - abstime) : 0;
+#if CONFIG_DTRACE
+       DTRACE_TMR4(thread_callout__create, thread_call_func_t, call->tc_call.func, 0, (call->ttd >> 32), (unsigned) (call->ttd & 0xFFFFFFFF));
+#endif
        thread_call_unlock();
        splx(s);
 
@@ -933,6 +941,9 @@ thread_call_cancel(
 
        thread_call_unlock();
        splx(s);
+#if CONFIG_DTRACE
+       DTRACE_TMR4(thread_callout__cancel, thread_call_func_t, call->tc_call.func, 0, (call->ttd >> 32), (unsigned) (call->ttd & 0xFFFFFFFF));
+#endif
 
        return (result);
 }
@@ -1135,6 +1146,9 @@ thread_call_thread(
        thread_t        self = current_thread();
        boolean_t       canwait;
 
+       if ((thread_get_tag_internal(self) & THREAD_TAG_CALLOUT) == 0)
+               (void)thread_set_tag_internal(self, THREAD_TAG_CALLOUT);
+
        /*
         * A wakeup with THREAD_INTERRUPTED indicates that 
         * we should terminate.
index e2836e293dd1c2ec7f8a268165aacdd2ee4a34c5..e1ddebc36302b3ce644a4ea755bb340a433ca0d2 100644 (file)
@@ -228,6 +228,8 @@ struct thread_call {
 
        uint32_t                        tc_flags;
        int32_t                         tc_refs;
+
+       uint64_t                        ttd; /* Time to deadline at creation */
 }; 
 
 #define THREAD_CALL_ALLOC              0x01
index 0d737dbbbee80e7a88650ff20872d7e9567579e8..5a17e057c3648e1fc028441bd52d4d889631e90b 100644 (file)
@@ -40,7 +40,7 @@
 
 #include <sys/kdebug.h>
 
-#if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
+#if CONFIG_DTRACE
 #include <mach/sdt.h>
 #endif
 
@@ -358,6 +358,15 @@ timer_call_enter_internal(
                call->soft_deadline = deadline;
        }
 #endif
+       call->ttd =  call->soft_deadline - ctime;
+
+#if CONFIG_DTRACE
+       DTRACE_TMR6(callout__create, timer_call_func_t, CE(call)->func,
+       timer_call_param_t, CE(call)->param0, uint32_t, call->flags,
+           (deadline - call->soft_deadline),
+           (call->ttd >> 32), (unsigned) (call->ttd & 0xFFFFFFFF));
+#endif
+
        queue = timer_queue_assign(deadline);
 
        old_queue = timer_call_enqueue_deadline_unlocked(call, queue, deadline);
@@ -409,6 +418,12 @@ timer_call_cancel(
        }
        splx(s);
 
+#if CONFIG_DTRACE
+       DTRACE_TMR6(callout__cancel, timer_call_func_t, CE(call)->func,
+           timer_call_param_t, CE(call)->param0, uint32_t, call->flags, 0,
+           (call->ttd >> 32), (unsigned) (call->ttd & 0xFFFFFFFF));
+#endif
+
        return (old_queue != NULL);
 }
 
@@ -499,18 +514,25 @@ timer_queue_expire(
                                DECR_TIMER_CALLOUT | DBG_FUNC_START,
                                VM_KERNEL_UNSLIDE(func), param0, param1, 0, 0);
 
-#if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
-                       DTRACE_TMR3(callout__start, timer_call_func_t, func, 
-                                                                               timer_call_param_t, param0, 
-                                                                               timer_call_param_t, param1);
+#if CONFIG_DTRACE
+                       DTRACE_TMR6(callout__start, timer_call_func_t, func,
+                           timer_call_param_t, param0, unsigned, call->flags,
+                           0, (call->ttd >> 32),
+                           (unsigned) (call->ttd & 0xFFFFFFFF));
 #endif
 
+                       /* Maintain time-to-deadline in per-processor data
+                        * structure for thread wakeup deadline statistics.
+                        */
+                       uint64_t *ttdp = &(PROCESSOR_DATA(current_processor(), timer_call_ttd));
+                       *ttdp = call->ttd;
                        (*func)(param0, param1);
+                       *ttdp = 0;
 
-#if CONFIG_DTRACE && (DEVELOPMENT || DEBUG )
-                       DTRACE_TMR3(callout__end, timer_call_func_t, func, 
-                                                                               timer_call_param_t, param0, 
-                                                                               timer_call_param_t, param1);
+#if CONFIG_DTRACE
+                       DTRACE_TMR3(callout__end, timer_call_func_t, func,
+                           timer_call_param_t, param0, timer_call_param_t,
+                           param1);
 #endif
 
                        KERNEL_DEBUG_CONSTANT_IST(KDEBUG_TRACE, 
index f2a074d39b713930e3fd6936156e190041622163..1f9370b1ef84ed917bdbef3f3a325cd49ec93296 100644 (file)
@@ -49,6 +49,7 @@ typedef struct timer_call {
        uint32_t                flags;
        boolean_t               async_dequeue;  /* this field is protected by
                                                   call_entry queue's lock */
+       uint64_t                ttd; /* Time to deadline at creation */
 } *timer_call_t;
 
 typedef void                           *timer_call_param_t;
index d90f3be37fdde25d62c0c2d87d4d9cae3dc326d4..0464d5ed054b396115f2e23bac876cbc189c106d 100644 (file)
@@ -185,7 +185,7 @@ typedef struct host_priority_info   *host_priority_info_t;
 /* host_statistics64() */
 #define HOST_VM_INFO64         4       /* 64-bit virtual memory stats */
 #define HOST_EXTMOD_INFO64     5       /* External modification stats */
-
+#define HOST_EXPIRED_TASK_INFO        6        /* Statistics for expired tasks */
 
 struct host_load_info {
        integer_t       avenrun[3];     /* scaled by LOAD_SCALE */
index 551f2b0fc496d1f385198742030e67577c84642c..cf99fbd0913f860f7466cb5120101601e2b5a644 100644 (file)
 #define        DTRACE_TMR3(name, type1, arg1, type2, arg2, type3, arg3)                \
        DTRACE_PROBE3(__sdt_, name, arg1, arg2, arg3);
 
+#define        DTRACE_TMR4(name, type1, arg1, arg2, arg3, arg4)                        \
+       DTRACE_PROBE4(__sdt_, name, arg1, arg2, arg3, arg4);
+
+#define        DTRACE_TMR5(name, type1, arg1, type2, arg2, type3, arg3, arg4, arg5)    \
+       DTRACE_PROBE5(__sdt_, name, arg1, arg2, arg3, arg4, arg5);
+
+#define        DTRACE_TMR6(name, type1, arg1, type2, arg2, type3, arg3, arg4, arg5, arg6) \
+       DTRACE_PROBE6(__sdt_, name, arg1, arg2, arg3, arg4, arg5, arg6);
+
 #define        DTRACE_VM(name)                                                 \
        DTRACE_PROBE(__vminfo_, name)
 
index d115f3826fd5af497c53ea6c6787c50bd56493dc..8a24624c011d5a33edcf79302214e70199ebebe3 100644 (file)
@@ -264,6 +264,20 @@ typedef struct task_extmod_info    *task_extmod_info_t;
 /* Always 64-bit in user and kernel */
 #define MACH_TASK_BASIC_INFO     20         /* always 64-bit basic info */
 
+#define TASK_POWER_INFO        21
+struct task_power_info {
+        uint64_t                total_user;
+        uint64_t                total_system;
+        uint64_t                task_interrupt_wakeups;
+        uint64_t                task_platform_idle_wakeups;
+        uint64_t                task_timer_wakeups_bin_1;
+        uint64_t                task_timer_wakeups_bin_2;
+};
+typedef struct task_power_info        task_power_info_data_t;
+typedef struct task_power_info        *task_power_info_t;
+#define TASK_POWER_INFO_COUNT        ((mach_msg_type_number_t) \
+                (sizeof (task_power_info_data_t) / sizeof (natural_t)))
+
 struct mach_task_basic_info {
         mach_vm_size_t  virtual_size;       /* virtual memory size (bytes) */
         mach_vm_size_t  resident_size;      /* resident memory size (bytes) */
index 7d0f15a103ecd8067f49eb7762d0e0aa1d0b0d11..7c91a24690e3f8ac980953d2d4153a873a7cb37e 100644 (file)
@@ -548,6 +548,7 @@ int mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
            struct vnode *dvp, struct vnode *vp, struct componentname *cnp);
 void   mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
            struct vnode *dvp, struct componentname *cnp);
+void   mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags);
 int    vnode_label(struct mount *mp, struct vnode *dvp, struct vnode *vp,
            struct componentname *cnp, int flags, vfs_context_t ctx);
 void   vnode_relabel(struct vnode *vp);
index 91439381351e513d92851cf7bb50674779e469c8..a5c13843e4e666c260e713e8e5ccf5cc16bda1ce 100644 (file)
@@ -6008,6 +6008,23 @@ typedef int mpo_vnode_notify_create_t(
        struct componentname *cnp
 );
 
+/**
+  @brief Inform MAC policies that a vnode has been opened
+  @param cred User credential for the creating process
+  @param vp vnode opened
+  @param label Policy label for the vp
+  @param acc_mode open(2) access mode used
+
+  Inform Mac policies that a vnode have been successfully opened
+  (passing all MAC polices and DAC).
+*/
+typedef void mpo_vnode_notify_open_t(
+       kauth_cred_t cred,
+       struct vnode *vp,
+       struct label *label,
+       int acc_mode
+);
+
 /**
   @brief Inform MAC policies that a vnode has been renamed
   @param cred User credential for the renaming process
@@ -6362,7 +6379,7 @@ struct mac_policy_ops {
        mpo_thread_label_destroy_t              *mpo_thread_label_destroy;
        mpo_system_check_kas_info_t     *mpo_system_check_kas_info;
        mpo_reserved_hook_t                     *mpo_reserved18;
-       mpo_reserved_hook_t                     *mpo_reserved19;
+       mpo_vnode_notify_open_t                 *mpo_vnode_notify_open;
        mpo_reserved_hook_t                     *mpo_reserved20;
        mpo_reserved_hook_t                     *mpo_reserved21;
        mpo_reserved_hook_t                     *mpo_reserved22;
index ba8e50fceaea4b823b1dd68562e0314e65013023..7bf550622ad8488f2f85052bbb805d75f40807d2 100644 (file)
@@ -392,6 +392,19 @@ mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
            dvp, dvp->v_label, cnp);
 }
 
+void
+mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
+{
+       kauth_cred_t cred;
+
+       if (!mac_vnode_enforce || 
+               !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
+               return;
+
+       cred = vfs_context_ucred(ctx);
+       MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
+}
+
 /*
  * Extended attribute 'name' was updated via
  * vn_setxattr() or vn_removexattr().  Allow the