kernel - Fix filesystem lookup error due to parent directory recyclement race
[dragonfly.git] / sys / sys / ccbque.h
1 /*
2  * [NetBSD for NEC PC98 series]
3  *  Copyright (c) 1994, 1995, 1996 NetBSD/pc98 porting staff.
4  *  All rights reserved.
5  * 
6  *  Redistribution and use in source and binary forms, with or without
7  *  modification, are permitted provided that the following conditions
8  *  are met:
9  *  1. Redistributions of source code must retain the above copyright
10  *     notice, this list of conditions and the following disclaimer.
11  *  2. Redistributions in binary form must reproduce the above copyright
12  *     notice, this list of conditions and the following disclaimer in the
13  *     documentation and/or other materials provided with the distribution.
14  *  3. The name of the author may not be used to endorse or promote products
15  *     derived from this software without specific prior written permission.
16  * 
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
21  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
23  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
25  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27  * POSSIBILITY OF SUCH DAMAGE.
28  *
29  * $NetBSD$
30  * $FreeBSD: src/sys/i386/isa/ccbque.h,v 1.3.6.2 2000/10/21 07:44:24 nyan Exp $
31  * $DragonFly: src/sys/sys/ccbque.h,v 1.11 2008/01/05 14:02:41 swildner Exp $
32  */
33 /*
34  * Common command control queue funcs.
35  * Written by N. Honda.
36  */
37
38 #ifndef _SYS_CCBQUE_H_
39 #define _SYS_CCBQUE_H_
40
41 #define CCB_MWANTED 0x01
42                                                 
43 /* (I)  structure and prototype */
44 #define GENERIC_CCB_ASSERT(DEV, CCBTYPE)                                \
45 TAILQ_HEAD(CCBTYPE##tab, CCBTYPE);                                      \
46 struct CCBTYPE##que {                                                   \
47         struct CCBTYPE##tab CCBTYPE##tab;                               \
48         int count;                                                      \
49         int maxccb;                                                     \
50         u_int flags;                                                    \
51 };                                                                      \
52                                                                         \
53 void DEV##_init_ccbque (int);                                   \
54 struct CCBTYPE *DEV##_get_ccb (void);                           \
55 void DEV##_free_ccb (struct CCBTYPE *);
56
57 /* (II)  static allocated memory */
58 #define GENERIC_CCB_STATIC_ALLOC(DEV, CCBTYPE)                          \
59 static struct CCBTYPE##que CCBTYPE##que;
60
61 /* (III)  functions */
62 #define GENERIC_CCB(DEV, CCBTYPE, CHAIN)                                \
63                                                                         \
64 void                                                                    \
65 DEV##_init_ccbque(int count)                                            \
66 {                                                                       \
67         if (CCBTYPE##que.maxccb == 0)                                   \
68                 TAILQ_INIT(&CCBTYPE##que.CCBTYPE##tab);                 \
69         CCBTYPE##que.maxccb += count;                                   \
70 }                                                                       \
71                                                                         \
72 struct CCBTYPE *                                                        \
73 DEV##_get_ccb(void)                                                             \
74 {                                                                       \
75         struct CCBTYPE *cb;                                             \
76                                                                         \
77         crit_enter();                                                   \
78                                                                         \
79         if (CCBTYPE##que.count < CCBTYPE##que.maxccb)                   \
80         {                                                               \
81                 CCBTYPE##que.count ++;                                  \
82                 cb = TAILQ_FIRST(&CCBTYPE##que.CCBTYPE##tab);           \
83                 if (cb != NULL)                                         \
84                 {                                                       \
85                         TAILQ_REMOVE(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);\
86                         goto out;                                       \
87                 }                                                       \
88                 else                                                    \
89                 {                                                       \
90                         cb = kmalloc(sizeof(*cb), M_DEVBUF, M_INTWAIT|M_ZERO);\
91                         if (cb != NULL)                                 \
92                                 goto out;                               \
93                 }                                                       \
94                 CCBTYPE##que.count --;                                  \
95         }                                                               \
96                                                                         \
97         cb = NULL;                                                      \
98                                                                         \
99 out:                                                                    \
100         crit_exit();                                                    \
101         return cb;                                                      \
102 }                                                                       \
103                                                                         \
104 void                                                                    \
105 DEV##_free_ccb(struct CCBTYPE *cb)                                                      \
106 {                                                                       \
107         crit_enter();                                                   \
108                                                                         \
109         TAILQ_INSERT_TAIL(&CCBTYPE##que.CCBTYPE##tab, cb, CHAIN);       \
110         CCBTYPE##que.count --;                                          \
111                                                                         \
112         if (CCBTYPE##que.flags & CCB_MWANTED)                           \
113         {                                                               \
114                 CCBTYPE##que.flags &= ~CCB_MWANTED;                     \
115                 wakeup ((caddr_t) &CCBTYPE##que.count);                 \
116         }                                                               \
117         crit_exit();                                                    \
118 }
119 #endif  /* !_SYS_CCBQUE_H_ */