[BACK]Return to rf_revent.c CVS log [TXT][DIR] Up to [local] / sys / dev / raidframe

Annotation of sys/dev/raidframe/rf_revent.c, Revision 1.1.1.1

1.1       nbrk        1: /*     $OpenBSD: rf_revent.c,v 1.10 2002/12/16 07:01:05 tdeval Exp $   */
                      2: /*     $NetBSD: rf_revent.c,v 1.7 2000/05/30 02:04:29 oster Exp $      */
                      3:
                      4: /*
                      5:  * Copyright (c) 1995 Carnegie-Mellon University.
                      6:  * All rights reserved.
                      7:  *
                      8:  * Author:
                      9:  *
                     10:  * Permission to use, copy, modify and distribute this software and
                     11:  * its documentation is hereby granted, provided that both the copyright
                     12:  * notice and this permission notice appear in all copies of the
                     13:  * software, derivative works or modified versions, and any portions
                     14:  * thereof, and that both notices appear in supporting documentation.
                     15:  *
                     16:  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
                     17:  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
                     18:  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
                     19:  *
                     20:  * Carnegie Mellon requests users of this software to return to
                     21:  *
                     22:  *  Software Distribution Coordinator  or  Software.Distribution@CS.CMU.EDU
                     23:  *  School of Computer Science
                     24:  *  Carnegie Mellon University
                     25:  *  Pittsburgh PA 15213-3890
                     26:  *
                     27:  * any improvements or extensions that they make and grant Carnegie the
                     28:  * rights to redistribute these changes.
                     29:  */
                     30:
                     31: /*
                     32:  * revent.c -- Reconstruction event handling code.
                     33:  */
                     34:
                     35: #include <sys/errno.h>
                     36:
                     37: #include "rf_raid.h"
                     38: #include "rf_revent.h"
                     39: #include "rf_etimer.h"
                     40: #include "rf_general.h"
                     41: #include "rf_freelist.h"
                     42: #include "rf_desc.h"
                     43: #include "rf_shutdown.h"
                     44:
                     45: static RF_FreeList_t *rf_revent_freelist;
                     46: #define        RF_MAX_FREE_REVENT      128
                     47: #define        RF_REVENT_INC             8
                     48: #define        RF_REVENT_INITIAL         8
                     49:
                     50:
                     51:
                     52: #include <sys/proc.h>
                     53: #include <sys/kernel.h>
                     54:
                     55: #define        DO_WAIT(_rc)                                                    \
                     56:        tsleep(&(_rc)->eventQueue, PRIBIO, "RAIDframe eventq", 0)
                     57:
                     58: #define        DO_SIGNAL(_rc)  wakeup(&(_rc)->eventQueue)
                     59:
                     60:
                     61: void rf_ShutdownReconEvent(void *);
                     62:
                     63: RF_ReconEvent_t *GetReconEventDesc(RF_RowCol_t, RF_RowCol_t, void *,
                     64:        RF_Revent_t);
                     65:
                     66: void
                     67: rf_ShutdownReconEvent(void *ignored)
                     68: {
                     69:        RF_FREELIST_DESTROY(rf_revent_freelist, next, (RF_ReconEvent_t *));
                     70: }
                     71:
                     72: int
                     73: rf_ConfigureReconEvent(RF_ShutdownList_t **listp)
                     74: {
                     75:        int rc;
                     76:
                     77:        RF_FREELIST_CREATE(rf_revent_freelist, RF_MAX_FREE_REVENT,
                     78:            RF_REVENT_INC, sizeof(RF_ReconEvent_t));
                     79:        if (rf_revent_freelist == NULL)
                     80:                return (ENOMEM);
                     81:        rc = rf_ShutdownCreate(listp, rf_ShutdownReconEvent, NULL);
                     82:        if (rc) {
                     83:                RF_ERRORMSG3("Unable to add to shutdown list file %s line %d"
                     84:                    " rc=%d\n", __FILE__, __LINE__, rc);
                     85:                rf_ShutdownReconEvent(NULL);
                     86:                return (rc);
                     87:        }
                     88:        RF_FREELIST_PRIME(rf_revent_freelist, RF_REVENT_INITIAL, next,
                     89:            (RF_ReconEvent_t *));
                     90:        return (0);
                     91: }
                     92:
                     93: /*
                     94:  * Returns the next reconstruction event, blocking the calling thread
                     95:  * until one becomes available. Will now return null if it is blocked
                     96:  * or will return an event if it is not.
                     97:  */
                     98:
                     99: RF_ReconEvent_t *
                    100: rf_GetNextReconEvent(RF_RaidReconDesc_t *reconDesc, RF_RowCol_t row,
                    101:     void (*continueFunc) (void *), void *continueArg)
                    102: {
                    103:        RF_Raid_t *raidPtr = reconDesc->raidPtr;
                    104:        RF_ReconCtrl_t *rctrl = raidPtr->reconControl[row];
                    105:        RF_ReconEvent_t *event;
                    106:
                    107:        RF_ASSERT(row >= 0 && row <= raidPtr->numRow);
                    108:        RF_LOCK_MUTEX(rctrl->eq_mutex);
                    109:        /* q NULL and count==0 must be equivalent conditions. */
                    110:        RF_ASSERT((rctrl->eventQueue == NULL) == (rctrl->eq_count == 0));
                    111:
                    112:        rctrl->continueFunc = continueFunc;
                    113:        rctrl->continueArg = continueArg;
                    114:
                    115:        /*
                    116:         * mpsleep timeout value: secs = timo_val/hz. 'ticks' here is
                    117:         * defined as cycle-counter ticks, not softclock ticks.
                    118:         */
                    119:
                    120: #define        MAX_RECON_EXEC_USECS            (100 * 1000)    /* 100 ms */
                    121: #define        RECON_DELAY_MS                  25
                    122: #define        RECON_TIMO                      ((RECON_DELAY_MS * hz) / 1000)
                    123:
                    124:        /*
                    125:         * We are not pre-emptible in the kernel, but we don't want to run
                    126:         * forever. If we run w/o blocking for more than MAX_RECON_EXEC_USECS
                    127:         * delay for RECON_DELAY_MS before continuing. This may murder us with
                    128:         * context switches, so we may need to increase both the
                    129:         * MAX...TICKS and the RECON_DELAY_MS.
                    130:         */
                    131:        if (reconDesc->reconExecTimerRunning) {
                    132:                int status;
                    133:
                    134:                RF_ETIMER_STOP(reconDesc->recon_exec_timer);
                    135:                RF_ETIMER_EVAL(reconDesc->recon_exec_timer);
                    136:                reconDesc->reconExecTicks +=
                    137:                    RF_ETIMER_VAL_US(reconDesc->recon_exec_timer);
                    138:                if (reconDesc->reconExecTicks > reconDesc->maxReconExecTicks)
                    139:                        reconDesc->maxReconExecTicks =
                    140:                            reconDesc->reconExecTicks;
                    141:                if (reconDesc->reconExecTicks >= MAX_RECON_EXEC_USECS) {
                    142:                        /* We've been running too long - sleep. */
                    143: #if RF_RECON_STATS > 0
                    144:                        reconDesc->numReconExecDelays++;
                    145: #endif /* RF_RECON_STATS > 0 */
                    146:                        status = tsleep(&reconDesc->reconExecTicks,
                    147:                            PRIBIO, "recon delay", RECON_TIMO);
                    148:                        RF_ASSERT(status == EWOULDBLOCK);
                    149:                        reconDesc->reconExecTicks = 0;
                    150:                }
                    151:        }
                    152:        while (!rctrl->eventQueue) {
                    153: #if RF_RECON_STATS > 0
                    154:                reconDesc->numReconEventWaits++;
                    155: #endif                         /* RF_RECON_STATS > 0 */
                    156:                DO_WAIT(rctrl);
                    157:                reconDesc->reconExecTicks = 0;  /* We've just waited. */
                    158:        }
                    159:
                    160:        RF_ETIMER_START(reconDesc->recon_exec_timer);
                    161:        reconDesc->reconExecTimerRunning = 1;
                    162:
                    163:        event = rctrl->eventQueue;
                    164:        rctrl->eventQueue = event->next;
                    165:        event->next = NULL;
                    166:        rctrl->eq_count--;
                    167:
                    168:        /* q NULL and count==0 must be equivalent conditions. */
                    169:        RF_ASSERT((rctrl->eventQueue == NULL) == (rctrl->eq_count == 0));
                    170:        RF_UNLOCK_MUTEX(rctrl->eq_mutex);
                    171:        return (event);
                    172: }
                    173:
                    174: /* Enqueues a reconstruction event on the indicated queue. */
                    175: void
                    176: rf_CauseReconEvent(RF_Raid_t *raidPtr, RF_RowCol_t row, RF_RowCol_t col,
                    177:     void *arg, RF_Revent_t type)
                    178: {
                    179:        RF_ReconCtrl_t *rctrl = raidPtr->reconControl[row];
                    180:        RF_ReconEvent_t *event = GetReconEventDesc(row, col, arg, type);
                    181:
                    182:        if (type == RF_REVENT_BUFCLEAR) {
                    183:                RF_ASSERT(col != rctrl->fcol);
                    184:        }
                    185:        RF_ASSERT(row >= 0 && row <= raidPtr->numRow && col >= 0 &&
                    186:            col <= raidPtr->numCol);
                    187:        RF_LOCK_MUTEX(rctrl->eq_mutex);
                    188:        /* q NULL and count==0 must be equivalent conditions. */
                    189:        RF_ASSERT((rctrl->eventQueue == NULL) == (rctrl->eq_count == 0));
                    190:        event->next = rctrl->eventQueue;
                    191:        rctrl->eventQueue = event;
                    192:        rctrl->eq_count++;
                    193:        RF_UNLOCK_MUTEX(rctrl->eq_mutex);
                    194:
                    195:        DO_SIGNAL(rctrl);
                    196: }
                    197:
                    198: /* Allocates and initializes a recon event descriptor. */
                    199: RF_ReconEvent_t *
                    200: GetReconEventDesc(RF_RowCol_t row, RF_RowCol_t col, void *arg, RF_Revent_t type)
                    201: {
                    202:        RF_ReconEvent_t *t;
                    203:
                    204:        RF_FREELIST_GET(rf_revent_freelist, t, next, (RF_ReconEvent_t *));
                    205:        if (t == NULL)
                    206:                return (NULL);
                    207:        t->col = col;
                    208:        t->arg = arg;
                    209:        t->type = type;
                    210:        return (t);
                    211: }
                    212:
                    213: void
                    214: rf_FreeReconEventDesc(RF_ReconEvent_t *event)
                    215: {
                    216:        RF_FREELIST_FREE(rf_revent_freelist, event, next);
                    217: }

CVSweb