~jlukas79/+junk/mysql-server

« back to all changes in this revision

Viewing changes to mysys/wqueue.c

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
#include <wqueue.h>
 
3
 
 
4
#define STRUCT_PTR(TYPE, MEMBER, a)                                           \
 
5
          (TYPE *) ((char *) (a) - offsetof(TYPE, MEMBER))
 
6
/*
 
7
  Link a thread into double-linked queue of waiting threads.
 
8
 
 
9
  SYNOPSIS
 
10
    wqueue_link_into_queue()
 
11
      wqueue              pointer to the queue structure
 
12
      thread              pointer to the thread to be added to the queue
 
13
 
 
14
  RETURN VALUE
 
15
    none
 
16
 
 
17
  NOTES.
 
18
    Queue is represented by a circular list of the thread structures
 
19
    The list is double-linked of the type (**prev,*next), accessed by
 
20
    a pointer to the last element.
 
21
*/
 
22
 
 
23
void wqueue_link_into_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
 
24
{
 
25
  struct st_my_thread_var *last;
 
26
  if (!(last= wqueue->last_thread))
 
27
  {
 
28
    /* Queue is empty */
 
29
    thread->next= thread;
 
30
    thread->prev= &thread->next;
 
31
  }
 
32
  else
 
33
  {
 
34
    thread->prev= last->next->prev;
 
35
    last->next->prev= &thread->next;
 
36
    thread->next= last->next;
 
37
    last->next= thread;
 
38
  }
 
39
  wqueue->last_thread= thread;
 
40
}
 
41
 
 
42
 
 
43
/*
 
44
  Add a thread to single-linked queue of waiting threads
 
45
 
 
46
  SYNOPSIS
 
47
    wqueue_add_to_queue()
 
48
      wqueue              pointer to the queue structure
 
49
      thread              pointer to the thread to be added to the queue
 
50
 
 
51
  RETURN VALUE
 
52
    none
 
53
 
 
54
  NOTES.
 
55
    Queue is represented by a circular list of the thread structures
 
56
    The list is single-linked of the type (*next), accessed by a pointer
 
57
    to the last element.
 
58
*/
 
59
 
 
60
void wqueue_add_to_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
 
61
{
 
62
  struct st_my_thread_var *last;
 
63
  if (!(last= wqueue->last_thread))
 
64
    thread->next= thread;
 
65
  else
 
66
  {
 
67
    thread->next= last->next;
 
68
    last->next= thread;
 
69
  }
 
70
#ifndef DBUG_OFF
 
71
  thread->prev= NULL; /* force segfault if used */
 
72
#endif
 
73
  wqueue->last_thread= thread;
 
74
}
 
75
 
 
76
/*
 
77
  Unlink a thread from double-linked queue of waiting threads
 
78
 
 
79
  SYNOPSIS
 
80
    wqueue_unlink_from_queue()
 
81
      wqueue              pointer to the queue structure
 
82
      thread              pointer to the thread to be removed from the queue
 
83
 
 
84
  RETURN VALUE
 
85
    none
 
86
 
 
87
  NOTES.
 
88
    See NOTES for link_into_queue
 
89
*/
 
90
 
 
91
void wqueue_unlink_from_queue(WQUEUE *wqueue, struct st_my_thread_var *thread)
 
92
{
 
93
  if (thread->next == thread)
 
94
    /* The queue contains only one member */
 
95
    wqueue->last_thread= NULL;
 
96
  else
 
97
  {
 
98
    thread->next->prev= thread->prev;
 
99
    *thread->prev= thread->next;
 
100
    if (wqueue->last_thread == thread)
 
101
      wqueue->last_thread= STRUCT_PTR(struct st_my_thread_var, next,
 
102
                                      thread->prev);
 
103
  }
 
104
  thread->next= NULL;
 
105
}
 
106
 
 
107
 
 
108
/*
 
109
  Remove all threads from queue signaling them to proceed
 
110
 
 
111
  SYNOPSIS
 
112
    wqueue_realease_queue()
 
113
      wqueue              pointer to the queue structure
 
114
      thread              pointer to the thread to be added to the queue
 
115
 
 
116
  RETURN VALUE
 
117
    none
 
118
 
 
119
  NOTES.
 
120
    See notes for add_to_queue
 
121
    When removed from the queue each thread is signaled via condition
 
122
    variable thread->suspend.
 
123
*/
 
124
 
 
125
void wqueue_release_queue(WQUEUE *wqueue)
 
126
{
 
127
  struct st_my_thread_var *last= wqueue->last_thread;
 
128
  struct st_my_thread_var *next= last->next;
 
129
  struct st_my_thread_var *thread;
 
130
  do
 
131
  {
 
132
    thread= next;
 
133
    pthread_cond_signal(&thread->suspend);
 
134
    next= thread->next;
 
135
    thread->next= NULL;
 
136
  }
 
137
  while (thread != last);
 
138
  wqueue->last_thread= NULL;
 
139
}
 
140
 
 
141
 
 
142
/**
 
143
  @brief Removes all threads waiting for read or first one waiting for write.
 
144
 
 
145
  @param wqueue          pointer to the queue structure
 
146
  @param thread          pointer to the thread to be added to the queue
 
147
 
 
148
  @note This function is applicable only to single linked lists.
 
149
*/
 
150
 
 
151
void wqueue_release_one_locktype_from_queue(WQUEUE *wqueue)
 
152
{
 
153
  struct st_my_thread_var *last= wqueue->last_thread;
 
154
  struct st_my_thread_var *next= last->next;
 
155
  struct st_my_thread_var *thread;
 
156
  struct st_my_thread_var *new_list= NULL;
 
157
  uint first_type= next->lock_type;
 
158
  if (first_type == MY_PTHREAD_LOCK_WRITE)
 
159
  {
 
160
    /* release first waiting for write lock */
 
161
    pthread_cond_signal(&next->suspend);
 
162
    if (next == last)
 
163
      wqueue->last_thread= NULL;
 
164
    else
 
165
      last->next= next->next;
 
166
    next->next= NULL;
 
167
    return;
 
168
  }
 
169
  do
 
170
  {
 
171
    thread= next;
 
172
    next= thread->next;
 
173
    if (thread->lock_type == MY_PTHREAD_LOCK_WRITE)
 
174
    {
 
175
      /* skip waiting for write lock */
 
176
      if (new_list)
 
177
      {
 
178
        thread->next= new_list->next;
 
179
        new_list= new_list->next= thread;
 
180
      }
 
181
      else
 
182
        new_list= thread->next= thread;
 
183
    }
 
184
    else
 
185
    {
 
186
      /* release waiting for read lock */
 
187
      pthread_cond_signal(&thread->suspend);
 
188
      thread->next= NULL;
 
189
    }
 
190
  } while (thread != last);
 
191
  wqueue->last_thread= new_list;
 
192
}
 
193
 
 
194
 
 
195
/*
 
196
  Add thread and wait
 
197
 
 
198
  SYNOPSYS
 
199
    wqueue_add_and_wait()
 
200
    wqueue               queue to add to
 
201
    thread               thread which is waiting
 
202
    lock                 mutex need for the operation
 
203
*/
 
204
 
 
205
void wqueue_add_and_wait(WQUEUE *wqueue,
 
206
                         struct st_my_thread_var *thread,
 
207
                         pthread_mutex_t *lock)
 
208
{
 
209
  DBUG_ENTER("wqueue_add_and_wait");
 
210
  DBUG_PRINT("enter",
 
211
             ("thread: 0x%lx  cond: 0x%lx  mutex: 0x%lx",
 
212
              (ulong) thread, (ulong) &thread->suspend, (ulong) lock));
 
213
  wqueue_add_to_queue(wqueue, thread);
 
214
  do
 
215
  {
 
216
    DBUG_PRINT("info", ("wait... cond:  0x%lx  mutex:  0x%lx",
 
217
                        (ulong) &thread->suspend, (ulong) lock));
 
218
    pthread_cond_wait(&thread->suspend, lock);
 
219
    DBUG_PRINT("info", ("wait done cond: 0x%lx  mutex: 0x%lx   next: 0x%lx",
 
220
                        (ulong) &thread->suspend, (ulong) lock,
 
221
                        (ulong) thread->next));
 
222
  }
 
223
  while (thread->next);
 
224
  DBUG_VOID_RETURN;
 
225
}