Home | History | Annotate | Line # | Download | only in raidframe
rf_fifo.c revision 1.2
      1 /*	$NetBSD: rf_fifo.c,v 1.2 1999/01/26 02:33:57 oster Exp $	*/
      2 /*
      3  * Copyright (c) 1995 Carnegie-Mellon University.
      4  * All rights reserved.
      5  *
      6  * Author: Mark Holland
      7  *
      8  * Permission to use, copy, modify and distribute this software and
      9  * its documentation is hereby granted, provided that both the copyright
     10  * notice and this permission notice appear in all copies of the
     11  * software, derivative works or modified versions, and any portions
     12  * thereof, and that both notices appear in supporting documentation.
     13  *
     14  * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
     15  * CONDITION.  CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
     16  * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
     17  *
     18  * Carnegie Mellon requests users of this software to return to
     19  *
     20  *  Software Distribution Coordinator  or  Software.Distribution (at) CS.CMU.EDU
     21  *  School of Computer Science
     22  *  Carnegie Mellon University
     23  *  Pittsburgh PA 15213-3890
     24  *
     25  * any improvements or extensions that they make and grant Carnegie the
     26  * rights to redistribute these changes.
     27  */
     28 
     29 /***************************************************
     30  *
     31  * rf_fifo.c --  prioritized fifo queue code.
     32  * There are only two priority levels: hi and lo.
     33  *
     34  * Aug 4, 1994, adapted from raidSim version (MCH)
     35  *
     36  ***************************************************/
     37 
     38 #include "rf_types.h"
     39 #include "rf_alloclist.h"
     40 #include "rf_stripelocks.h"
     41 #include "rf_layout.h"
     42 #include "rf_diskqueue.h"
     43 #include "rf_fifo.h"
     44 #include "rf_debugMem.h"
     45 #include "rf_general.h"
     46 #include "rf_threadid.h"
     47 #include "rf_options.h"
     48 
     49 /* just malloc a header, zero it (via calloc), and return it */
     50 /*ARGSUSED*/
     51 void *rf_FifoCreate(sectPerDisk, clList, listp)
     52   RF_SectorCount_t      sectPerDisk;
     53   RF_AllocListElem_t   *clList;
     54   RF_ShutdownList_t   **listp;
     55 {
     56   RF_FifoHeader_t *q;
     57 
     58   RF_CallocAndAdd(q, 1, sizeof(RF_FifoHeader_t), (RF_FifoHeader_t *), clList);
     59   q->hq_count = q->lq_count = 0;
     60   return((void *)q);
     61 }
     62 
     63 void rf_FifoEnqueue(q_in, elem, priority)
     64   void                *q_in;
     65   RF_DiskQueueData_t  *elem;
     66   int                  priority;
     67 {
     68   RF_FifoHeader_t *q = (RF_FifoHeader_t *)q_in;
     69 
     70   RF_ASSERT(priority == RF_IO_NORMAL_PRIORITY || priority == RF_IO_LOW_PRIORITY);
     71 
     72   elem->next = NULL;
     73   if (priority == RF_IO_NORMAL_PRIORITY) {
     74     if (!q->hq_tail) {
     75       RF_ASSERT(q->hq_count == 0 && q->hq_head == NULL);
     76       q->hq_head = q->hq_tail = elem;
     77     } else {
     78       RF_ASSERT(q->hq_count != 0 && q->hq_head != NULL);
     79       q->hq_tail->next = elem;
     80       q->hq_tail = elem;
     81     }
     82     q->hq_count++;
     83   }
     84   else {
     85     RF_ASSERT(elem->next == NULL);
     86     if (rf_fifoDebug) {
     87       int tid;
     88       rf_get_threadid(tid);
     89       printf("[%d] fifo: ENQ lopri\n", tid);
     90     }
     91     if (!q->lq_tail) {
     92       RF_ASSERT(q->lq_count == 0 && q->lq_head == NULL);
     93       q->lq_head = q->lq_tail = elem;
     94     } else {
     95       RF_ASSERT(q->lq_count != 0 && q->lq_head != NULL);
     96       q->lq_tail->next = elem;
     97       q->lq_tail = elem;
     98     }
     99     q->lq_count++;
    100   }
    101   if ((q->hq_count + q->lq_count)!= elem->queue->queueLength) {
    102 	  printf("Queue lengths differ!: %d %d %d\n",
    103 		 q->hq_count, q->lq_count, (int)elem->queue->queueLength);
    104 	  printf("%d %d %d %d\n",
    105 		 (int)elem->queue->numOutstanding,
    106 		 (int)elem->queue->maxOutstanding,
    107 		 (int)elem->queue->row,
    108 		 (int)elem->queue->col);
    109   }
    110   RF_ASSERT((q->hq_count + q->lq_count) == elem->queue->queueLength);
    111 }
    112 
    113 RF_DiskQueueData_t *rf_FifoDequeue(q_in)
    114   void  *q_in;
    115 {
    116   RF_FifoHeader_t *q = (RF_FifoHeader_t *) q_in;
    117   RF_DiskQueueData_t *nd;
    118 
    119   RF_ASSERT(q);
    120   if (q->hq_head) {
    121     RF_ASSERT(q->hq_count != 0 && q->hq_tail != NULL);
    122     nd = q->hq_head; q->hq_head = q->hq_head->next;
    123     if (!q->hq_head) q->hq_tail = NULL;
    124     nd->next = NULL;
    125     q->hq_count--;
    126   } else if (q->lq_head) {
    127     RF_ASSERT(q->lq_count != 0 && q->lq_tail != NULL);
    128     nd = q->lq_head; q->lq_head = q->lq_head->next;
    129     if (!q->lq_head) q->lq_tail = NULL;
    130     nd->next = NULL;
    131     q->lq_count--;
    132     if (rf_fifoDebug) {
    133       int tid;
    134       rf_get_threadid(tid);
    135       printf("[%d] fifo: DEQ lopri %lx\n", tid, (long)nd);
    136     }
    137   } else {
    138     RF_ASSERT(q->hq_count == 0 && q->lq_count == 0 && q->hq_tail == NULL && q->lq_tail == NULL);
    139     nd = NULL;
    140   }
    141   return(nd);
    142 }
    143 
    144 /* This never gets used!! No loss (I hope) if we don't include it... GO */
    145 #if !defined(__NetBSD__) && !defined(_KERNEL)
    146 
    147 static RF_DiskQueueData_t *n_in_q(headp, tailp, countp, n, deq)
    148   RF_DiskQueueData_t  **headp;
    149   RF_DiskQueueData_t  **tailp;
    150   int                  *countp;
    151   int                   n;
    152   int                   deq;
    153 {
    154   RF_DiskQueueData_t *r, *s;
    155   int i;
    156 
    157   for(s=NULL,i=n,r=*headp;r;s=r,r=r->next) {
    158     if (i == 0)
    159       break;
    160     i--;
    161   }
    162   RF_ASSERT(r != NULL);
    163   if (deq == 0)
    164     return(r);
    165   if (s) {
    166     s->next = r->next;
    167   }
    168   else {
    169     *headp = r->next;
    170   }
    171   if (*tailp == r)
    172     *tailp = s;
    173   (*countp)--;
    174   return(r);
    175 }
    176 #endif
    177 
    178 #if !defined(KERNEL) && RF_INCLUDE_QUEUE_RANDOM > 0
    179 RF_DiskQueueData_t *rf_RandomPeek(q_in)
    180   void  *q_in;
    181 {
    182   RF_FifoHeader_t *q = (RF_FifoHeader_t *) q_in;
    183   RF_DiskQueueData_t *req;
    184   int n;
    185 
    186   if (q->hq_head) {
    187     n = q->rval % q->hq_count;
    188     req = n_in_q(&q->hq_head, &q->hq_tail, &q->hq_count, n, 0);
    189   }
    190   else {
    191     RF_ASSERT(q->hq_count == 0);
    192     if (q->lq_head == NULL) {
    193       RF_ASSERT(q->lq_count == 0);
    194       return(NULL);
    195     }
    196     n = q->rval % q->lq_count;
    197     req = n_in_q(&q->lq_head, &q->lq_tail, &q->lq_count, n, 0);
    198   }
    199   RF_ASSERT((q->hq_count + q->lq_count) == req->queue->queueLength);
    200   RF_ASSERT(req != NULL);
    201   return(req);
    202 }
    203 
    204 RF_DiskQueueData_t *rf_RandomDequeue(q_in)
    205   void  *q_in;
    206 {
    207   RF_FifoHeader_t *q = (RF_FifoHeader_t *) q_in;
    208   RF_DiskQueueData_t *req;
    209   int n;
    210 
    211   if (q->hq_head) {
    212     n = q->rval % q->hq_count;
    213     q->rval = (long)RF_STATIC_RANDOM();
    214     req = n_in_q(&q->hq_head, &q->hq_tail, &q->hq_count, n, 1);
    215   }
    216   else {
    217     RF_ASSERT(q->hq_count == 0);
    218     if (q->lq_head == NULL) {
    219       RF_ASSERT(q->lq_count == 0);
    220       return(NULL);
    221     }
    222     n = q->rval % q->lq_count;
    223     q->rval = (long)RF_STATIC_RANDOM();
    224     req = n_in_q(&q->lq_head, &q->lq_tail, &q->lq_count, n, 1);
    225   }
    226   RF_ASSERT((q->hq_count + q->lq_count) == (req->queue->queueLength-1));
    227   return(req);
    228 }
    229 #endif /* !KERNEL && RF_INCLUDE_QUEUE_RANDOM > 0 */
    230 
    231 /* Return ptr to item at head of queue.  Used to examine request
    232  * info without actually dequeueing the request.
    233  */
    234 RF_DiskQueueData_t *rf_FifoPeek(void *q_in)
    235 {
    236   RF_DiskQueueData_t *headElement = NULL;
    237   RF_FifoHeader_t *q = (RF_FifoHeader_t *) q_in;
    238 
    239   RF_ASSERT(q);
    240   if (q->hq_head)
    241     headElement = q->hq_head;
    242   else if (q->lq_head)
    243     headElement = q->lq_head;
    244   return(headElement);
    245 }
    246 
    247 /* We sometimes need to promote a low priority access to a regular priority access.
    248  * Currently, this is only used when the user wants to write a stripe which is currently
    249  * under reconstruction.
    250  * This routine will promote all accesses tagged with the indicated parityStripeID from
    251  * the low priority queue to the end of the normal priority queue.
    252  * We assume the queue is locked upon entry.
    253  */
    254 int rf_FifoPromote(q_in, parityStripeID, which_ru)
    255   void               *q_in;
    256   RF_StripeNum_t      parityStripeID;
    257   RF_ReconUnitNum_t   which_ru;
    258 {
    259   RF_FifoHeader_t *q = (RF_FifoHeader_t *) q_in;
    260   RF_DiskQueueData_t *lp = q->lq_head, *pt = NULL;  /* lp = lo-pri queue pointer, pt = trailer */
    261   int retval = 0;
    262 
    263   while (lp) {
    264 
    265     /* search for the indicated parity stripe in the low-pri queue */
    266     if (lp->parityStripeID == parityStripeID && lp->which_ru == which_ru) {
    267       /*printf("FifoPromote:  promoting access for psid %ld\n",parityStripeID);*/
    268       if (pt) pt->next = lp->next;                              /* delete an entry other than the first */
    269       else q->lq_head = lp->next;                               /* delete the head entry */
    270 
    271       if (!q->lq_head) q->lq_tail = NULL;                       /* we deleted the only entry */
    272       else if (lp == q->lq_tail) q->lq_tail = pt;               /* we deleted the tail entry */
    273 
    274       lp->next = NULL;
    275       q->lq_count--;
    276 
    277       if (q->hq_tail) {q->hq_tail->next = lp; q->hq_tail = lp;} /* append to hi-priority queue */
    278       else {q->hq_head = q->hq_tail = lp;}
    279       q->hq_count++;
    280 
    281       /*UpdateShortestSeekFinishTimeForced(lp->requestPtr, lp->diskState);*/     /* deal with this later, if ever */
    282 
    283       lp = (pt) ? pt->next : q->lq_head;		       /* reset low-pri pointer and continue */
    284       retval++;
    285 
    286     } else {pt = lp; lp = lp->next;}
    287   }
    288 
    289   /* sanity check.  delete this if you ever put more than one entry in the low-pri queue */
    290   RF_ASSERT(retval == 0 || retval == 1);
    291   if (rf_fifoDebug) {
    292     int tid;
    293     rf_get_threadid(tid);
    294     printf("[%d] fifo: promote %d\n", tid, retval);
    295   }
    296   return(retval);
    297 }
    298