xref: /netbsd-src/sys/dev/raidframe/rf_threadstuff.h (revision dc306354b0b29af51801a7632f1e95265a68cd81)
1 /*	$NetBSD: rf_threadstuff.h,v 1.1 1998/11/13 04:20:35 oster Exp $	*/
2 /*
3  * Copyright (c) 1995 Carnegie-Mellon University.
4  * All rights reserved.
5  *
6  * Author: Mark Holland, Daniel Stodolsky, Jim Zelenka
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@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  * threadstuff.h -- definitions for threads, locks, and synchronization
31  *
32  * The purpose of this file is provide some illusion of portability.
33  * If the functions below can be implemented with the same semantics on
34  * some new system, then at least the synchronization and thread control
35  * part of the code should not require modification to port to a new machine.
36  * the only other place where the pthread package is explicitly used is
37  * threadid.h
38  *
39  * this file should be included above stdio.h to get some necessary defines.
40  *
41  */
42 
43 /* :
44  * Log: rf_threadstuff.h,v
45  * Revision 1.38  1996/08/12 22:37:47  jimz
46  * add AIX stuff for user driver
47  *
48  * Revision 1.37  1996/08/11  00:47:09  jimz
49  * make AIX friendly
50  *
51  * Revision 1.36  1996/07/23  22:06:59  jimz
52  * add rf_destroy_threadgroup
53  *
54  * Revision 1.35  1996/07/23  21:31:16  jimz
55  * add init_threadgroup
56  *
57  * Revision 1.34  1996/07/18  22:57:14  jimz
58  * port simulator to AIX
59  *
60  * Revision 1.33  1996/07/15  17:22:18  jimz
61  * nit-pick code cleanup
62  * resolve stdlib problems on DEC OSF
63  *
64  * Revision 1.32  1996/06/17  03:01:11  jimz
65  * get rid of JOIN stuff
66  *
67  * Revision 1.31  1996/06/14  23:15:38  jimz
68  * attempt to deal with thread GC problem
69  *
70  * Revision 1.30  1996/06/11  18:12:36  jimz
71  * get rid of JOIN operations
72  * use ThreadGroup stuff instead
73  * fix some allocation/deallocation and sync bugs
74  *
75  * Revision 1.29  1996/06/11  13:48:10  jimz
76  * make kernel RF_THREAD_CREATE give back happier return vals
77  *
78  * Revision 1.28  1996/06/10  16:40:01  jimz
79  * break user-level stuff out into lib+apps
80  *
81  * Revision 1.27  1996/06/10  11:55:47  jimz
82  * Straightened out some per-array/not-per-array distinctions, fixed
83  * a couple bugs related to confusion. Added shutdown lists. Removed
84  * layout shutdown function (now subsumed by shutdown lists).
85  *
86  * Revision 1.26  1996/06/09  02:36:46  jimz
87  * lots of little crufty cleanup- fixup whitespace
88  * issues, comment #ifdefs, improve typing in some
89  * places (esp size-related)
90  *
91  * Revision 1.25  1996/06/05  18:06:02  jimz
92  * Major code cleanup. The Great Renaming is now done.
93  * Better modularity. Better typing. Fixed a bunch of
94  * synchronization bugs. Made a lot of global stuff
95  * per-desc or per-array. Removed dead code.
96  *
97  * Revision 1.24  1996/05/30  11:29:41  jimz
98  * Numerous bug fixes. Stripe lock release code disagreed with the taking code
99  * about when stripes should be locked (I made it consistent: no parity, no lock)
100  * There was a lot of extra serialization of I/Os which I've removed- a lot of
101  * it was to calculate values for the cache code, which is no longer with us.
102  * More types, function, macro cleanup. Added code to properly quiesce the array
103  * on shutdown. Made a lot of stuff array-specific which was (bogusly) general
104  * before. Fixed memory allocation, freeing bugs.
105  *
106  * Revision 1.23  1996/05/20  19:31:54  jimz
107  * add atomic debug (mutex and cond leak finder) stuff
108  *
109  * Revision 1.22  1996/05/20  16:24:49  jimz
110  * get happy in simulator
111  *
112  * Revision 1.21  1996/05/20  16:15:07  jimz
113  * switch to rf_{mutex,cond}_{init,destroy}
114  *
115  * Revision 1.20  1996/05/18  19:51:34  jimz
116  * major code cleanup- fix syntax, make some types consistent,
117  * add prototypes, clean out dead code, et cetera
118  *
119  * Revision 1.19  1996/05/09  17:16:53  jimz
120  * correct arg to JOIN_THREAD
121  *
122  * Revision 1.18  1995/12/12  18:10:06  jimz
123  * MIN -> RF_MIN, MAX -> RF_MAX, ASSERT -> RF_ASSERT
124  * fix 80-column brain damage in comments
125  *
126  * Revision 1.17  1995/12/06  15:15:21  root
127  * added copyright info
128  *
129  */
130 
131 #ifndef _RF__RF_THREADSTUFF_H_
132 #define _RF__RF_THREADSTUFF_H_
133 
134 #include "rf_types.h"
135 
136 #define rf_create_managed_mutex(a,b) _rf_create_managed_mutex(a,b,__FILE__,__LINE__)
137 #define rf_create_managed_cond(a,b) _rf_create_managed_cond(a,b,__FILE__,__LINE__)
138 #define rf_init_managed_threadgroup(a,b) _rf_init_managed_threadgroup(a,b,__FILE__,__LINE__)
139 #define rf_init_threadgroup(a) _rf_init_threadgroup(a,__FILE__,__LINE__)
140 #define rf_destroy_threadgroup(a) _rf_destroy_threadgroup(a,__FILE__,__LINE__)
141 
142 int _rf_init_threadgroup(RF_ThreadGroup_t *g, char *file, int line);
143 int _rf_destroy_threadgroup(RF_ThreadGroup_t *g, char *file, int line);
144 int _rf_init_managed_threadgroup(RF_ShutdownList_t **listp,
145 	RF_ThreadGroup_t *g, char *file, int line);
146 
147 #ifndef SIMULATE /* will null all this calls */
148 #ifndef KERNEL
149 
150 #if defined(__osf__) || defined(AIX)
151 #include <pthread.h>
152 #endif /* __osf__ || AIX */
153 
154 #define RF_DEBUG_ATOMIC 0
155 
156 #if RF_DEBUG_ATOMIC > 0
157 #define RF_ATENT_M 1
158 #define RF_ATENT_C 2
159 typedef struct RF_ATEnt_s RF_ATEnt_t;
160 struct RF_ATEnt_s {
161 	char            *file;
162 	int              line;
163 	pthread_mutex_t  m;
164 	pthread_cond_t   c;
165 	int              type;
166 	int              otype;
167 	RF_ATEnt_t      *next;
168 	RF_ATEnt_t      *prev;
169 };
170 
171 #define RF_DECLARE_MUTEX(_m_)                RF_ATEnt_t *_m_;
172 #define RF_DECLARE_STATIC_MUTEX(_m_)  static RF_ATEnt_t *_m_;
173 #define RF_DECLARE_EXTERN_MUTEX(_m_)  extern RF_ATEnt_t *_m_;
174 #define RF_DECLARE_COND(_c_)                 RF_ATEnt_t *_c_;
175 #define RF_DECLARE_STATIC_COND(_c_)   static RF_ATEnt_t *_c_;
176 #define RF_DECLARE_EXTERN_COND(_c_)   extern RF_ATEnt_t *_c_;
177 
178 int _rf_mutex_init(RF_ATEnt_t **m, char *file, int line);
179 int _rf_mutex_destroy(RF_ATEnt_t **m, char *file, int line);
180 int _rf_cond_init(RF_ATEnt_t **c, char *file, int line);
181 int _rf_cond_destroy(RF_ATEnt_t **c, char *file, int line);
182 void rf_atent_init(void);
183 void rf_atent_shutdown(void);
184 
185 #define rf_mutex_init(_m_) _rf_mutex_init(_m_,__FILE__,__LINE__)
186 #define rf_mutex_destroy(_m_) _rf_mutex_destroy(_m_,__FILE__,__LINE__)
187 #define rf_cond_init(_m_) _rf_cond_init(_m_,__FILE__,__LINE__)
188 #define rf_cond_destroy(_m_) _rf_cond_destroy(_m_,__FILE__,__LINE__)
189 
190 #define RF_LOCK_MUTEX(_a_)     {RF_ASSERT((_a_)->type == RF_ATENT_M); pthread_mutex_lock(&((_a_)->m));}
191 #define RF_UNLOCK_MUTEX(_a_)   {RF_ASSERT((_a_)->type == RF_ATENT_M); pthread_mutex_unlock(&((_a_)->m));}
192 
193 #define RF_WAIT_COND(_c_,_m_)  { \
194 	RF_ASSERT((_c_)->type == RF_ATENT_C); \
195 	RF_ASSERT((_m_)->type == RF_ATENT_M); \
196 	pthread_cond_wait( &((_c_)->c), &((_m_)->m) ); \
197 }
198 #define RF_SIGNAL_COND(_c_)    {RF_ASSERT((_c_)->type == RF_ATENT_C); pthread_cond_signal( &((_c_)->c));}
199 #define RF_BROADCAST_COND(_c_) {RF_ASSERT((_c_)->type == RF_ATENT_C); pthread_cond_broadcast(&((_c_)->c));}
200 
201 #else /* RF_DEBUG_ATOMIC > 0 */
202 
203 /* defining these as macros allows us to NULL them out in the kernel */
204 #define RF_DECLARE_MUTEX(_m_)                pthread_mutex_t _m_;
205 #define RF_DECLARE_STATIC_MUTEX(_m_)  static pthread_mutex_t _m_;
206 #define RF_DECLARE_EXTERN_MUTEX(_m_)  extern pthread_mutex_t _m_;
207 #define RF_DECLARE_COND(_c_)                 pthread_cond_t  _c_;
208 #define RF_DECLARE_STATIC_COND(_c_)   static pthread_cond_t  _c_;
209 #define RF_DECLARE_EXTERN_COND(_c_)   extern pthread_cond_t  _c_;
210 
211 int rf_mutex_init(pthread_mutex_t *m);
212 int rf_mutex_destroy(pthread_mutex_t *m);
213 int rf_cond_init(pthread_cond_t *c);
214 int rf_cond_destroy(pthread_cond_t *c);
215 
216 #define RF_LOCK_MUTEX(_m_)     {pthread_mutex_lock(&(_m_));}
217 #define RF_UNLOCK_MUTEX(_m_)   pthread_mutex_unlock(&(_m_))
218 
219 #define RF_WAIT_COND(_c_,_m_)  pthread_cond_wait( &(_c_), &(_m_) )
220 #define RF_SIGNAL_COND(_c_)    pthread_cond_signal( &(_c_) )
221 #define RF_BROADCAST_COND(_c_) pthread_cond_broadcast(&(_c_))
222 
223 #endif /* RF_DEBUG_ATOMIC > 0 */
224 
225 int _rf_create_managed_mutex(RF_ShutdownList_t **listp, pthread_mutex_t *m, char *file, int line);
226 int _rf_create_managed_cond(RF_ShutdownList_t **listp, pthread_cond_t *c, char *file, int line);
227 
228 typedef pthread_t       RF_Thread_t;
229 #ifdef __osf__
230 typedef pthread_addr_t  RF_ThreadArg_t;        /* the argument to a thread function */
231 #else /* __osf__ */
232 typedef void *RF_ThreadArg_t;        /* the argument to a thread function */
233 #endif /* __osf__ */
234 typedef pthread_attr_t  RF_ThreadAttr_t;     /* a thread creation attribute structure */
235 
236 #ifdef __osf__
237 #define RF_EXIT_THREAD(_status_)                  pthread_exit( (pthread_addr_t) (_status_) )
238 #else /* __osf__ */
239 #define RF_EXIT_THREAD(_status_)                  pthread_exit( (void *) (_status_) )
240 #endif /* __osf__ */
241 #define RF_DELAY_THREAD(_secs_, _msecs_)          {struct timespec interval;                   \
242 						interval.tv_sec = (_secs_);                 \
243 						interval.tv_nsec = (_msecs_)*1000000;       \
244 						pthread_delay_np(&interval);                \
245 					       }
246 #define RF_DELAY_THREAD_TS(_ts_) pthread_delay_np(&(_ts_))
247 
248 #ifdef __osf__
249 #define RF_THREAD_ATTR_CREATE(_attr_)            pthread_attr_create( &(_attr_) )
250 #define RF_THREAD_ATTR_DELETE(_attr_)            pthread_attr_delete( &(_attr_) )
251 #endif /* __osf__ */
252 #ifdef AIX
253 #define RF_THREAD_ATTR_CREATE(_attr_)            pthread_attr_init( &(_attr_) )
254 #define RF_THREAD_ATTR_DELETE(_attr_)            pthread_attr_destroy( &(_attr_) )
255 #endif /* AIX */
256 #define RF_THREAD_ATTR_SETSTACKSIZE(_attr_,_sz_) pthread_attr_setstacksize(&(_attr_), (long) (_sz_))
257 #define RF_THREAD_ATTR_GETSTACKSIZE(_attr_)      pthread_attr_getstacksize(_attr_)
258 #define RF_THREAD_ATTR_SETSCHED(_attr_,_sched_)  pthread_attr_setsched(&(_attr_), (_sched_))
259 #define RF_CREATE_ATTR_THREAD(_handle_, _attr_, _func_, _arg_) \
260   pthread_create(&(_handle_), (_attr_), (pthread_startroutine_t) (_func_), (_arg_))
261 
262 
263 extern pthread_attr_t raidframe_attr_default;
264 int rf_thread_create(RF_Thread_t *thread, pthread_attr_t attr,
265   void (*func)(), RF_ThreadArg_t arg);
266 
267 #define RF_CREATE_THREAD(_handle_, _func_, _arg_)  \
268   rf_thread_create(&(_handle_), raidframe_attr_default, (_func_), (_arg_))
269 
270 #else   /* KERNEL */
271 #ifdef __NetBSD__
272 #include <sys/lock.h>
273 #define decl_simple_lock_data(a,b) a struct simplelock b;
274 #define simple_lock_addr(a) ((struct simplelock *)&(a))
275 #else
276 #include <kern/task.h>
277 #include <kern/thread.h>
278 #include <kern/lock.h>
279 #include <kern/sched_prim.h>
280 #define decl_simple_lock_data(a,b) a int (b);
281 #endif /* __NetBSD__ */
282 
283 #ifdef __NetBSD__
284 typedef struct proc *RF_Thread_t;
285 #else
286 typedef thread_t RF_Thread_t;
287 #endif
288 typedef void *RF_ThreadArg_t;
289 
290 #define RF_DECLARE_MUTEX(_m_)           decl_simple_lock_data(,(_m_))
291 #define RF_DECLARE_STATIC_MUTEX(_m_)    decl_simple_lock_data(static,(_m_))
292 #define RF_DECLARE_EXTERN_MUTEX(_m_)    decl_simple_lock_data(extern,(_m_))
293 
294 #define RF_DECLARE_COND(_c_)            int _c_;
295 #define RF_DECLARE_STATIC_COND(_c_)     static int _c_;
296 #define RF_DECLARE_EXTERN_COND(_c_)     extern int _c_;
297 
298 #define RF_LOCK_MUTEX(_m_)              simple_lock(&(_m_))
299 #define RF_UNLOCK_MUTEX(_m_)            simple_unlock(&(_m_))
300 
301 
302 #ifdef __NetBSD__
303 #include <sys/types.h>
304 #include <sys/kthread.h>
305 /*
306  * In NetBSD, kernel threads are simply processes which share several
307  * substructures and never run in userspace.
308  *
309  * XXX Note, NetBSD does not yet have a wakeup_one(), so we always
310  * XXX get Thundering Herd when a condition occurs.
311  */
312 #define RF_WAIT_COND(_c_,_m_)           { \
313 	RF_UNLOCK_MUTEX(_m_); \
314 	tsleep(&_c_, PRIBIO | PCATCH, "rfwcond", 0); \
315 	RF_LOCK_MUTEX(_m_); \
316 }
317 #define RF_SIGNAL_COND(_c_)            wakeup(&(_c_))
318 #define RF_BROADCAST_COND(_c_)         wakeup(&(_c_))
319 #define	RF_CREATE_THREAD(_handle_, _func_, _arg_) \
320 	kthread_create((void (*) __P((void *)))(_func_), (void *)(_arg_), \
321 	    (struct proc **)&(_handle_), "raid")
322 #else /* ! __NetBSD__ */
323 /*
324  * Digital UNIX/Mach threads.
325  */
326 #define RF_WAIT_COND(_c_,_m_)           { \
327 	assert_wait((vm_offset_t)&(_c_), TRUE); \
328 	RF_UNLOCK_MUTEX(_m_); \
329 	thread_block(); \
330 	RF_LOCK_MUTEX(_m_); \
331 }
332 #define RF_SIGNAL_COND(_c_)            thread_wakeup_one(((vm_offset_t)&(_c_)))
333 #define RF_BROADCAST_COND(_c_)         thread_wakeup(((vm_offset_t)&(_c_)))
334 extern task_t first_task;
335 #define RF_CREATE_THREAD(_handle_, _func_, _arg_) \
336 	(((_handle_ = kernel_thread_w_arg(first_task, (void (*)())_func_, (void *)(_arg_))) != THREAD_NULL) ? 0 : ENOMEM)
337 #endif /* __NetBSD__ */
338 #endif /* KERNEL */
339 #else /* SIMULATE */
340 
341 #define RF_DECLARE_MUTEX(_m_)        int _m_;
342 #define RF_DECLARE_STATIC_MUTEX(_m_) static int _m_;
343 #define RF_DECLARE_EXTERN_MUTEX(_m_) extern int _m_;
344 #define RF_DECLARE_COND(_c_)         int _c_;
345 #define RF_DECLARE_STATIC_COND(_c_)  static int _c_;
346 #define RF_DECLARE_EXTERN_COND(_c_)  extern int _c_;
347 
348 extern int rf_mutex_init(int *m);
349 extern int rf_mutex_destroy(int *m);
350 extern int rf_cond_init(int *c);
351 extern int rf_cond_destroy(int *c);
352 
353 int rf_mutex_init(int *m);
354 int rf_mutex_destroy(int *m);
355 int _rf_create_managed_mutex(RF_ShutdownList_t **listp, int *m, char *file, int line);
356 int _rf_create_managed_cond(RF_ShutdownList_t **listp, int *m, char *file, int line);
357 
358 typedef void  *RF_ThreadArg_t;        /* the argument to a thread function */
359 
360 #define RF_LOCK_MUTEX(_m_)
361 #define RF_UNLOCK_MUTEX(_m_)
362 
363 #define RF_WAIT_COND(_c_,_m_)
364 #define RF_SIGNAL_COND(_c_)
365 #define RF_BROADCAST_COND(_c_)
366 
367 #define RF_EXIT_THREAD(_status_)
368 #define RF_DELAY_THREAD(_secs_, _msecs_)
369 
370 #define RF_THREAD_ATTR_CREATE(_attr_) ;
371 #define RF_THREAD_ATTR_DELETE(_attr_) ;
372 #define RF_THREAD_ATTR_SETSTACKSIZE(_attr_,_sz_) ;
373 #define RF_THREAD_ATTR_SETSCHED(_attr_,_sched_)  ;
374 #define RF_CREATE_ATTR_THREAD(_handle_, _attr_, _func_, _arg_) ;
375 
376 #define RF_CREATE_THREAD(_handle_, _func_, _arg_)  1
377 
378 #endif /* SIMULATE */
379 
380 struct RF_ThreadGroup_s {
381   int  created;
382   int  running;
383   int  shutdown;
384   RF_DECLARE_MUTEX(mutex)
385   RF_DECLARE_COND(cond)
386 };
387 
388 /*
389  * Someone has started a thread in the group
390  */
391 #define RF_THREADGROUP_STARTED(_g_) { \
392 	RF_LOCK_MUTEX((_g_)->mutex); \
393 	(_g_)->created++; \
394 	RF_UNLOCK_MUTEX((_g_)->mutex); \
395 }
396 
397 /*
398  * Thread announcing that it is now running
399  */
400 #define RF_THREADGROUP_RUNNING(_g_) { \
401 	RF_LOCK_MUTEX((_g_)->mutex); \
402 	(_g_)->running++; \
403 	RF_UNLOCK_MUTEX((_g_)->mutex); \
404 	RF_SIGNAL_COND((_g_)->cond); \
405 }
406 
407 /*
408  * Thread announcing that it is now done
409  */
410 #define RF_THREADGROUP_DONE(_g_) { \
411 	RF_LOCK_MUTEX((_g_)->mutex); \
412 	(_g_)->shutdown++; \
413 	RF_UNLOCK_MUTEX((_g_)->mutex); \
414 	RF_SIGNAL_COND((_g_)->cond); \
415 }
416 
417 /*
418  * Wait for all threads to start running
419  */
420 #define RF_THREADGROUP_WAIT_START(_g_) { \
421 	RF_LOCK_MUTEX((_g_)->mutex); \
422 	while((_g_)->running < (_g_)->created) { \
423 		RF_WAIT_COND((_g_)->cond, (_g_)->mutex); \
424 	} \
425 	RF_UNLOCK_MUTEX((_g_)->mutex); \
426 }
427 
428 /*
429  * Wait for all threads to stop running
430  */
431 #ifndef __NetBSD__
432 #define RF_THREADGROUP_WAIT_STOP(_g_) { \
433 	RF_LOCK_MUTEX((_g_)->mutex); \
434 	RF_ASSERT((_g_)->running == (_g_)->created); \
435 	while((_g_)->shutdown < (_g_)->running) { \
436 		RF_WAIT_COND((_g_)->cond, (_g_)->mutex); \
437 	} \
438 	RF_UNLOCK_MUTEX((_g_)->mutex); \
439 }
440 #else
441   /* XXX Note that we've removed the assert.  That should get put back
442      in once we actually get something like a kernel thread running */
443 #define RF_THREADGROUP_WAIT_STOP(_g_) { \
444 	RF_LOCK_MUTEX((_g_)->mutex); \
445 	while((_g_)->shutdown < (_g_)->running) { \
446 		RF_WAIT_COND((_g_)->cond, (_g_)->mutex); \
447 	} \
448 	RF_UNLOCK_MUTEX((_g_)->mutex); \
449 }
450 #endif
451 
452 #if defined(__NetBSD__) && defined(_KERNEL)
453 
454 int rf_mutex_init(struct simplelock *);
455 int rf_mutex_destroy(struct simplelock *);
456 int _rf_create_managed_mutex(RF_ShutdownList_t **, struct simplelock *,
457 			     char *, int);
458 int _rf_create_managed_cond(RF_ShutdownList_t **listp, int *,
459 			    char *file, int line);
460 
461 int rf_cond_init(int *c); /* XXX need to write?? */
462 int rf_cond_destroy(int *c); /* XXX need to write?? */
463 #endif
464 #endif /* !_RF__RF_THREADSTUFF_H_ */
465