[BACK]Return to mp_setperf.c CVS log [TXT][DIR] Up to [local] / sys / arch / i386 / i386

Annotation of sys/arch/i386/i386/mp_setperf.c, Revision 1.1.1.1

1.1       nbrk        1: /* $OpenBSD: mp_setperf.c,v 1.2 2007/05/01 04:18:32 gwk Exp $ */
                      2: /*
                      3:  * Copyright (c) 2007 Gordon Willem Klok <gwk@openbsd.org>
                      4:  *
                      5:  * Permission to use, copy, modify, and distribute this software for any
                      6:  * purpose with or without fee is hereby granted, provided that the above
                      7:  * copyright notice and this permission notice appear in all copies.
                      8:  *
                      9:  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
                     10:  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
                     11:  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
                     12:  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
                     13:  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
                     14:  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
                     15:  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
                     16:  */
                     17:
                     18: #include <sys/param.h>
                     19: #include <sys/systm.h>
                     20: #include <sys/sysctl.h>
                     21: #include <sys/mutex.h>
                     22:
                     23: #include <machine/cpu.h>
                     24:
                     25: #include <machine/intr.h>
                     26:
                     27: struct mutex setperf_mp_mutex = MUTEX_INITIALIZER(IPL_HIGH);
                     28:
                     29: /* underlying setperf mechanism e.g. k8_powernow_setperf() */
                     30: void (*ul_setperf)(int);
                     31:
                     32: #define MP_SETPERF_STEADY      0       /* steady state - normal operation */
                     33: #define MP_SETPERF_INTRANSIT   1       /* in transition */
                     34: #define MP_SETPERF_PROCEED     2       /* proceed with transition */
                     35: #define MP_SETPERF_FINISH      3       /* return from IPI */
                     36:
                     37:
                     38: /* protected by setperf_mp_mutex */
                     39: volatile int mp_setperf_state = MP_SETPERF_STEADY;
                     40: volatile int mp_perflevel;
                     41:
                     42: void mp_setperf(int);
                     43:
                     44: void
                     45: mp_setperf(int level)
                     46: {
                     47:        CPU_INFO_ITERATOR cii;
                     48:        struct cpu_info *ci;
                     49:        int notready, s;
                     50:
                     51:        if (mp_setperf_state == MP_SETPERF_STEADY) {
                     52:                mtx_enter(&setperf_mp_mutex);
                     53:                mp_perflevel = level;
                     54:
                     55:                curcpu()->ci_setperf_state = CI_SETPERF_INTRANSIT;
                     56:                /* ask all other processors to drop what they are doing */
                     57:                CPU_INFO_FOREACH(cii, ci) {
                     58:                        if (ci->ci_setperf_state != CI_SETPERF_INTRANSIT) {
                     59:                                ci->ci_setperf_state =
                     60:                                    CI_SETPERF_SHOULDSTOP;
                     61:                                i386_send_ipi(ci, I386_IPI_SETPERF);
                     62:                        }
                     63:                }
                     64:
                     65:
                     66:                /* Loop until all processors report ready */
                     67:                do {
                     68:                        CPU_INFO_FOREACH(cii, ci) {
                     69:                                if ((notready = (ci->ci_setperf_state
                     70:                                    != CI_SETPERF_INTRANSIT)))
                     71:                                        break;
                     72:                        }
                     73:                } while (notready);
                     74:
                     75:                mp_setperf_state = MP_SETPERF_PROCEED; /* release the hounds */
                     76:
                     77:                s = splipi();
                     78:
                     79:                ul_setperf(mp_perflevel);
                     80:
                     81:                splx(s);
                     82:
                     83:                curcpu()->ci_setperf_state = CI_SETPERF_DONE;
                     84:                /* Loop until all processors report done */
                     85:                do {
                     86:                        CPU_INFO_FOREACH(cii, ci) {
                     87:                                if ((notready = (ci->ci_setperf_state
                     88:                                    != CI_SETPERF_DONE)))
                     89:                                        break;
                     90:                        }
                     91:                } while (notready);
                     92:
                     93:                mp_setperf_state = MP_SETPERF_FINISH;
                     94:                /* delay a little for potential straglers */
                     95:                DELAY(2);
                     96:                curcpu()->ci_setperf_state = CI_SETPERF_READY;
                     97:                mp_setperf_state = MP_SETPERF_STEADY; /* restore normallity */
                     98:                mtx_leave(&setperf_mp_mutex);
                     99:        }
                    100:
                    101: }
                    102:
                    103: void
                    104: i386_setperf_ipi(struct cpu_info *ci)
                    105: {
                    106:
                    107:        if (ci->ci_setperf_state == CI_SETPERF_SHOULDSTOP)
                    108:                ci->ci_setperf_state = CI_SETPERF_INTRANSIT;
                    109:
                    110:        while (mp_setperf_state != MP_SETPERF_PROCEED)
                    111:                ;
                    112:
                    113:        ul_setperf(mp_perflevel);
                    114:
                    115:        ci->ci_setperf_state = CI_SETPERF_DONE;
                    116:
                    117:        while (mp_setperf_state != MP_SETPERF_FINISH)
                    118:                ;
                    119:        ci->ci_setperf_state = CI_SETPERF_READY;
                    120: }
                    121:
                    122: void
                    123: mp_setperf_init()
                    124: {
                    125:        CPU_INFO_ITERATOR cii;
                    126:        struct cpu_info *ci;
                    127:
                    128:
                    129:        if (!cpu_setperf)
                    130:                return;
                    131:        ul_setperf = cpu_setperf;
                    132:
                    133:        cpu_setperf = mp_setperf;
                    134:
                    135:        CPU_INFO_FOREACH(cii, ci) {
                    136:                ci->ci_setperf_state = CI_SETPERF_READY;
                    137:        }
                    138:        mtx_init(&setperf_mp_mutex, IPL_HIGH);
                    139: }

CVSweb