win-pvdrivers

view liblfds.6/src/single_dir_for_windows_kernel/queue_queue.c @ 1025:aa2e51f67f7c

Fix hibernate under Win8. Change debugprints.
author James Harper <james.harper@bendigoit.com.au>
date Tue Feb 19 15:14:53 2013 +1100 (2013-02-19)
parents 6300617040e0
children
line source
1 #include "queue_internal.h"
7 /****************************************************************************/
8 int queue_enqueue( struct queue_state *qs, void *user_data )
9 {
10 ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
11 *qe[QUEUE_PAC_SIZE];
13 assert( qs != NULL );
14 // TRD : user_data can be NULL
16 queue_internal_new_element_from_freelist( qs, qe, user_data );
18 if( qe[QUEUE_POINTER] == NULL )
19 return( 0 );
21 queue_internal_queue( qs, qe );
23 return( 1 );
24 }
30 /****************************************************************************/
31 int queue_guaranteed_enqueue( struct queue_state *qs, void *user_data )
32 {
33 ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
34 *qe[QUEUE_PAC_SIZE];
36 assert( qs != NULL );
37 // TRD : user_data can be NULL
39 queue_internal_guaranteed_new_element_from_freelist( qs, qe, user_data );
41 if( qe[QUEUE_POINTER] == NULL )
42 return( 0 );
44 queue_internal_queue( qs, qe );
46 return( 1 );
47 }
53 /****************************************************************************/
54 void queue_internal_queue( struct queue_state *qs, struct queue_element *qe[QUEUE_PAC_SIZE] )
55 {
56 ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
57 *enqueue[QUEUE_PAC_SIZE],
58 *next[QUEUE_PAC_SIZE];
60 unsigned char
61 cas_result = 0;
63 assert( qs != NULL );
64 assert( qe != NULL );
66 do
67 {
68 enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
69 enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
71 next[QUEUE_POINTER] = enqueue[QUEUE_POINTER]->next[QUEUE_POINTER];
72 next[QUEUE_COUNTER] = enqueue[QUEUE_POINTER]->next[QUEUE_COUNTER];
74 /* TRD : this if() ensures that the next we read, just above,
75 really is from qs->enqueue (which we copied into enqueue)
76 */
78 if( qs->enqueue[QUEUE_POINTER] == enqueue[QUEUE_POINTER] and qs->enqueue[QUEUE_COUNTER] == enqueue[QUEUE_COUNTER] )
79 {
80 if( next[QUEUE_POINTER] == NULL )
81 {
82 qe[QUEUE_COUNTER] = next[QUEUE_COUNTER] + 1;
83 cas_result = abstraction_dcas( (volatile atom_t *) enqueue[QUEUE_POINTER]->next, (atom_t *) qe, (atom_t *) next );
84 }
85 else
86 {
87 next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
88 abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
89 }
90 }
91 }
92 while( cas_result == 0 );
94 qe[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
95 abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) qe, (atom_t *) enqueue );
97 return;
98 }
104 /****************************************************************************/
105 int queue_dequeue( struct queue_state *qs, void **user_data )
106 {
107 ALIGN(ALIGN_DOUBLE_POINTER) struct queue_element
108 *enqueue[QUEUE_PAC_SIZE],
109 *dequeue[QUEUE_PAC_SIZE],
110 *next[QUEUE_PAC_SIZE];
112 unsigned char
113 cas_result = 0;
115 int
116 rv = 1,
117 state = QUEUE_STATE_UNKNOWN,
118 finished_flag = LOWERED;
120 assert( qs != NULL );
121 assert( user_data != NULL );
123 do
124 {
125 dequeue[QUEUE_POINTER] = qs->dequeue[QUEUE_POINTER];
126 dequeue[QUEUE_COUNTER] = qs->dequeue[QUEUE_COUNTER];
128 enqueue[QUEUE_POINTER] = qs->enqueue[QUEUE_POINTER];
129 enqueue[QUEUE_COUNTER] = qs->enqueue[QUEUE_COUNTER];
131 next[QUEUE_POINTER] = dequeue[QUEUE_POINTER]->next[QUEUE_POINTER];
132 next[QUEUE_COUNTER] = dequeue[QUEUE_POINTER]->next[QUEUE_COUNTER];
134 /* TRD : confirm that dequeue didn't move between reading it
135 and reading its next pointer
136 */
138 if( dequeue[QUEUE_POINTER] == qs->dequeue[QUEUE_POINTER] and dequeue[QUEUE_COUNTER] == qs->dequeue[QUEUE_COUNTER] )
139 {
140 if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] == NULL )
141 state = QUEUE_STATE_EMPTY;
143 if( enqueue[QUEUE_POINTER] == dequeue[QUEUE_POINTER] and next[QUEUE_POINTER] != NULL )
144 state = QUEUE_STATE_ENQUEUE_OUT_OF_PLACE;
146 if( enqueue[QUEUE_POINTER] != dequeue[QUEUE_POINTER] )
147 state = QUEUE_STATE_ATTEMPT_DEQUEUE;
149 switch( state )
150 {
151 case QUEUE_STATE_EMPTY:
152 *user_data = NULL;
153 rv = 0;
154 finished_flag = RAISED;
155 break;
157 case QUEUE_STATE_ENQUEUE_OUT_OF_PLACE:
158 next[QUEUE_COUNTER] = enqueue[QUEUE_COUNTER] + 1;
159 abstraction_dcas( (volatile atom_t *) qs->enqueue, (atom_t *) next, (atom_t *) enqueue );
160 break;
162 case QUEUE_STATE_ATTEMPT_DEQUEUE:
163 *user_data = next[QUEUE_POINTER]->user_data;
165 next[QUEUE_COUNTER] = dequeue[QUEUE_COUNTER] + 1;
166 cas_result = abstraction_dcas( (volatile atom_t *) qs->dequeue, (atom_t *) next, (atom_t *) dequeue );
168 if( cas_result == 1 )
169 finished_flag = RAISED;
170 break;
171 }
172 }
173 }
174 while( finished_flag == LOWERED );
176 if( cas_result == 1 )
177 freelist_push( qs->fs, dequeue[QUEUE_POINTER]->fe );
179 return( rv );
180 }