LCOV - code coverage report
Current view: top level - include/freetds - thread.h (source / functions) Hit Total Coverage
Test: FreeTDS coverage Lines: 64 64 100.0 %
Date: 2024-03-23 09:12:27 Functions: 8 8 100.0 %

          Line data    Source code
       1             : /* FreeTDS - Library of routines accessing Sybase and Microsoft databases
       2             :  *
       3             :  * Copyright (C) 2005 Liam Widdowson
       4             :  * Copyright (C) 2010-2012 Frediano Ziglio
       5             :  *
       6             :  * This library is free software; you can redistribute it and/or
       7             :  * modify it under the terms of the GNU Library General Public
       8             :  * License as published by the Free Software Foundation; either
       9             :  * version 2 of the License, or (at your option) any later version.
      10             :  *
      11             :  * This library is distributed in the hope that it will be useful,
      12             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      14             :  * Library General Public License for more details.
      15             :  *
      16             :  * You should have received a copy of the GNU Library General Public
      17             :  * License along with this library; if not, write to the
      18             :  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
      19             :  * Boston, MA 02111-1307, USA.
      20             :  */
      21             : 
      22             : #ifndef TDSTHREAD_H
      23             : #define TDSTHREAD_H 1
      24             : 
      25             : #undef TDS_HAVE_MUTEX
      26             : 
      27             : #if defined(_THREAD_SAFE) && defined(TDS_HAVE_PTHREAD_MUTEX)
      28             : 
      29             : #include <tds_sysdep_public.h>
      30             : #include <freetds/sysdep_types.h>
      31             : #include <pthread.h>
      32             : #include <errno.h>
      33             : 
      34             : #include <freetds/pushvis.h>
      35             : 
      36             : typedef pthread_mutex_t tds_raw_mutex;
      37             : #define TDS_RAW_MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
      38             : 
      39             : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
      40             : {
      41      591016 :         pthread_mutex_lock(mtx);
      42             : }
      43             : 
      44             : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
      45             : {
      46      515876 :         return pthread_mutex_trylock(mtx);
      47             : }
      48             : 
      49             : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
      50             : {
      51     1025294 :         pthread_mutex_unlock(mtx);
      52             : }
      53             : 
      54             : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
      55             : {
      56       79216 :         return pthread_mutex_init(mtx, NULL);
      57             : }
      58             : 
      59             : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
      60             : {
      61       75617 :         pthread_mutex_destroy(mtx);
      62             : }
      63             : 
      64             : typedef pthread_cond_t tds_condition;
      65             : 
      66             : int tds_raw_cond_init(tds_condition *cond);
      67             : static inline int tds_raw_cond_destroy(tds_condition *cond)
      68             : {
      69        1816 :         return pthread_cond_destroy(cond);
      70             : }
      71             : static inline int tds_raw_cond_signal(tds_condition *cond)
      72             : {
      73       37327 :         return pthread_cond_signal(cond);
      74             : }
      75             : static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
      76             : {
      77          24 :         return pthread_cond_wait(cond, mtx);
      78             : }
      79             : int tds_raw_cond_timedwait(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
      80             : 
      81             : #define TDS_HAVE_MUTEX 1
      82             : 
      83             : typedef pthread_t tds_thread;
      84             : typedef pthread_t tds_thread_id;
      85             : typedef void *(*tds_thread_proc)(void *arg);
      86             : #define TDS_THREAD_PROC_DECLARE(name, arg) \
      87             :         void *name(void *arg)
      88             : #define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
      89             : 
      90             : static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
      91             : {
      92         294 :         return pthread_create(ret, NULL, proc, arg);
      93             : }
      94             : 
      95        1354 : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
      96             : {
      97             :         tds_thread th;
      98        1354 :         int ret = pthread_create(&th, NULL, proc, arg);
      99        1354 :         if (!ret)
     100        1354 :                 pthread_detach(th);
     101        1354 :         return ret;
     102             : }
     103             : 
     104             : static inline int tds_thread_join(tds_thread th, void **ret)
     105             : {
     106         294 :         return pthread_join(th, ret);
     107             : }
     108             : 
     109             : static inline tds_thread_id tds_thread_get_current_id(void)
     110             : {
     111     1027738 :         return pthread_self();
     112             : }
     113             : 
     114             : static inline int tds_thread_is_current(tds_thread_id th)
     115             : {
     116       86038 :         return pthread_equal(th, pthread_self());
     117             : }
     118             : 
     119             : #include <freetds/popvis.h>
     120             : 
     121             : #elif defined(_WIN32)
     122             : 
     123             : #include <freetds/windows.h>
     124             : #include <errno.h>
     125             : 
     126             : /* old version of Windows do not define this constant */
     127             : #ifndef ETIMEDOUT
     128             : #define ETIMEDOUT 138
     129             : #endif
     130             : 
     131             : struct ptw32_mcs_node_t_;
     132             : 
     133             : typedef struct {
     134             :         struct ptw32_mcs_node_t_ *lock;
     135             :         LONG done;
     136             :         DWORD thread_id;
     137             :         CRITICAL_SECTION crit;
     138             : } tds_raw_mutex;
     139             : 
     140             : #define TDS_RAW_MUTEX_INITIALIZER { NULL, 0, 0 }
     141             : 
     142             : static inline int
     143             : tds_raw_mutex_init(tds_raw_mutex *mtx)
     144             : {
     145             :         mtx->lock = NULL;
     146             :         mtx->done = 0;
     147             :         mtx->thread_id = 0;
     148             :         return 0;
     149             : }
     150             : 
     151             : void tds_win_mutex_lock(tds_raw_mutex *mutex);
     152             : 
     153             : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
     154             : {
     155             :         if (mtx->done) {
     156             :                 EnterCriticalSection(&mtx->crit);
     157             :                 mtx->thread_id = GetCurrentThreadId();
     158             :         } else {
     159             :                 tds_win_mutex_lock(mtx);
     160             :         }
     161             : }
     162             : 
     163             : int tds_raw_mutex_trylock(tds_raw_mutex *mtx);
     164             : 
     165             : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
     166             : {
     167             :         mtx->thread_id = 0;
     168             :         LeaveCriticalSection(&mtx->crit);
     169             : }
     170             : 
     171             : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
     172             : {
     173             :         if (mtx->done) {
     174             :                 DeleteCriticalSection(&mtx->crit);
     175             :                 mtx->done = 0;
     176             :         }
     177             : }
     178             : 
     179             : #define TDS_HAVE_MUTEX 1
     180             : 
     181             : /* easy way, only single signal supported */
     182             : typedef void *TDS_CONDITION_VARIABLE;
     183             : typedef union {
     184             :         HANDLE ev;
     185             :         TDS_CONDITION_VARIABLE cv;
     186             : } tds_condition;
     187             : 
     188             : extern int (*tds_raw_cond_init)(tds_condition *cond);
     189             : extern int (*tds_raw_cond_destroy)(tds_condition *cond);
     190             : extern int (*tds_raw_cond_signal)(tds_condition *cond);
     191             : extern int (*tds_raw_cond_timedwait)(tds_condition *cond, tds_raw_mutex *mtx, int timeout_sec);
     192             : static inline int tds_raw_cond_wait(tds_condition *cond, tds_raw_mutex *mtx)
     193             : {
     194             :         return tds_raw_cond_timedwait(cond, mtx, -1);
     195             : }
     196             : 
     197             : typedef HANDLE tds_thread;
     198             : typedef DWORD  tds_thread_id;
     199             : typedef DWORD (WINAPI *tds_thread_proc)(void *arg);
     200             : #define TDS_THREAD_PROC_DECLARE(name, arg) \
     201             :         DWORD WINAPI name(void *arg)
     202             : #define TDS_THREAD_RESULT(n) ((DWORD)(int)(n))
     203             : 
     204             : static inline int tds_thread_create(tds_thread *ret, tds_thread_proc proc, void *arg)
     205             : {
     206             :         *ret = CreateThread(NULL, 0, proc, arg, 0, NULL);
     207             :         return *ret != NULL ? 0 : 11 /* EAGAIN */;
     208             : }
     209             : 
     210             : static inline int tds_thread_create_detached(tds_thread_proc proc, void *arg)
     211             : {
     212             :         HANDLE h = CreateThread(NULL, 0, proc, arg, 0, NULL);
     213             :         if (h)
     214             :                 return 0;
     215             :         CloseHandle(h);
     216             :         return 11 /* EAGAIN */;
     217             : }
     218             : 
     219             : static inline int tds_thread_join(tds_thread th, void **ret)
     220             : {
     221             :         if (WaitForSingleObject(th, INFINITE) == WAIT_OBJECT_0) {
     222             :                 if (ret) {
     223             :                         DWORD r;
     224             :                         if (!GetExitCodeThread(th, &r))
     225             :                                 r = 0xffffffffu;
     226             :                         *ret = (void*) (((char*)0) + r);
     227             :                 }
     228             : 
     229             :                 CloseHandle(th);
     230             :                 return 0;
     231             :         }
     232             :         CloseHandle(th);
     233             :         return 22 /* EINVAL */;
     234             : }
     235             : 
     236             : static inline tds_thread_id tds_thread_get_current_id(void)
     237             : {
     238             :         return GetCurrentThreadId();
     239             : }
     240             : 
     241             : static inline int tds_thread_is_current(tds_thread_id th)
     242             : {
     243             :         return th == GetCurrentThreadId();
     244             : }
     245             : 
     246             : #else
     247             : 
     248             : #include <tds_sysdep_public.h>
     249             : 
     250             : /* define noops as "successful" */
     251             : typedef struct {
     252             :         char dummy[0]; /* compiler compatibility */
     253             : } tds_raw_mutex;
     254             : 
     255             : #define TDS_RAW_MUTEX_INITIALIZER {}
     256             : 
     257             : static inline void tds_raw_mutex_lock(tds_raw_mutex *mtx)
     258             : {
     259             : }
     260             : 
     261             : static inline int tds_raw_mutex_trylock(tds_raw_mutex *mtx)
     262             : {
     263             :         return 0;
     264             : }
     265             : 
     266             : static inline void tds_raw_mutex_unlock(tds_raw_mutex *mtx)
     267             : {
     268             : }
     269             : 
     270             : static inline int tds_raw_mutex_init(tds_raw_mutex *mtx)
     271             : {
     272             :         return 0;
     273             : }
     274             : 
     275             : static inline void tds_raw_mutex_free(tds_raw_mutex *mtx)
     276             : {
     277             : }
     278             : 
     279             : typedef struct {
     280             :         char dummy[0]; /* compiler compatibility */
     281             : } tds_condition;
     282             : 
     283             : static inline int tds_raw_cond_init(tds_condition *cond)
     284             : {
     285             :         return 0;
     286             : }
     287             : static inline int tds_raw_cond_destroy(tds_condition *cond)
     288             : {
     289             :         return 0;
     290             : }
     291             : #define tds_raw_cond_signal(cond) \
     292             :         FreeTDS_Condition_not_compiled
     293             : 
     294             : #define tds_raw_cond_wait(cond, mtx) \
     295             :         FreeTDS_Condition_not_compiled
     296             : 
     297             : #define tds_raw_cond_timedwait(cond, mtx, timeout_sec) \
     298             :         FreeTDS_Condition_not_compiled
     299             : 
     300             : typedef struct {
     301             :         char dummy[0]; /* compiler compatibility */
     302             : } tds_thread;
     303             : typedef int tds_thread_id;
     304             : 
     305             : typedef void *(*tds_thread_proc)(void *arg);
     306             : #define TDS_THREAD_PROC_DECLARE(name, arg) \
     307             :         void *name(void *arg)
     308             : #define TDS_THREAD_RESULT(n) ((void*)(TDS_INTPTR)(n))
     309             : 
     310             : #define tds_thread_create(ret, proc, arg) \
     311             :         FreeTDS_Thread_not_compiled
     312             : 
     313             : #define tds_thread_create_detached(proc, arg) \
     314             :         FreeTDS_Thread_not_compiled
     315             : 
     316             : #define tds_thread_join(th, ret) \
     317             :         FreeTDS_Thread_not_compiled
     318             : 
     319             : static inline tds_thread_id tds_thread_get_current_id(void)
     320             : {
     321             :         return 0;
     322             : }
     323             : 
     324             : static inline int tds_thread_is_current(tds_thread_id th)
     325             : {
     326             :         return 1;
     327             : }
     328             : 
     329             : #endif
     330             : 
     331             : #  define tds_cond_init tds_raw_cond_init
     332             : #  define tds_cond_destroy tds_raw_cond_destroy
     333             : #  define tds_cond_signal tds_raw_cond_signal
     334             : #  if !ENABLE_EXTRA_CHECKS
     335             : #    define TDS_MUTEX_INITIALIZER TDS_RAW_MUTEX_INITIALIZER
     336             : #    define tds_mutex tds_raw_mutex
     337             : #    define tds_mutex_lock tds_raw_mutex_lock
     338             : #    define tds_mutex_trylock tds_raw_mutex_trylock
     339             : #    define tds_mutex_unlock tds_raw_mutex_unlock
     340             : #    define tds_mutex_check_owned(mtx) do {} while(0)
     341             : #    define tds_mutex_init tds_raw_mutex_init
     342             : #    define tds_mutex_free tds_raw_mutex_free
     343             : #    define tds_cond_wait tds_raw_cond_wait
     344             : #    define tds_cond_timedwait tds_raw_cond_timedwait
     345             : #  else
     346             : #    include <assert.h>
     347             : 
     348             : typedef struct tds_mutex
     349             : {
     350             :         tds_raw_mutex mtx;
     351             :         volatile int locked;
     352             :         volatile tds_thread_id locked_by;
     353             : } tds_mutex;
     354             : 
     355             : #   define TDS_MUTEX_INITIALIZER { TDS_RAW_MUTEX_INITIALIZER, 0 }
     356             : 
     357      591016 : static inline void tds_mutex_lock(tds_mutex *mtx)
     358             : {
     359      591016 :         assert(mtx);
     360     1182032 :         tds_raw_mutex_lock(&mtx->mtx);
     361      591016 :         assert(!mtx->locked);
     362      591016 :         mtx->locked = 1;
     363      591016 :         mtx->locked_by = tds_thread_get_current_id();
     364      591016 : }
     365             : 
     366      434551 : static inline int tds_mutex_trylock(tds_mutex *mtx)
     367             : {
     368             :         int ret;
     369      434551 :         assert(mtx);
     370      869102 :         ret = tds_raw_mutex_trylock(&mtx->mtx);
     371      434551 :         if (!ret) {
     372      434278 :                 assert(!mtx->locked);
     373      434278 :                 mtx->locked = 1;
     374      434278 :                 mtx->locked_by = tds_thread_get_current_id();
     375             :         }
     376      434551 :         return ret;
     377             : }
     378             : 
     379     1025294 : static inline void tds_mutex_unlock(tds_mutex *mtx)
     380             : {
     381     1025294 :         assert(mtx && mtx->locked);
     382     1025294 :         mtx->locked = 0;
     383     2050588 :         tds_raw_mutex_unlock(&mtx->mtx);
     384     1025294 : }
     385             : 
     386       81325 : static inline void tds_mutex_check_owned(tds_mutex *mtx)
     387             : {
     388             :         int ret;
     389       81325 :         assert(mtx);
     390      162650 :         ret = tds_raw_mutex_trylock(&mtx->mtx);
     391       81325 :         assert(ret);
     392       81325 :         assert(mtx->locked);
     393      162650 :         assert(tds_thread_is_current(mtx->locked_by));
     394       81325 : }
     395             : 
     396             : static inline int tds_mutex_init(tds_mutex *mtx)
     397             : {
     398       79216 :         mtx->locked = 0;
     399      158432 :         return tds_raw_mutex_init(&mtx->mtx);
     400             : }
     401             : 
     402       75617 : static inline void tds_mutex_free(tds_mutex *mtx)
     403             : {
     404       75617 :         assert(mtx && !mtx->locked);
     405      151234 :         tds_raw_mutex_free(&mtx->mtx);
     406       75617 : }
     407             : 
     408           8 : static inline int tds_cond_wait(tds_condition *cond, tds_mutex *mtx)
     409             : {
     410             :         int ret;
     411           8 :         assert(mtx && mtx->locked);
     412           8 :         mtx->locked = 0;
     413          16 :         ret = tds_raw_cond_wait(cond, &mtx->mtx);
     414           8 :         mtx->locked = 1;
     415           8 :         mtx->locked_by = tds_thread_get_current_id();
     416           8 :         return ret;
     417             : }
     418             : 
     419          32 : static inline int tds_cond_timedwait(tds_condition *cond, tds_mutex *mtx, int timeout_sec)
     420             : {
     421             :         int ret;
     422          32 :         assert(mtx && mtx->locked);
     423          32 :         mtx->locked = 0;
     424          32 :         ret = tds_raw_cond_timedwait(cond, &mtx->mtx, timeout_sec);
     425          32 :         mtx->locked = 1;
     426          32 :         mtx->locked_by = tds_thread_get_current_id();
     427          32 :         return ret;
     428             : }
     429             : 
     430             : #  endif
     431             : 
     432             : #endif

Generated by: LCOV version 1.13