1
/* Copyright (c) 2005 PrimeBase Technologies GmbH
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
* 2006-03-22 Paul McCullagh
23
* This file contains windows specific code
26
#include "xt_config.h"
29
#include <my_pthread.h>
31
#include <sys/resource.h>
37
#include "pthread_xt.h"
38
#include "thread_xt.h"
42
xtPublic void xt_p_init_threading(void)
46
xtPublic int xt_p_set_normal_priority(pthread_t thr)
51
xtPublic int xt_p_set_low_priority(pthread_t thr)
56
xtPublic int xt_p_set_high_priority(pthread_t thr)
61
#define XT_RWLOCK_MAGIC 0x78AC390E
63
#ifdef XT_THREAD_LOCK_INFO
64
xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)
66
xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)
69
InitializeCriticalSection(&mutex->mt_cs);
70
#ifdef XT_THREAD_LOCK_INFO
71
xt_thread_lock_info_init(&mutex->mt_lock_info, mutex);
77
xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex)
79
DeleteCriticalSection(&mutex->mt_cs);
80
#ifdef XT_THREAD_LOCK_INFO
81
xt_thread_lock_info_free(&mutex->mt_lock_info);
86
xtPublic int xt_p_mutex_lock(xt_mutex_type *mx)
88
EnterCriticalSection(&mx->mt_cs);
89
#ifdef XT_THREAD_LOCK_INFO
90
xt_thread_lock_info_add_owner(&mx->mt_lock_info);
95
xtPublic int xt_p_mutex_unlock(xt_mutex_type *mx)
97
LeaveCriticalSection(&mx->mt_cs);
98
#ifdef XT_THREAD_LOCK_INFO
99
xt_thread_lock_info_release_owner(&mx->mt_lock_info);
104
xtPublic int xt_p_mutex_trylock(xt_mutex_type *mutex)
106
#if(_WIN32_WINNT >= 0x0400)
107
/* NOTE: MySQL bug! was using?!
108
* pthread_mutex_trylock(A) (WaitForSingleObject((A), 0) == WAIT_TIMEOUT)
110
if (TryEnterCriticalSection(&mutex->mt_cs)) {
111
#ifdef XT_THREAD_LOCK_INFO
112
xt_thread_lock_info_add_owner(&mutex->mt_lock_info);
118
EnterCriticalSection(&mutex->mt_cs);
119
#ifdef XT_THREAD_LOCK_INFO
120
xt_thread_lock_info_add_owner(&mutex->mt_lock_info);
126
#ifdef XT_THREAD_LOCK_INFO
127
xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr, const char *n)
129
xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwl, const pthread_condattr_t *attr)
135
return ERROR_BAD_ARGUMENTS;
137
rwl->rw_sh_count = 0;
138
rwl->rw_ex_count = 0;
139
rwl->rw_sh_complete_count = 0;
141
result = xt_p_mutex_init_with_autoname(&rwl->rw_ex_lock, NULL);
145
result = xt_p_mutex_init_with_autoname(&rwl->rw_sh_lock, NULL);
149
result = pthread_cond_init(&rwl->rw_sh_cond, NULL);
153
rwl->rw_magic = XT_RWLOCK_MAGIC;
154
#ifdef XT_THREAD_LOCK_INFO
156
xt_thread_lock_info_init(&rwl->rw_lock_info, rwl);
161
(void) xt_p_mutex_destroy(&rwl->rw_sh_lock);
164
(void) xt_p_mutex_destroy(&rwl->rw_ex_lock);
170
xtPublic int xt_p_rwlock_destroy(xt_rwlock_type *rwl)
172
int result = 0, result1 = 0, result2 = 0;
175
return ERROR_BAD_ARGUMENTS;
177
if (rwl->rw_magic != XT_RWLOCK_MAGIC)
178
return ERROR_BAD_ARGUMENTS;
180
if ((result = xt_p_mutex_lock(&rwl->rw_ex_lock)) != 0)
183
if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0) {
184
(void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
189
* Check whether any threads own/wait for the lock (wait for ex.access);
190
* report "BUSY" if so.
192
if (rwl->rw_ex_count > 0 || rwl->rw_sh_count > rwl->rw_sh_complete_count) {
193
result = xt_p_mutex_unlock(&rwl->rw_sh_lock);
194
result1 = xt_p_mutex_unlock(&rwl->rw_ex_lock);
195
result2 = ERROR_BUSY;
200
if ((result = xt_p_mutex_unlock(&rwl->rw_sh_lock)) != 0)
202
xt_p_mutex_unlock(&rwl->rw_ex_lock);
206
if ((result = xt_p_mutex_unlock(&rwl->rw_ex_lock)) != 0)
209
result = pthread_cond_destroy(&rwl->rw_sh_cond);
210
result1 = xt_p_mutex_destroy(&rwl->rw_sh_lock);
211
result2 = xt_p_mutex_destroy(&rwl->rw_ex_lock);
214
#ifdef XT_THREAD_LOCK_INFO
215
xt_thread_lock_info_free(&rwl->rw_lock_info);
218
return (result != 0) ? result : ((result1 != 0) ? result1 : result2);
222
xtPublic int xt_p_rwlock_rdlock(xt_rwlock_type *rwl)
227
return ERROR_BAD_ARGUMENTS;
229
if (rwl->rw_magic != XT_RWLOCK_MAGIC)
230
return ERROR_BAD_ARGUMENTS;
232
if ((result = xt_p_mutex_lock(&rwl->rw_ex_lock)) != 0)
235
if (++rwl->rw_sh_count == INT_MAX) {
236
if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0)
238
(void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
242
rwl->rw_sh_count -= rwl->rw_sh_complete_count;
243
rwl->rw_sh_complete_count = 0;
245
if ((result = xt_p_mutex_unlock(&rwl->rw_sh_lock)) != 0)
247
(void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
252
#ifdef XT_THREAD_LOCK_INFO
253
xt_thread_lock_info_add_owner(&rwl->rw_lock_info);
256
return (xt_p_mutex_unlock (&(rwl->rw_ex_lock)));
259
xtPublic int xt_p_rwlock_wrlock(xt_rwlock_type *rwl)
264
return ERROR_BAD_ARGUMENTS;
266
if (rwl->rw_magic != XT_RWLOCK_MAGIC)
267
return ERROR_BAD_ARGUMENTS;
269
if ((result = xt_p_mutex_lock (&rwl->rw_ex_lock)) != 0)
272
if ((result = xt_p_mutex_lock (&rwl->rw_sh_lock)) != 0) {
273
(void) xt_p_mutex_unlock (&rwl->rw_ex_lock);
277
if (rwl->rw_ex_count == 0) {
278
if (rwl->rw_sh_complete_count > 0) {
279
rwl->rw_sh_count -= rwl->rw_sh_complete_count;
280
rwl->rw_sh_complete_count = 0;
283
if (rwl->rw_sh_count > 0) {
284
rwl->rw_sh_complete_count = -rwl->rw_sh_count;
287
result = pthread_cond_wait (&rwl->rw_sh_cond, &rwl->rw_sh_lock.mt_cs);
289
while (result == 0 && rwl->rw_sh_complete_count < 0);
292
rwl->rw_sh_count = 0;
299
#ifdef XT_THREAD_LOCK_INFO
300
xt_thread_lock_info_add_owner(&rwl->rw_lock_info);
306
xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwl)
313
if (rwl->rw_magic != XT_RWLOCK_MAGIC)
316
if ((result = xt_p_mutex_trylock(&rwl->rw_ex_lock)) != 0)
319
if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0) {
320
(void) xt_p_mutex_unlock(&rwl->rw_ex_lock);
324
if (rwl->rw_ex_count == 0) {
325
if (rwl->rw_sh_complete_count > 0) {
326
rwl->rw_sh_count -= rwl->rw_sh_complete_count;
327
rwl->rw_sh_complete_count = 0;
330
if (rwl->rw_sh_count > 0) {
331
rwl->rw_sh_complete_count = -rwl->rw_sh_count;
334
result = pthread_cond_wait (&rwl->rw_sh_cond, &rwl->rw_sh_lock.mt_cs);
336
while (result == 0 && rwl->rw_sh_complete_count < 0);
339
rwl->rw_sh_count = 0;
346
#ifdef XT_THREAD_LOCK_INFO
347
xt_thread_lock_info_add_owner(&rwl->rw_lock_info);
353
xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwl)
358
return (ERROR_BAD_ARGUMENTS);
360
if (rwl->rw_magic != XT_RWLOCK_MAGIC)
361
return ERROR_BAD_ARGUMENTS;
363
if (rwl->rw_ex_count == 0) {
364
if ((result = xt_p_mutex_lock(&rwl->rw_sh_lock)) != 0)
367
if (++rwl->rw_sh_complete_count == 0)
368
result = pthread_cond_signal(&rwl->rw_sh_cond);
370
result1 = xt_p_mutex_unlock(&rwl->rw_sh_lock);
375
result = xt_p_mutex_unlock(&rwl->rw_sh_lock);
376
result1 = xt_p_mutex_unlock(&rwl->rw_ex_lock);
379
#ifdef XT_THREAD_LOCK_INFO
380
xt_thread_lock_info_release_owner(&rwl->rw_lock_info);
383
return ((result != 0) ? result : result1);
386
xtPublic int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
388
return xt_p_cond_timedwait(cond, mutex, NULL);
391
xtPublic int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mt, struct timespec *abstime)
393
return pthread_cond_timedwait(cond, &mt->mt_cs, abstime);
396
xtPublic int xt_p_join(pthread_t thread, void **value)
398
pthread_join(thread, value);
405
#define POLICY SCHED_RR
407
#define POLICY pth_policy
410
static int pth_policy;
411
static int pth_normal_priority;
412
static int pth_min_priority;
413
static int pth_max_priority;
415
/* Return zero if the priority was set OK,
418
static int pth_set_priority(pthread_t thread, int priority)
420
struct sched_param sp;
422
memset(&sp, 0, sizeof(struct sched_param));
423
sp.sched_priority = priority;
424
return pthread_setschedparam(thread, POLICY, &sp);
427
static void pth_get_priority_limits(void)
429
XTThreadPtr self = NULL;
430
struct sched_param sp;
434
/* Save original priority: */
435
err = pthread_getschedparam(pthread_self(), &pth_policy, &sp);
437
xt_throw_errno(XT_CONTEXT, err);
440
pth_normal_priority = sp.sched_priority;
442
start = sp.sched_priority;
445
pth_min_priority = sched_get_priority_min(sched_getscheduler(0));
446
pth_max_priority = sched_get_priority_max(sched_getscheduler(0));
448
/* Search for the minimum priority: */
449
pth_min_priority = start;
451
/* 2007-03-01: Corrected, pth_set_priority returns the error code
452
* (thanks to Hakan for pointing out this bug!)
454
if (pth_set_priority(pthread_self(), pth_min_priority-1) != 0)
459
/* Search for the maximum priority: */
460
pth_max_priority = start;
462
if (pth_set_priority(pthread_self(), pth_max_priority+1) != 0)
467
/* Restore original priority: */
468
pthread_setschedparam(pthread_self(), pth_policy, &sp);
472
xtPublic void xt_p_init_threading(void)
474
pth_get_priority_limits();
477
xtPublic int xt_p_set_low_priority(pthread_t thr)
479
if (pth_min_priority != pth_max_priority)
480
return pth_set_priority(thr, pth_min_priority);
484
xtPublic int xt_p_set_normal_priority(pthread_t thr)
486
if (pth_min_priority != pth_max_priority)
487
return pth_set_priority(thr, pth_normal_priority);
491
xtPublic int xt_p_set_high_priority(pthread_t thr)
493
if (pth_min_priority != pth_max_priority)
494
return pth_set_priority(thr, pth_max_priority);
500
xtPublic int xt_p_mutex_lock(xt_mutex_type *mutex, u_int line, const char *file)
502
XTThreadPtr self = xt_get_self();
505
ASSERT_NS(mutex->mu_init == 12345);
506
r = pthread_mutex_lock(&mutex->mu_plock);
509
printf("==LOCK mutex %d %s:%d\n", (int) mutex->mu_trace, file, (int) line);
510
ASSERT_NS(!mutex->mu_locker);
511
mutex->mu_locker = self;
512
mutex->mu_line = line;
513
mutex->mu_file = file;
515
#ifdef XT_THREAD_LOCK_INFO
516
xt_thread_lock_info_add_owner(&mutex->mu_lock_info);
521
xtPublic int xt_p_mutex_unlock(xt_mutex_type *mutex)
523
XTThreadPtr self = xt_get_self();
525
ASSERT_NS(mutex->mu_init == 12345);
526
ASSERT_NS(mutex->mu_locker == self);
527
mutex->mu_locker = NULL;
529
printf("UNLOCK mutex %d\n", (int) mutex->mu_trace);
530
#ifdef XT_THREAD_LOCK_INFO
531
xt_thread_lock_info_release_owner(&mutex->mu_lock_info);
533
return pthread_mutex_unlock(&mutex->mu_plock);
536
xtPublic int xt_p_mutex_destroy(xt_mutex_type *mutex)
538
//ASSERT_NS(mutex->mu_init == 12345);
539
mutex->mu_init = 11111;
540
#ifdef XT_THREAD_LOCK_INFO
541
xt_thread_lock_info_free(&mutex->mu_lock_info);
543
return pthread_mutex_destroy(&mutex->mu_plock);
546
xtPublic int xt_p_mutex_trylock(xt_mutex_type *mutex)
548
XTThreadPtr self = xt_get_self();
551
ASSERT_NS(mutex->mu_init == 12345);
552
r = pthread_mutex_trylock(&mutex->mu_plock);
554
ASSERT_NS(!mutex->mu_locker);
555
mutex->mu_locker = self;
556
#ifdef XT_THREAD_LOCK_INFO
557
xt_thread_lock_info_add_owner(&mutex->mu_lock_info);
563
#ifdef XT_THREAD_LOCK_INFO
564
xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr, const char *n)
566
xtPublic int xt_p_mutex_init(xt_mutex_type *mutex, const pthread_mutexattr_t *attr)
569
mutex->mu_init = 12345;
570
mutex->mu_trace = FALSE;
571
mutex->mu_locker = NULL;
572
#ifdef XT_THREAD_LOCK_INFO
574
xt_thread_lock_info_init(&mutex->mu_lock_info, mutex);
576
return pthread_mutex_init(&mutex->mu_plock, attr);
579
xtPublic int xt_p_cond_wait(xt_cond_type *cond, xt_mutex_type *mutex)
581
XTThreadPtr self = xt_get_self();
584
ASSERT_NS(mutex->mu_init == 12345);
585
ASSERT_NS(mutex->mu_locker == self);
586
mutex->mu_locker = NULL;
587
r = pthread_cond_wait(cond, &mutex->mu_plock);
588
ASSERT_NS(!mutex->mu_locker);
589
mutex->mu_locker = self;
593
xtPublic int xt_p_cond_timedwait(xt_cond_type *cond, xt_mutex_type *mutex, const struct timespec *abstime)
595
XTThreadPtr self = xt_get_self();
598
ASSERT_NS(mutex->mu_init == 12345);
599
ASSERT_NS(mutex->mu_locker == self);
600
mutex->mu_locker = NULL;
601
r = pthread_cond_timedwait(cond, &mutex->mu_plock, abstime);
602
ASSERT_NS(!mutex->mu_locker);
603
mutex->mu_locker = self;
607
xtPublic int xt_p_rwlock_rdlock(xt_rwlock_type *rwlock)
611
ASSERT_NS(rwlock->rw_init == 67890);
612
r = pthread_rwlock_rdlock(&rwlock->rw_plock);
613
#ifdef XT_THREAD_LOCK_INFO
614
xt_thread_lock_info_add_owner(&rwlock->rw_lock_info);
619
xtPublic int xt_p_rwlock_wrlock(xt_rwlock_type *rwlock)
621
XTThreadPtr self = xt_get_self();
624
ASSERT_NS(rwlock->rw_init == 67890);
625
r = pthread_rwlock_wrlock(&rwlock->rw_plock);
627
ASSERT_NS(!rwlock->rw_locker);
628
rwlock->rw_locker = self;
630
#ifdef XT_THREAD_LOCK_INFO
631
xt_thread_lock_info_add_owner(&rwlock->rw_lock_info);
636
xtPublic xtBool xt_p_rwlock_try_wrlock(xt_rwlock_type *rwlock)
638
XTThreadPtr self = xt_get_self();
641
ASSERT_NS(rwlock->rw_init == 67890);
642
r = pthread_rwlock_trywrlock(&rwlock->rw_plock);
644
ASSERT_NS(!rwlock->rw_locker);
645
rwlock->rw_locker = self;
646
#ifdef XT_THREAD_LOCK_INFO
647
xt_thread_lock_info_add_owner(&rwlock->rw_lock_info);
653
xtPublic int xt_p_rwlock_unlock(xt_rwlock_type *rwlock)
655
XTThreadPtr self = xt_get_self();
657
ASSERT_NS(rwlock->rw_init == 67890);
658
if (rwlock->rw_locker) {
659
ASSERT_NS(rwlock->rw_locker == self);
660
rwlock->rw_locker = NULL;
662
#ifdef XT_THREAD_LOCK_INFO
663
xt_thread_lock_info_release_owner(&rwlock->rw_lock_info);
665
return pthread_rwlock_unlock(&rwlock->rw_plock);
668
xtPublic int xt_p_rwlock_destroy(xt_rwlock_type *rwlock)
670
ASSERT_NS(rwlock->rw_init == 67890);
672
#ifdef XT_THREAD_LOCK_INFO
673
xt_thread_lock_info_free(&rwlock->rw_lock_info);
675
return pthread_rwlock_destroy(&rwlock->rw_plock);
678
#ifdef XT_THREAD_LOCK_INFO
679
xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwlock, const pthread_rwlockattr_t *attr, const char *n)
681
xtPublic int xt_p_rwlock_init(xt_rwlock_type *rwlock, const pthread_rwlockattr_t *attr)
684
rwlock->rw_init = 67890;
685
rwlock->rw_readers = 0;
686
rwlock->rw_locker = NULL;
687
#ifdef XT_THREAD_LOCK_INFO
689
xt_thread_lock_info_init(&rwlock->rw_lock_info, rwlock);
691
return pthread_rwlock_init(&rwlock->rw_plock, attr);
694
#endif // DEBUG_LOCKING