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