* This tdq is about to idle. Try to steal a thread from another CPU before * choosing the idle thread. */
| 1916 | * choosing the idle thread. |
| 1917 | */ |
| 1918 | static void |
| 1919 | tdq_trysteal(struct tdq *tdq) |
| 1920 | { |
| 1921 | struct cpu_group *cg; |
| 1922 | struct tdq *steal; |
| 1923 | cpuset_t mask; |
| 1924 | int cpu, i; |
| 1925 | |
| 1926 | if (smp_started == 0 || trysteal_limit == 0 || tdq->tdq_cg == NULL) |
| 1927 | return; |
| 1928 | CPU_FILL(&mask); |
| 1929 | CPU_CLR(PCPU_GET(cpuid), &mask); |
| 1930 | /* We don't want to be preempted while we're iterating. */ |
| 1931 | spinlock_enter(); |
| 1932 | TDQ_UNLOCK(tdq); |
| 1933 | for (i = 1, cg = tdq->tdq_cg; ; ) { |
| 1934 | cpu = sched_highest(cg, mask, steal_thresh); |
| 1935 | /* |
| 1936 | * If a thread was added while interrupts were disabled don't |
| 1937 | * steal one here. |
| 1938 | */ |
| 1939 | if (tdq->tdq_load > 0) { |
| 1940 | TDQ_LOCK(tdq); |
| 1941 | break; |
| 1942 | } |
| 1943 | if (cpu == -1) { |
| 1944 | i++; |
| 1945 | cg = cg->cg_parent; |
| 1946 | if (cg == NULL || i > trysteal_limit) { |
| 1947 | TDQ_LOCK(tdq); |
| 1948 | break; |
| 1949 | } |
| 1950 | continue; |
| 1951 | } |
| 1952 | steal = TDQ_CPU(cpu); |
| 1953 | /* |
| 1954 | * The data returned by sched_highest() is stale and |
| 1955 | * the chosen CPU no longer has an eligible thread. |
| 1956 | */ |
| 1957 | if (steal->tdq_load < steal_thresh || |
| 1958 | steal->tdq_transferable == 0) |
| 1959 | continue; |
| 1960 | tdq_lock_pair(tdq, steal); |
| 1961 | /* |
| 1962 | * If we get to this point, unconditonally exit the loop |
| 1963 | * to bound the time spent in the critcal section. |
| 1964 | * |
| 1965 | * If a thread was added while interrupts were disabled don't |
| 1966 | * steal one here. |
| 1967 | */ |
| 1968 | if (tdq->tdq_load > 0) { |
| 1969 | TDQ_UNLOCK(steal); |
| 1970 | break; |
| 1971 | } |
| 1972 | /* |
| 1973 | * The data returned by sched_highest() is stale and |
| 1974 | * the chosen CPU no longer has an eligible thread. |
| 1975 | */ |
no test coverage detected