LCOV - code coverage report
Current view: top level - lib/util - smb_threads.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 0 29 0.0 %
Date: 2024-04-21 15:09:00 Functions: 0 2 0.0 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    SMB client library implementation (thread interface functions).
       4             :    Copyright (C) Jeremy Allison, 2009.
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program 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
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : /*
      21             :  * This code is based in the ideas in openssl
      22             :  * but somewhat simpler and expended to include
      23             :  * thread local storage.
      24             :  */
      25             : 
      26             : #include "replace.h"
      27             : #include "smb_threads.h"
      28             : #include "smb_threads_internal.h"
      29             : #include "lib/util/debug.h"
      30             : #include "lib/util/fault.h"
      31             : #include "lib/util/memory.h"
      32             : 
      33             : /*********************************************************
      34             :  Functions to vector the locking primitives used internally
      35             :  by libsmbclient.
      36             : *********************************************************/
      37             : 
      38             : const struct smb_thread_functions *global_tfp;
      39             : 
      40             : /*********************************************************
      41             :  Dynamic lock array.
      42             : *********************************************************/
      43             : 
      44             : void **global_lock_array;
      45             : 
      46             : /*********************************************************
      47             :  Mutex used for our internal "once" function
      48             : *********************************************************/
      49             : 
      50             : static void *once_mutex = NULL;
      51             : 
      52             : 
      53             : /*********************************************************
      54             :  Function to set the locking primitives used by libsmbclient.
      55             : *********************************************************/
      56             : 
      57           0 : int smb_thread_set_functions(const struct smb_thread_functions *tf)
      58             : {
      59           0 :         int i;
      60             : 
      61           0 :         global_tfp = tf;
      62             : 
      63             : #if defined(PARANOID_MALLOC_CHECKER)
      64             : #ifdef malloc
      65             : #undef malloc
      66             : #endif
      67             : #endif
      68             : 
      69             :         /* Here we initialize any static locks we're using. */
      70           0 :         global_lock_array = (void **)malloc(sizeof(void *) *NUM_GLOBAL_LOCKS);
      71             : 
      72             : #if defined(PARANOID_MALLOC_CHECKER)
      73             : #define malloc(s) __ERROR_DONT_USE_MALLOC_DIRECTLY
      74             : #endif
      75             : 
      76           0 :         if (global_lock_array == NULL) {
      77           0 :                 return ENOMEM;
      78             :         }
      79             : 
      80           0 :         for (i = 0; i < NUM_GLOBAL_LOCKS; i++) {
      81           0 :                 char *name = NULL;
      82           0 :                 if (asprintf(&name, "global_lock_%d", i) == -1) {
      83           0 :                         SAFE_FREE(global_lock_array);
      84           0 :                         return ENOMEM;
      85             :                 }
      86           0 :                 if (global_tfp->create_mutex(name,
      87           0 :                                 &global_lock_array[i],
      88             :                                 __location__)) {
      89           0 :                         smb_panic("smb_thread_set_functions: create mutexes failed");
      90             :                 }
      91           0 :                 SAFE_FREE(name);
      92             :         }
      93             : 
      94             :         /* Create the mutex we'll use for our "once" function */
      95           0 :         if (SMB_THREAD_CREATE_MUTEX("smb_once", once_mutex) != 0) {
      96           0 :                 smb_panic("smb_thread_set_functions: failed to create 'once' mutex");
      97             :         }
      98             : 
      99           0 :         return 0;
     100             : }
     101             : 
     102             : /*******************************************************************
     103             :  Call a function only once. We implement this ourselves
     104             :  using our own mutex rather than using the thread implementation's
     105             :  *_once() function because each implementation has its own
     106             :  type for the variable which keeps track of whether the function
     107             :  has been called, and there's no easy way to allocate the correct
     108             :  size variable in code internal to Samba without knowing the
     109             :  implementation's "once" type.
     110             : ********************************************************************/
     111             : 
     112           0 : int smb_thread_once(smb_thread_once_t *ponce,
     113             :                     void (*init_fn)(void *pdata),
     114             :                     void *pdata)
     115             : {
     116           0 :         int ret;
     117             : 
     118             :         /* Lock our "once" mutex in order to test and initialize ponce */
     119           0 :         if (SMB_THREAD_LOCK(once_mutex) != 0) {
     120           0 :                 smb_panic("error locking 'once'");
     121             :         }
     122             : 
     123             :         /* Keep track of whether we ran their init function */
     124           0 :         ret = ! *ponce;
     125             : 
     126             :         /*
     127             :          * See if another thread got here after we tested it initially but
     128             :          * before we got our lock.
     129             :          */
     130           0 :         if (! *ponce) {
     131             :                 /* Nope, we need to run the initialization function */
     132           0 :                 (*init_fn)(pdata);
     133             : 
     134             :                 /* Now we can indicate that the function has been run */
     135           0 :                 *ponce = true;
     136             :         }
     137             : 
     138             :         /* Unlock the mutex */
     139           0 :         if (SMB_THREAD_UNLOCK(once_mutex) != 0) {
     140           0 :                 smb_panic("error unlocking 'once'");
     141             :         }
     142             :         
     143             :         /*
     144             :          * Tell 'em whether we ran their init function. If they passed a data
     145             :          * pointer to the init function and the init function could change
     146             :          * something in the pointed-to data, this will tell them whether that
     147             :          * data is valid or not.
     148             :          */
     149           0 :         return ret;
     150             : }
     151             : 
     152             : 
     153             : #if 0
     154             : /* Test. - pthread implementations. */
     155             : #include <pthread.h>
     156             : 
     157             : #ifdef malloc
     158             : #undef malloc
     159             : #endif
     160             : 
     161             : SMB_THREADS_DEF_PTHREAD_IMPLEMENTATION(tf);
     162             : 
     163             : static smb_thread_once_t ot = SMB_THREAD_ONCE_INIT;
     164             : void *pkey = NULL;
     165             : 
     166             : static void init_fn(void)
     167             : {
     168             :         int ret;
     169             : 
     170             :         if (!global_tfp) {
     171             :                 /* Non-thread safe init case. */
     172             :                 if (ot) {
     173             :                         return;
     174             :                 }
     175             :                 ot = true;
     176             :         }
     177             : 
     178             :         if ((ret = SMB_THREAD_CREATE_TLS("test_tls", pkey)) != 0) {
     179             :                 printf("Create tls once error: %d\n", ret);
     180             :         }
     181             : }
     182             : 
     183             : /* Test function. */
     184             : int test_threads(void)
     185             : {
     186             :         int ret;
     187             :         void *plock = NULL;
     188             :         smb_thread_set_functions(&tf);
     189             : 
     190             :         SMB_THREAD_ONCE(&ot, init_fn);
     191             : 
     192             :         if ((ret = SMB_THREAD_CREATE_MUTEX("test", plock)) != 0) {
     193             :                 printf("Create lock error: %d\n", ret);
     194             :         }
     195             :         if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_LOCK)) != 0) {
     196             :                 printf("lock error: %d\n", ret);
     197             :         }
     198             :         if ((ret = SMB_THREAD_LOCK(plock, SMB_THREAD_UNLOCK)) != 0) {
     199             :                 printf("unlock error: %d\n", ret);
     200             :         }
     201             :         SMB_THREAD_DESTROY_MUTEX(plock);
     202             :         SMB_THREAD_DESTROY_TLS(pkey);
     203             : 
     204             :         return 0;
     205             : }
     206             : #endif

Generated by: LCOV version 1.14