]> git.saurik.com Git - apple/xnu.git/blobdiff - osfmk/kern/priority.c
xnu-201.tar.gz
[apple/xnu.git] / osfmk / kern / priority.c
index d88ade25df761f5541508cde9bc8a669ec054396..31caeb97a7881302498266457ec8731b105562e1 100644 (file)
 #include <kern/thread.h>
 #include <kern/processor.h>
 #include <machine/machparam.h>
-#include <kern/sf.h>
-#include <kern/mk_sp.h>        /*** ??? fix so this can be removed ***/
-/*** ??? Should this file be MK SP-specific?  Or is it more general purpose? ***/
-
-
-
-/*
- *     USAGE_THRESHOLD is the amount by which usage must change to
- *     cause a priority shift that moves a thread between run queues.
- */
-
-#ifdef PRI_SHIFT_2
-#if    PRI_SHIFT_2 > 0
-#define        USAGE_THRESHOLD (((1 << PRI_SHIFT) + (1 << PRI_SHIFT_2)) << (2 + SCHED_SHIFT))
-#else  /* PRI_SHIFT_2 > 0 */
-#define        USAGE_THRESHOLD (((1 << PRI_SHIFT) - (1 << -(PRI_SHIFT_2))) << (2 + SCHED_SHIFT))
-#endif /* PRI_SHIFT_2 > 0 */
-#else  /* PRI_SHIFT_2 */
-#define USAGE_THRESHOLD        (1 << (PRI_SHIFT + 2 + SCHED_SHIFT))
-#endif /* PRI_SHIFT_2 */
 
 /*
- *     thread_quantum_update:
+ *     thread_quantum_expire:
  *
  *     Recalculate the quantum and priority for a thread.
- *     The number of ticks that has elapsed since we were last called
- *     is passed as "nticks."
  */
 
 void
-thread_quantum_update(
-       register int            mycpu,
-       register thread_t       thread,
-       int                                     nticks,
-       int                                     state)
+thread_quantum_expire(
+       timer_call_param_t      p0,
+       timer_call_param_t      p1)
 {
-       register int                            quantum;
-       register processor_t            myprocessor;
+       register processor_t            myprocessor = p0;
+       register thread_t                       thread = p1;
        register processor_set_t        pset;
        spl_t                                           s;
 
-       myprocessor = cpu_to_processor(mycpu);
        pset = myprocessor->processor_set;
 
        /*
-        *      Account for thread's utilization of these ticks.
-        *      This assumes that there is *always* a current thread.
-        *      When the processor is idle, it should be the idle thread.
+        *      Update set_quanta for timesharing.
         */
+       pset->set_quanta = pset->machine_quanta[
+                                                       (pset->runq.count > pset->processor_count) ?
+                                                                 pset->processor_count : pset->runq.count];
+
+       s = splsched();
+       thread_lock(thread);
 
        /*
-        *      Update set_quantum and calculate the current quantum.
+        * Check for failsafe trip.
         */
-       pset->set_quantum = pset->machine_quantum[
-                                                       (pset->runq.count > pset->processor_count) ?
-                                                                 pset->processor_count : pset->runq.count];
+       if (!(thread->sched_mode & TH_MODE_TIMESHARE)) {
+               extern uint64_t         max_unsafe_computation;
+               uint64_t                        new_computation;
+
+               new_computation = myprocessor->quantum_end;
+               new_computation -= thread->computation_epoch;
+               if (new_computation + thread->metered_computation >
+                                                                                       max_unsafe_computation) {
+                       extern uint32_t         sched_safe_duration;
+
+                       if (thread->sched_mode & TH_MODE_REALTIME) {
+                               if (thread->depress_priority < 0)
+                                       thread->priority = MINPRI;
+                               else
+                                       thread->depress_priority = MINPRI;
+
+                               thread->safe_mode |= TH_MODE_REALTIME;
+                               thread->sched_mode &= ~TH_MODE_REALTIME;
+                       }
 
-       if (myprocessor->runq.count != 0)
-               quantum = min_quantum;
-       else
-               quantum = pset->set_quantum;
+                       thread->safe_release = sched_tick + sched_safe_duration;
+                       thread->sched_mode |= (TH_MODE_FAILSAFE|TH_MODE_TIMESHARE);
+               }
+       }
                
        /*
         *      Now recompute the priority of the thread if appropriate.
         */
+       if (thread->sched_stamp != sched_tick)
+               update_priority(thread);
+       else
+       if (    (thread->sched_mode & TH_MODE_TIMESHARE)        &&
+                               thread->depress_priority < 0                            ) {
+               thread_timer_delta(thread);
+               thread->sched_usage += thread->sched_delta;
+               thread->sched_delta = 0;
+               compute_my_priority(thread);
+       }
 
-       {
-               s = splsched();
-               thread_lock(thread);
-
-               if (!(thread->policy & (POLICY_TIMESHARE|POLICY_RR|POLICY_FIFO))) {
-                       thread_unlock(thread);
-                       splx(s);
-                       return;
-               }
-
-               if (thread->state&TH_IDLE) {
-                       /* Don't try to time-slice idle threads */
-                       myprocessor->first_quantum = TRUE;
-                       if (thread->sched_stamp != sched_tick)
-                               update_priority(thread);
-                       thread_unlock(thread);
-                       splx(s);
-                       ast_check();
-                       return;
-               }
-
-               myprocessor->quantum -= nticks;
-               /*
-                *      Runtime quantum adjustment.  Use quantum_adj_index
-                *      to avoid synchronizing quantum expirations.
-                */
-               if (    quantum != myprocessor->last_quantum    &&
-                                       pset->processor_count > 1                                       ) {
-                       myprocessor->last_quantum = quantum;
-                       simple_lock(&pset->quantum_adj_lock);
-                       quantum = min_quantum + (pset->quantum_adj_index *
-                                                                                       (quantum - min_quantum)) / 
-                                                                                               (pset->processor_count - 1);
-                       if (++(pset->quantum_adj_index) >= pset->processor_count)
-                               pset->quantum_adj_index = 0;
-                       simple_unlock(&pset->quantum_adj_lock);
-               }
-               if (myprocessor->quantum <= 0) {
-                       if (thread->sched_stamp != sched_tick)
-                               update_priority(thread);
-                       else
-                       if (    thread->policy == POLICY_TIMESHARE              &&
-                                       thread->depress_priority < 0                            ) {
-                               thread_timer_delta(thread);
-                               thread->sched_usage += thread->sched_delta;
-                               thread->sched_delta = 0;
-                               compute_my_priority(thread);
-                       }
+       /*
+        *      This quantum is up, give this thread another.
+        */
+       if (first_quantum(myprocessor))
+               myprocessor->slice_quanta--;
 
-                       /*
-                        *      This quantum is up, give this thread another.
-                        */
-                       myprocessor->first_quantum = FALSE;
-                       if (thread->policy == POLICY_TIMESHARE)
-                               myprocessor->quantum += quantum;
-                       else
-                               myprocessor->quantum += min_quantum;
-               }
-               /*
-                *      Recompute priority if appropriate.
-                */
-               else {
-                   if (thread->sched_stamp != sched_tick)
-                               update_priority(thread);
-                   else
-                       if (    thread->policy == POLICY_TIMESHARE              &&
-                                       thread->depress_priority < 0                            ) {
-                               thread_timer_delta(thread);
-                               if (thread->sched_delta >= USAGE_THRESHOLD) {
-                                   thread->sched_usage +=      thread->sched_delta;
-                                   thread->sched_delta = 0;
-                                   compute_my_priority(thread);
-                               }
-                       }
-               }
+       thread->current_quantum = (thread->sched_mode & TH_MODE_REALTIME)?
+                                                                       thread->realtime.computation: std_quantum;
+       myprocessor->quantum_end += thread->current_quantum;
+       timer_call_enter1(&myprocessor->quantum_timer,
+                                                       thread, myprocessor->quantum_end);
 
-               thread_unlock(thread);
-               splx(s);
+       thread_unlock(thread);
+       splx(s);
 
-               /*
-                * Check for and schedule ast if needed.
-                */
-               ast_check();
-       }
+       /*
+        * Check for and schedule ast if needed.
+        */
+       ast_check();
 }