| 844 | } |
| 845 | |
| 846 | void |
| 847 | vpanic(const char *fmt, va_list ap) |
| 848 | { |
| 849 | #ifdef SMP |
| 850 | cpuset_t other_cpus; |
| 851 | #endif |
| 852 | struct thread *td = curthread; |
| 853 | int bootopt, newpanic; |
| 854 | static char buf[256]; |
| 855 | |
| 856 | spinlock_enter(); |
| 857 | |
| 858 | #ifdef SMP |
| 859 | /* |
| 860 | * stop_cpus_hard(other_cpus) should prevent multiple CPUs from |
| 861 | * concurrently entering panic. Only the winner will proceed |
| 862 | * further. |
| 863 | */ |
| 864 | if (panicstr == NULL && !kdb_active) { |
| 865 | other_cpus = all_cpus; |
| 866 | CPU_CLR(PCPU_GET(cpuid), &other_cpus); |
| 867 | stop_cpus_hard(other_cpus); |
| 868 | } |
| 869 | #endif |
| 870 | |
| 871 | /* |
| 872 | * Ensure that the scheduler is stopped while panicking, even if panic |
| 873 | * has been entered from kdb. |
| 874 | */ |
| 875 | td->td_stopsched = 1; |
| 876 | |
| 877 | bootopt = RB_AUTOBOOT; |
| 878 | newpanic = 0; |
| 879 | if (panicstr) |
| 880 | bootopt |= RB_NOSYNC; |
| 881 | else { |
| 882 | bootopt |= RB_DUMP; |
| 883 | panicstr = fmt; |
| 884 | panicked = true; |
| 885 | newpanic = 1; |
| 886 | } |
| 887 | |
| 888 | if (newpanic) { |
| 889 | (void)vsnprintf(buf, sizeof(buf), fmt, ap); |
| 890 | panicstr = buf; |
| 891 | cngrab(); |
| 892 | printf("panic: %s\n", buf); |
| 893 | } else { |
| 894 | printf("panic: "); |
| 895 | vprintf(fmt, ap); |
| 896 | printf("\n"); |
| 897 | } |
| 898 | #ifdef SMP |
| 899 | printf("cpuid = %d\n", PCPU_GET(cpuid)); |
| 900 | #endif |
| 901 | printf("time = %jd\n", (intmax_t )time_second); |
| 902 | #ifdef KDB |
| 903 | if ((newpanic || trace_all_panics) && trace_on_panic) |
no test coverage detected