~mysql/mysql-server/mysql-6.0

« back to all changes in this revision

Viewing changes to mit-pthreads/pthreads/cond.c

  • Committer: bk at mysql
  • Date: 2000-07-31 19:29:14 UTC
  • Revision ID: sp1r-bk@work.mysql.com-20000731192914-08846
Import changeset

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* ==== cond.c ============================================================
 
2
 * Copyright (c) 1993, 1994 by Chris Provenzano, proven@mit.edu
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 * 1. Redistributions of source code must retain the above copyright
 
9
 *    notice, this list of conditions and the following disclaimer.
 
10
 * 2. Redistributions in binary form must reproduce the above copyright
 
11
 *    notice, this list of conditions and the following disclaimer in the
 
12
 *    documentation and/or other materials provided with the distribution.
 
13
 * 3. All advertising materials mentioning features or use of this software
 
14
 *    must display the following acknowledgement:
 
15
 *  This product includes software developed by Chris Provenzano.
 
16
 * 4. The name of Chris Provenzano may not be used to endorse or promote 
 
17
 *        products derived from this software without specific prior written
 
18
 *        permission.
 
19
 *
 
20
 * THIS SOFTWARE IS PROVIDED BY CHRIS PROVENZANO ``AS IS'' AND
 
21
 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 
22
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 
23
 * ARE DISCLAIMED.  IN NO EVENT SHALL CHRIS PROVENZANO BE LIABLE FOR ANY 
 
24
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 
25
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 
 
26
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
27
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 
 
28
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 
29
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 
 
30
 * SUCH DAMAGE.
 
31
 *
 
32
 * Description : Condition variable functions.
 
33
 *
 
34
 *  1.00 93/10/28 proven
 
35
 *      -Started coding this file.
 
36
 */
 
37
 
 
38
#ifndef lint
 
39
static const char rcsid[] = "$Id$";
 
40
#endif
 
41
 
 
42
#include <pthread.h>
 
43
#include <sys/time.h>
 
44
#include <stdlib.h>
 
45
#include <timers.h>
 
46
#include <errno.h>
 
47
 
 
48
#ifndef ETIME
 
49
#define ETIME ETIMEDOUT  
 
50
#endif
 
51
 
 
52
/* ==========================================================================
 
53
 * pthread_cond_is_debug()
 
54
 *
 
55
 * Check that cond is a debug cond and if so returns entry number into
 
56
 * array of debug condes.
 
57
 */
 
58
static int pthread_cond_debug_count = 0;
 
59
static pthread_cond_t ** pthread_cond_debug_ptrs = NULL;
 
60
static pthread_mutex_t pthread_cond_debug_mutex = PTHREAD_MUTEX_INITIALIZER;
 
61
 
 
62
static inline int pthread_cond_is_debug(pthread_cond_t * cond) 
 
63
{
 
64
        int i;
 
65
 
 
66
        for (i = 0; i < pthread_cond_debug_count; i++) {
 
67
                if (pthread_cond_debug_ptrs[i] == cond) {
 
68
                        return(i);
 
69
                }
 
70
        }
 
71
        return(NOTOK);
 
72
}
 
73
/* ==========================================================================
 
74
 * pthread_cond_init()
 
75
 *
 
76
 * In this implementation I don't need to allocate memory.
 
77
 * ENOMEM, EAGAIN should never be returned. Arch that have
 
78
 * weird constraints may need special coding.
 
79
 */
 
80
int pthread_cond_init(pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
 
81
{
 
82
        enum pthread_condtype type;
 
83
 
 
84
        /* Only check if attr specifies some mutex type other than fast */
 
85
        if ((cond_attr) && (cond_attr->c_type != COND_TYPE_FAST)) {
 
86
                if (cond_attr->c_type >= COND_TYPE_MAX) {
 
87
                        return(EINVAL);
 
88
                }
 
89
                type = cond_attr->c_type;
 
90
        } else {
 
91
                type = COND_TYPE_FAST;
 
92
        }
 
93
 
 
94
        switch (type) {
 
95
        case COND_TYPE_FAST:
 
96
        case COND_TYPE_COUNTING_FAST: 
 
97
                break;
 
98
        case COND_TYPE_DEBUG:
 
99
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
100
                if (pthread_cond_is_debug(cond) == NOTOK) {
 
101
                        pthread_cond_t ** new;
 
102
 
 
103
                        if ((new = (pthread_cond_t **)realloc(pthread_cond_debug_ptrs,
 
104
                          (pthread_cond_debug_count + 1) * (sizeof(void *)))) == NULL) {
 
105
                                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
106
                                return(ENOMEM);
 
107
                        }
 
108
                        pthread_cond_debug_ptrs = new;
 
109
                        pthread_cond_debug_ptrs[pthread_cond_debug_count++] = cond;
 
110
                } else {
 
111
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
112
                        return(EBUSY);
 
113
                }
 
114
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
115
        break;
 
116
    case COND_TYPE_STATIC_FAST:
 
117
        defualt:
 
118
        return(EINVAL);
 
119
        break;
 
120
        }
 
121
 
 
122
        /* Set all other paramaters */
 
123
        pthread_queue_init(&cond->c_queue);
 
124
        cond->c_flags   |= COND_FLAGS_INITED;
 
125
        cond->c_type    = type;
 
126
        return(OK);
 
127
}
 
128
 
 
129
/* ==========================================================================
 
130
 * pthread_cond_destroy()
 
131
 */
 
132
int pthread_cond_destroy(pthread_cond_t *cond)
 
133
{
 
134
        int i;
 
135
 
 
136
        /* Only check if cond is of type other than fast */
 
137
        switch(cond->c_type) {
 
138
        case COND_TYPE_FAST:
 
139
        case COND_TYPE_COUNTING_FAST: 
 
140
                break;
 
141
    case COND_TYPE_DEBUG:
 
142
        if (pthread_queue_get(&(cond->c_queue))) {
 
143
            return(EBUSY);
 
144
        }
 
145
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
146
                if ((i = pthread_cond_is_debug(cond)) == NOTOK) {
 
147
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
148
            return(EINVAL);
 
149
        }
 
150
 
 
151
                /* Remove the cond from the list of debug condition variables */
 
152
                pthread_cond_debug_ptrs[i] = 
 
153
                  pthread_cond_debug_ptrs[--pthread_cond_debug_count];
 
154
                pthread_cond_debug_ptrs[pthread_cond_debug_count] = NULL;
 
155
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
156
        break;
 
157
        case COND_TYPE_STATIC_FAST:
 
158
        default:
 
159
                return(EINVAL);
 
160
                break;
 
161
        }
 
162
 
 
163
        /* Cleanup cond, others might want to use it. */
 
164
        pthread_queue_init(&cond->c_queue);
 
165
        cond->c_flags   = 0;
 
166
        return(OK);
 
167
}
 
168
 
 
169
/* ==========================================================================
 
170
 * pthread_cond_wait()
 
171
 */
 
172
int pthread_cond_wait(pthread_cond_t *cond, pthread_mutex_t *mutex)
 
173
{
 
174
        int rval;
 
175
 
 
176
        pthread_sched_prevent();
 
177
        switch (cond->c_type) {
 
178
        case COND_TYPE_DEBUG: 
 
179
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
180
                if (pthread_cond_is_debug(cond) == NOTOK) {
 
181
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
182
                        pthread_sched_resume();
 
183
                        return(EINVAL);
 
184
                }
 
185
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
186
 
 
187
        /*
 
188
         * Fast condition variables do not check for any error conditions.
 
189
     */
 
190
        case COND_TYPE_FAST: 
 
191
        case COND_TYPE_STATIC_FAST:
 
192
                pthread_queue_enq(&cond->c_queue, pthread_run);
 
193
                pthread_mutex_unlock(mutex);
 
194
 
 
195
                pthread_run->data.mutex = mutex;
 
196
 
 
197
                SET_PF_WAIT_EVENT(pthread_run);
 
198
                SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
 
199
                /* Reschedule will unlock pthread_run */
 
200
                pthread_resched_resume(PS_COND_WAIT);
 
201
                CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
 
202
                CLEAR_PF_DONE_EVENT(pthread_run);
 
203
 
 
204
                pthread_run->data.mutex = NULL;
 
205
 
 
206
                rval = pthread_mutex_lock(mutex);
 
207
                return(rval);
 
208
                break;
 
209
        case COND_TYPE_COUNTING_FAST: 
 
210
                {
 
211
                int count = mutex->m_data.m_count;
 
212
 
 
213
                pthread_queue_enq(&cond->c_queue, pthread_run);
 
214
                pthread_mutex_unlock(mutex);
 
215
                mutex->m_data.m_count = 1;
 
216
 
 
217
                pthread_run->data.mutex = mutex;
 
218
 
 
219
                SET_PF_WAIT_EVENT(pthread_run);
 
220
                SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
 
221
                /* Reschedule will unlock pthread_run */
 
222
                pthread_resched_resume(PS_COND_WAIT);
 
223
                CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
 
224
                CLEAR_PF_DONE_EVENT(pthread_run);
 
225
 
 
226
                pthread_run->data.mutex = NULL;
 
227
 
 
228
                rval = pthread_mutex_lock(mutex);
 
229
                mutex->m_data.m_count = count;
 
230
                return(rval);
 
231
                break;
 
232
                }
 
233
        default:
 
234
                rval = EINVAL;
 
235
                break;
 
236
        }
 
237
        pthread_sched_resume();
 
238
        return(rval);
 
239
}
 
240
 
 
241
/* ==========================================================================
 
242
 * pthread_cond_timedwait()
 
243
 */
 
244
int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t *mutex,
 
245
  const struct timespec * abstime)
 
246
{
 
247
        struct timespec current_time, new_time;
 
248
        int rval = OK;
 
249
        
 
250
        pthread_sched_prevent();
 
251
        machdep_gettimeofday(& current_time);
 
252
 
 
253
        switch (cond->c_type) {
 
254
        case COND_TYPE_DEBUG: 
 
255
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
256
                if (pthread_cond_is_debug(cond) == NOTOK) {
 
257
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
258
                        pthread_sched_resume();
 
259
                        return(EINVAL);
 
260
                }
 
261
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
262
 
 
263
        /*
 
264
         * Fast condition variables do not check for any error conditions.
 
265
     */
 
266
        case COND_TYPE_FAST: 
 
267
        case COND_TYPE_STATIC_FAST:
 
268
 
 
269
                /* Set pthread wakeup time*/
 
270
                pthread_run->wakeup_time = *abstime;
 
271
 
 
272
                /* Install us on the sleep queue */
 
273
                sleep_schedule (&current_time, &(pthread_run->wakeup_time));
 
274
 
 
275
                pthread_queue_enq(&cond->c_queue, pthread_run);
 
276
                SET_PF_WAIT_EVENT(pthread_run);
 
277
                pthread_mutex_unlock(mutex);
 
278
 
 
279
                pthread_run->data.mutex = mutex;
 
280
 
 
281
                SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
 
282
                /* Reschedule will unlock pthread_run */
 
283
                pthread_resched_resume(PS_COND_WAIT);
 
284
                CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
 
285
 
 
286
                pthread_run->data.mutex = NULL;
 
287
 
 
288
                /* Remove ourselves from sleep queue. If we fail then we timedout */
 
289
        if (sleep_cancel(pthread_run) == NOTOK) {
 
290
                        SET_ERRNO(ETIME);
 
291
                        rval = ETIME;
 
292
                }
 
293
 
 
294
                CLEAR_PF_DONE_EVENT(pthread_run);
 
295
                pthread_mutex_lock(mutex);
 
296
                return(rval);
 
297
                break;
 
298
        case COND_TYPE_COUNTING_FAST: 
 
299
                {
 
300
                int count = mutex->m_data.m_count;
 
301
 
 
302
                /* Set pthread wakeup time*/
 
303
                pthread_run->wakeup_time = *abstime;
 
304
 
 
305
                /* Install us on the sleep queue */
 
306
                sleep_schedule (&current_time, &(pthread_run->wakeup_time));
 
307
 
 
308
                pthread_queue_enq(&cond->c_queue, pthread_run);
 
309
                SET_PF_WAIT_EVENT(pthread_run);
 
310
                pthread_mutex_unlock(mutex);
 
311
 
 
312
                pthread_run->data.mutex = mutex;
 
313
 
 
314
                SET_PF_AT_CANCEL_POINT(pthread_run); /* This is a cancel point */
 
315
                /* Reschedule will unlock pthread_run */
 
316
                pthread_resched_resume(PS_COND_WAIT);
 
317
                CLEAR_PF_AT_CANCEL_POINT(pthread_run); /* No longer at cancel point */
 
318
 
 
319
                pthread_run->data.mutex = NULL;
 
320
 
 
321
                /* Remove ourselves from sleep queue. If we fail then we timedout */
 
322
        if (sleep_cancel(pthread_run) == NOTOK) {
 
323
                        SET_ERRNO(ETIME);
 
324
                        rval = ETIME;
 
325
                }
 
326
 
 
327
                CLEAR_PF_DONE_EVENT(pthread_run);
 
328
                pthread_mutex_lock(mutex);
 
329
                mutex->m_data.m_count = count;
 
330
                return(rval);
 
331
                break;
 
332
                }
 
333
        default:
 
334
                rval = EINVAL;
 
335
                break;
 
336
        }
 
337
        pthread_sched_resume();
 
338
        return(rval);
 
339
}
 
340
 
 
341
/* ==========================================================================
 
342
 * pthread_cond_signal()
 
343
 */
 
344
int pthread_cond_signal(pthread_cond_t *cond)
 
345
{
 
346
        struct pthread *pthread;
 
347
        int rval;
 
348
 
 
349
        pthread_sched_prevent();
 
350
        switch (cond->c_type) {
 
351
        case COND_TYPE_DEBUG: 
 
352
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
353
                if (pthread_cond_is_debug(cond) == NOTOK) {
 
354
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
355
                        pthread_sched_resume();
 
356
                        return(EINVAL);
 
357
                }
 
358
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
359
 
 
360
        case COND_TYPE_FAST: 
 
361
        case COND_TYPE_STATIC_FAST:
 
362
                if (pthread = pthread_queue_deq(&cond->c_queue)) {
 
363
                        if ((SET_PF_DONE_EVENT(pthread)) == OK) {
 
364
                                pthread_sched_other_resume(pthread);
 
365
                        } else {
 
366
                                pthread_sched_resume();
 
367
                        }
 
368
                        return(OK);
 
369
                }
 
370
                rval = OK;
 
371
                break;
 
372
        default:
 
373
                rval = EINVAL;
 
374
                break;
 
375
        }
 
376
        pthread_sched_resume();
 
377
        return(rval);
 
378
}
 
379
 
 
380
/* ==========================================================================
 
381
 * pthread_cond_broadcast() 
 
382
 *
 
383
 * Not much different then the above routine.
 
384
 */
 
385
int pthread_cond_broadcast(pthread_cond_t *cond)
 
386
{
 
387
        struct pthread * pthread, * high_pthread, * low_pthread;
 
388
        int rval;
 
389
 
 
390
        pthread_sched_prevent();
 
391
        switch (cond->c_type) {
 
392
        case COND_TYPE_DEBUG: 
 
393
                pthread_mutex_lock(&pthread_cond_debug_mutex);
 
394
                if (pthread_cond_is_debug(cond) == NOTOK) {
 
395
                        pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
396
                        pthread_sched_resume();
 
397
                        return(EINVAL);
 
398
                }
 
399
                pthread_mutex_unlock(&pthread_cond_debug_mutex);
 
400
 
 
401
        case COND_TYPE_FAST: 
 
402
        case COND_TYPE_STATIC_FAST:
 
403
                if (pthread = pthread_queue_deq(&cond->c_queue)) {
 
404
                        pthread->state = PS_RUNNING;
 
405
                        high_pthread = pthread;
 
406
 
 
407
                        while (pthread = pthread_queue_deq(&cond->c_queue)) {
 
408
                                if (pthread->pthread_priority > 
 
409
                                  high_pthread->pthread_priority) {
 
410
                                        low_pthread = high_pthread;
 
411
                                        high_pthread = pthread;
 
412
                                } else {
 
413
                                        low_pthread     = pthread;
 
414
                                }
 
415
                                if ((SET_PF_DONE_EVENT(low_pthread)) == OK) {
 
416
                                        pthread_prio_queue_enq(pthread_current_prio_queue, 
 
417
                                          low_pthread);
 
418
                                        low_pthread->state = PS_RUNNING;
 
419
                                }
 
420
                        }
 
421
                        if ((SET_PF_DONE_EVENT(high_pthread)) == OK) {
 
422
                                pthread_sched_other_resume(high_pthread);
 
423
                        } else {
 
424
                                pthread_sched_resume();
 
425
                        }
 
426
                        return(OK);
 
427
                }
 
428
                rval = OK;
 
429
                break;
 
430
        default:
 
431
                rval = EINVAL;
 
432
                break;
 
433
        }
 
434
        pthread_sched_resume();
 
435
        return(rval);
 
436
}
 
437