root/dev/raidframe/rf_revent.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rf_ShutdownReconEvent
  2. rf_ConfigureReconEvent
  3. rf_GetNextReconEvent
  4. rf_CauseReconEvent
  5. GetReconEventDesc
  6. rf_FreeReconEventDesc

    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 }

/* [<][>][^][v][top][bottom][index][help] */