Annotation of sys/arch/i386/i386/db_mp.c, Revision 1.1
1.1 ! nbrk 1: /* $OpenBSD: db_mp.c,v 1.4 2004/07/20 20:18:53 art Exp $ */
! 2:
! 3: /*
! 4: * Copyright (c) 2003, 2004 Andreas Gunnarsson <andreas@openbsd.org>
! 5: *
! 6: * Permission to use, copy, modify, and distribute this software for any
! 7: * purpose with or without fee is hereby granted, provided that the above
! 8: * copyright notice and this permission notice appear in all copies.
! 9: *
! 10: * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
! 11: * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
! 12: * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
! 13: * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
! 14: * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
! 15: * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
! 16: * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
! 17: */
! 18:
! 19: #include <sys/types.h>
! 20: #include <sys/simplelock.h>
! 21:
! 22: #include <machine/db_machdep.h>
! 23: #include <sys/mutex.h>
! 24:
! 25: #include <ddb/db_output.h>
! 26:
! 27: struct mutex ddb_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
! 28:
! 29: volatile int ddb_state = DDB_STATE_NOT_RUNNING; /* protected by ddb_mp_mutex */
! 30: volatile cpuid_t ddb_active_cpu; /* protected by ddb_mp_mutex */
! 31:
! 32: extern volatile boolean_t db_switch_cpu;
! 33: extern volatile long db_switch_to_cpu;
! 34:
! 35: /*
! 36: * All processors wait in db_enter_ddb() (unless explicitly started from
! 37: * ddb) but only one owns ddb. If the current processor should own ddb,
! 38: * db_enter_ddb() returns 1. If the current processor should keep
! 39: * executing as usual (if ddb is exited or the processor is explicitly
! 40: * started), db_enter_ddb returns 0.
! 41: * If this is the first CPU entering ddb, db_enter_ddb() will stop all
! 42: * other CPUs by sending IPIs.
! 43: */
! 44: int
! 45: db_enter_ddb()
! 46: {
! 47: int i;
! 48:
! 49: mtx_enter(&ddb_mp_mutex);
! 50:
! 51: /* If we are first in, grab ddb and stop all other CPUs */
! 52: if (ddb_state == DDB_STATE_NOT_RUNNING) {
! 53: ddb_active_cpu = cpu_number();
! 54: ddb_state = DDB_STATE_RUNNING;
! 55: curcpu()->ci_ddb_paused = CI_DDB_INDDB;
! 56: mtx_leave(&ddb_mp_mutex);
! 57: for (i = 0; i < I386_MAXPROCS; i++) {
! 58: if (cpu_info[i] != NULL && i != cpu_number() &&
! 59: cpu_info[i]->ci_ddb_paused != CI_DDB_STOPPED) {
! 60: cpu_info[i]->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 61: i386_send_ipi(cpu_info[i], I386_IPI_DDB);
! 62: }
! 63: }
! 64: return (1);
! 65: }
! 66:
! 67: /* Leaving ddb completely. Start all other CPUs and return 0 */
! 68: if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_EXITING) {
! 69: for (i = 0; i < I386_MAXPROCS; i++) {
! 70: if (cpu_info[i] != NULL) {
! 71: cpu_info[i]->ci_ddb_paused = CI_DDB_RUNNING;
! 72: }
! 73: }
! 74: mtx_leave(&ddb_mp_mutex);
! 75: return (0);
! 76: }
! 77:
! 78: /* We're switching to another CPU. db_ddbproc_cmd() has made sure
! 79: * it is waiting for ddb, we just have to set ddb_active_cpu. */
! 80: if (ddb_active_cpu == cpu_number() && db_switch_cpu) {
! 81: curcpu()->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 82: db_switch_cpu = 0;
! 83: ddb_active_cpu = db_switch_to_cpu;
! 84: cpu_info[db_switch_to_cpu]->ci_ddb_paused = CI_DDB_ENTERDDB;
! 85: }
! 86:
! 87: /* Wait until we should enter ddb or resume */
! 88: while (ddb_active_cpu != cpu_number() &&
! 89: curcpu()->ci_ddb_paused != CI_DDB_RUNNING) {
! 90: if (curcpu()->ci_ddb_paused == CI_DDB_SHOULDSTOP)
! 91: curcpu()->ci_ddb_paused = CI_DDB_STOPPED;
! 92: mtx_leave(&ddb_mp_mutex);
! 93:
! 94: /* Busy wait without locking, we'll confirm with lock later */
! 95: while (ddb_active_cpu != cpu_number() &&
! 96: curcpu()->ci_ddb_paused != CI_DDB_RUNNING)
! 97: ; /* Do nothing */
! 98:
! 99: mtx_enter(&ddb_mp_mutex);
! 100: }
! 101:
! 102: /* Either enter ddb or exit */
! 103: if (ddb_active_cpu == cpu_number() && ddb_state == DDB_STATE_RUNNING) {
! 104: curcpu()->ci_ddb_paused = CI_DDB_INDDB;
! 105: mtx_leave(&ddb_mp_mutex);
! 106: return (1);
! 107: } else {
! 108: mtx_leave(&ddb_mp_mutex);
! 109: return (0);
! 110: }
! 111: }
! 112:
! 113: void
! 114: db_startcpu(int cpu)
! 115: {
! 116: if (cpu != cpu_number() && cpu_info[cpu] != NULL) {
! 117: mtx_enter(&ddb_mp_mutex);
! 118: cpu_info[cpu]->ci_ddb_paused = CI_DDB_RUNNING;
! 119: mtx_leave(&ddb_mp_mutex);
! 120: }
! 121: }
! 122:
! 123: void
! 124: db_stopcpu(int cpu)
! 125: {
! 126: mtx_enter(&ddb_mp_mutex);
! 127: if (cpu != cpu_number() && cpu_info[cpu] != NULL &&
! 128: cpu_info[cpu]->ci_ddb_paused != CI_DDB_STOPPED) {
! 129: cpu_info[cpu]->ci_ddb_paused = CI_DDB_SHOULDSTOP;
! 130: mtx_leave(&ddb_mp_mutex);
! 131: i386_send_ipi(cpu_info[cpu], I386_IPI_DDB);
! 132: } else {
! 133: mtx_leave(&ddb_mp_mutex);
! 134: }
! 135: }
! 136:
! 137: void
! 138: i386_ipi_db(struct cpu_info *ci)
! 139: {
! 140: Debugger();
! 141: }
CVSweb