LCOV - code coverage report
Current view: top level - src - posix-lock.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 25 36 69.4 %
Date: 2016-09-12 12:50:44 Functions: 4 5 80.0 %

          Line data    Source code
       1             : /* posix-lock.c - GPGRT lock functions for POSIX systems
       2             :    Copyright (C) 2005-2009 Free Software Foundation, Inc.
       3             :    Copyright (C) 2014 g10 Code GmbH
       4             : 
       5             :    This file is part of libgpg-error.
       6             : 
       7             :    libgpg-error is free software; you can redistribute it and/or
       8             :    modify it under the terms of the GNU Lesser General Public License
       9             :    as published by the Free Software Foundation; either version 2.1 of
      10             :    the License, or (at your option) any later version.
      11             : 
      12             :    libgpg-error is distributed in the hope that it will be useful, but
      13             :    WITHOUT ANY WARRANTY; without even the implied warranty of
      14             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      15             :    Lesser General Public License for more details.
      16             : 
      17             :    You should have received a copy of the GNU Lesser General Public
      18             :    License along with this program; if not, see <https://www.gnu.org/licenses/>.
      19             : 
      20             :    Parts of the code, in particular use_pthreads_p, are based on code
      21             :    from gettext, written by Bruno Haible <bruno@clisp.org>, 2005.
      22             :  */
      23             : 
      24             : #if HAVE_CONFIG_H
      25             : #include <config.h>
      26             : #endif
      27             : 
      28             : #ifdef HAVE_W32_SYSTEM
      29             : # error This module may not be build for Windows.
      30             : #endif
      31             : 
      32             : #include <stdlib.h>
      33             : #include <stdio.h>
      34             : #include <string.h>
      35             : #include <errno.h>
      36             : #include <assert.h>
      37             : 
      38             : #if USE_POSIX_THREADS
      39             : # include <pthread.h>
      40             : #endif
      41             : 
      42             : #include "gpg-error.h"
      43             : #include "lock.h"
      44             : #include "posix-lock-obj.h"
      45             : 
      46             : 
      47             : #if USE_POSIX_THREADS
      48             : # if USE_POSIX_THREADS_WEAK
      49             :    /* On ELF systems it is easy to use pthreads using weak
      50             :       references.  Take care not to test the address of a weak
      51             :       referenced function we actually use; some GCC versions have a
      52             :       bug were &foo != NULL is always evaluated to true in PIC mode.  */
      53             : #  pragma weak pthread_cancel
      54             : #  pragma weak pthread_mutex_init
      55             : #  pragma weak pthread_mutex_lock
      56             : #  pragma weak pthread_mutex_trylock
      57             : #  pragma weak pthread_mutex_unlock
      58             : #  pragma weak pthread_mutex_destroy
      59             : #  if ! PTHREAD_IN_USE_DETECTION_HARD
      60             : #   define use_pthread_p() (!!pthread_cancel)
      61             : #  endif
      62             : # else /*!USE_POSIX_THREADS_WEAK*/
      63             : #  if ! PTHREAD_IN_USE_DETECTION_HARD
      64             : #   define use_pthread_p() (1)
      65             : #  endif
      66             : # endif /*!USE_POSIX_THREADS_WEAK*/
      67             : # if PTHREAD_IN_USE_DETECTION_HARD
      68             : /* The function to be executed by a dummy thread.  */
      69             : static void *
      70             : dummy_thread_func (void *arg)
      71             : {
      72             :   return arg;
      73             : }
      74             : 
      75             : static int
      76             : use_pthread_p (void)
      77             : {
      78             :   static int tested;
      79             :   static int result; /* 1: linked with -lpthread, 0: only with libc */
      80             : 
      81             :   if (!tested)
      82             :     {
      83             :       pthread_t thread;
      84             : 
      85             :       if (pthread_create (&thread, NULL, dummy_thread_func, NULL))
      86             :         result = 0; /* Thread creation failed.  */
      87             :       else
      88             :         {
      89             :           /* Thread creation works.  */
      90             :           void *retval;
      91             :           if (pthread_join (thread, &retval) != 0)
      92             :             {
      93             :               assert (!"pthread_join");
      94             :               abort ();
      95             :             }
      96             :           result = 1;
      97             :         }
      98             :       tested = 1;
      99             :     }
     100             :   return result;
     101             : }
     102             : #endif /*PTHREAD_IN_USE_DETECTION_HARD*/
     103             : #endif /*USE_POSIX_THREADS*/
     104             : 
     105             : 
     106             : 
     107             : static _gpgrt_lock_t *
     108             : get_lock_object (gpgrt_lock_t *lockhd)
     109             : {
     110             :   _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
     111             : 
     112       39461 :   if (lock->vers != LOCK_ABI_VERSION)
     113             :     {
     114           0 :       assert (!"lock ABI version");
     115             :       abort ();
     116             :     }
     117             :   if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
     118             :     {
     119             :       assert (!"sizeof lock obj");
     120             :       abort ();
     121             :     }
     122             : 
     123             :   return lock;
     124             : }
     125             : 
     126             : 
     127             : gpg_err_code_t
     128           7 : _gpgrt_lock_init (gpgrt_lock_t *lockhd)
     129             : {
     130             :   _gpgrt_lock_t *lock = (_gpgrt_lock_t*)lockhd;
     131             :   int rc;
     132             : 
     133             :   /* If VERS is zero we assume that no static initialization has been
     134             :      done, so we setup our ABI version right here.  The caller might
     135             :      have called us to test whether lock support is at all available. */
     136           7 :   if (!lock->vers)
     137             :     {
     138             :       if (sizeof (gpgrt_lock_t) < sizeof (_gpgrt_lock_t))
     139             :         {
     140             :           assert (!"sizeof lock obj");
     141             :           abort ();
     142             :         }
     143           6 :       lock->vers = LOCK_ABI_VERSION;
     144             :     }
     145             :   else /* Run the usual check.  */
     146             :     lock = get_lock_object (lockhd);
     147             : 
     148             : #if USE_POSIX_THREADS
     149           7 :   if (use_pthread_p())
     150             :     {
     151           7 :       rc = pthread_mutex_init (&lock->u.mtx, NULL);
     152           7 :       if (rc)
     153           0 :         rc = gpg_err_code_from_errno (rc);
     154             :     }
     155             :   else
     156             :     rc = 0; /* Threads are not used.  */
     157             : #else /* Unknown thread system.  */
     158             :   rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED;
     159             : #endif /* Unknown thread system.  */
     160             : 
     161           7 :   return rc;
     162             : }
     163             : 
     164             : 
     165             : gpg_err_code_t
     166       19498 : _gpgrt_lock_lock (gpgrt_lock_t *lockhd)
     167             : {
     168             :   _gpgrt_lock_t *lock = get_lock_object (lockhd);
     169             :   int rc;
     170             : 
     171             : #if USE_POSIX_THREADS
     172       19498 :   if (use_pthread_p())
     173             :     {
     174       19507 :       rc = pthread_mutex_lock (&lock->u.mtx);
     175       19950 :       if (rc)
     176           0 :         rc = gpg_err_code_from_errno (rc);
     177             :     }
     178             :   else
     179             :     rc = 0; /* Threads are not used.  */
     180             : #else /* Unknown thread system.  */
     181             :   rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED;
     182             : #endif /* Unknown thread system.  */
     183             : 
     184       19941 :   return rc;
     185             : }
     186             : 
     187             : 
     188             : gpg_err_code_t
     189           0 : _gpgrt_lock_trylock (gpgrt_lock_t *lockhd)
     190             : {
     191             :   _gpgrt_lock_t *lock = get_lock_object (lockhd);
     192             :   int rc;
     193             : 
     194             : #if USE_POSIX_THREADS
     195           0 :   if (use_pthread_p())
     196             :     {
     197           0 :       rc = pthread_mutex_trylock (&lock->u.mtx);
     198           0 :       if (rc)
     199           0 :         rc = gpg_err_code_from_errno (rc);
     200             :     }
     201             :   else
     202             :     rc = 0; /* Threads are not used.  */
     203             : #else /* Unknown thread system.  */
     204             :   rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED;
     205             : #endif /* Unknown thread system.  */
     206             : 
     207           0 :   return rc;
     208             : }
     209             : 
     210             : 
     211             : gpg_err_code_t
     212       19953 : _gpgrt_lock_unlock (gpgrt_lock_t *lockhd)
     213             : {
     214             :   _gpgrt_lock_t *lock = get_lock_object (lockhd);
     215             :   int rc;
     216             : 
     217             : #if USE_POSIX_THREADS
     218       19953 :   if (use_pthread_p())
     219             :     {
     220       19949 :       rc = pthread_mutex_unlock (&lock->u.mtx);
     221       19712 :       if (rc)
     222           0 :         rc = gpg_err_code_from_errno (rc);
     223             :     }
     224             :   else
     225             :     rc = 0; /* Threads are not used.  */
     226             : #else /* Unknown thread system.  */
     227             :   rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED;
     228             : #endif /* Unknown thread system.  */
     229             : 
     230       19716 :   return rc;
     231             : }
     232             : 
     233             : 
     234             : /* Note: Use this function only if no other thread holds or waits for
     235             :    this lock.  */
     236             : gpg_err_code_t
     237           9 : _gpgrt_lock_destroy (gpgrt_lock_t *lockhd)
     238             : {
     239             :   _gpgrt_lock_t *lock = get_lock_object (lockhd);
     240             :   int rc;
     241             : 
     242             : #if USE_POSIX_THREADS
     243           9 :   if (use_pthread_p())
     244             :     {
     245           9 :       rc = pthread_mutex_destroy (&lock->u.mtx);
     246           9 :       if (rc)
     247           0 :         rc = gpg_err_code_from_errno (rc);
     248             :       else
     249             :         {
     250             :           /* Re-init the mutex so that it can be re-used.  */
     251           9 :           gpgrt_lock_t tmp = GPGRT_LOCK_INITIALIZER;
     252           9 :           memcpy (lockhd, &tmp, sizeof tmp);
     253             :         }
     254             :     }
     255             :   else
     256             :     rc = 0; /* Threads are not used.  */
     257             : #else /* Unknown thread system.  */
     258             :   rc = lock->vers == LOCK_ABI_NOT_AVAILABLE? 0 : GPG_ERR_NOT_IMPLEMENTED;
     259             : #endif /* Unknown thread system.  */
     260             : 
     261           9 :   return rc;
     262             : }

Generated by: LCOV version 1.11