win95-initial-port-20010430
[openafs.git] / src / WINNT / client_osi / osiqueue.c
1 /* 
2  * Copyright (C) 1998, 1989 Transarc Corporation - All rights reserved
3  *
4  * (C) COPYRIGHT IBM CORPORATION 1987, 1988
5  * LICENSED MATERIALS - PROPERTY OF IBM
6  *
7  */
8
9 /* Copyright (C) 1994 Cazamar Systems, Inc. */
10
11 #include <afs/param.h>
12 #include <afs/stds.h>
13
14 #ifndef DJGPP
15 #include <windows.h>
16 #endif /* !DJGPP */
17 #include "osi.h"
18 #include <stdlib.h>
19
20 /* critical section protecting allocation of osi_queueData_t elements */
21 Crit_Sec osi_qdcrit;
22
23 /* free list of queue elements */
24 osi_queueData_t *osi_QDFreeListp = NULL;
25
26 void osi_QAdd(osi_queue_t **headpp, osi_queue_t *eltp)
27 {
28         osi_queue_t *tp;
29
30         /* and both paths do the following; do this early to keep
31          * machine busy while processing delay on conditional check
32          */
33         eltp->prevp = NULL;
34
35         if (tp = *headpp) {
36                 /* there is one element here */
37                 eltp->nextp = tp;
38                 tp->prevp = eltp;
39         }
40         else {
41                 /* we're the first */
42                 eltp->nextp = NULL;
43         }
44
45         /* and both paths do the following */
46         *headpp = eltp;
47 }
48
49 void osi_QAddH(osi_queue_t **headpp, osi_queue_t **tailpp, osi_queue_t *eltp)
50 {
51         osi_queue_t *tp;
52
53         /* and both paths do the following; do this early to keep
54          * machine busy while processing delay on conditional check
55          */
56         eltp->prevp = NULL;
57
58         if (tp = *headpp) {
59                 /* there is one element here */
60                 eltp->nextp = tp;
61                 tp->prevp = eltp;
62         }
63         else {
64                 /* we're the first */
65                 eltp->nextp = NULL;
66                 *tailpp = eltp;
67         }
68
69         /* and both paths do the following */
70         *headpp = eltp;
71 }
72
73 void osi_QAddT(osi_queue_t **headpp, osi_queue_t **tailpp, osi_queue_t *eltp)
74 {
75         osi_queue_t *tp;
76
77         eltp->nextp = NULL;
78
79         if (tp = *tailpp) {
80                 /* there's at least one element in the list; append ourselves */
81                 eltp->prevp = tp;
82                 tp->nextp = eltp;
83                 *tailpp = eltp;
84         }
85         else {
86                 /* we're the only element in the list */
87                 *headpp = eltp;
88                 *tailpp = eltp;
89                 eltp->prevp = NULL;
90         }
91 }
92
93 void osi_QRemove(osi_queue_t **headpp, osi_queue_t *eltp)
94 {
95         osi_queue_t *np;        /* next dude */
96
97         np = eltp->nextp;       /* useful for both paths */
98
99         if (eltp == *headpp) {
100                 /* we're the first element in the list */
101                 *headpp = np;
102                 if (np) np->prevp = NULL;
103         }
104         else {
105                 eltp->prevp->nextp = np;
106                 if (np) np->prevp = eltp->prevp;
107         }
108 }
109
110 void osi_InitQueue(void)
111 {
112         static int initd = 0;
113
114         if (initd) return;
115
116         initd = 1;
117         thrd_InitCrit(&osi_qdcrit);
118 }
119
120 osi_queueData_t *osi_QDAlloc(void)
121 {
122         osi_queueData_t *tp;
123         int i;
124
125         thrd_EnterCrit(&osi_qdcrit);
126         if (tp = osi_QDFreeListp) {
127                 osi_QDFreeListp = (osi_queueData_t *) tp->q.nextp;
128         }
129         else {
130                 /* need to allocate a block more */
131                 tp = (osi_queueData_t *) malloc(OSI_NQDALLOC * sizeof(osi_queueData_t));
132
133                 /* leave last guy off of the free list; this is the one we'll
134                  * return.
135                  */
136                 for(i=0; i<OSI_NQDALLOC-1; i++, tp++) {
137                         tp->q.nextp = (osi_queue_t *) osi_QDFreeListp;
138                         tp->datap = NULL;
139                         osi_QDFreeListp = tp;
140                 }
141                 
142                 /* when we get here, tp is pointing to the last dude allocated.
143                  * This guy wasn't put on the free list, so we can return him now.
144                  */
145                 tp->datap = NULL;
146         }
147         thrd_LeaveCrit(&osi_qdcrit);
148
149         osi_assertx(tp->datap == NULL, "queue freelist screwup");
150
151         return tp;
152 }
153
154 void osi_QDFree(osi_queueData_t *qp)
155 {
156         thrd_EnterCrit(&osi_qdcrit);
157         qp->q.nextp = (osi_queue_t *) osi_QDFreeListp;
158         qp->datap = NULL;
159         osi_QDFreeListp = qp;
160         thrd_LeaveCrit(&osi_qdcrit);
161 }