Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Globals/TLS for libubf
0003  *
0004  * @file ubf_tls.c
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 
0035 /*---------------------------Includes-----------------------------------*/
0036 #include <stdlib.h>
0037 #include <stdio.h>
0038 #include <ndrstandard.h>
0039 #include <ubf_tls.h>
0040 #include <string.h>
0041 #include "thlock.h"
0042 #include "userlog.h"
0043 #include <ndebug.h>
0044 /*---------------------------Externs------------------------------------*/
0045 /*---------------------------Macros-------------------------------------*/
0046 /*---------------------------Enums--------------------------------------*/
0047 /*---------------------------Typedefs-----------------------------------*/
0048 /*---------------------------Globals------------------------------------*/
0049 __thread ubf_tls_t *G_ubf_tls = NULL; /* single place for library TLS storage */
0050 /*---------------------------Statics------------------------------------*/
0051 exprivate pthread_key_t M_ubf_tls_key;
0052 exprivate MUTEX_LOCKDECL(M_thdata_init);
0053 exprivate int M_first = EXTRUE;
0054 /*---------------------------Prototypes---------------------------------*/
0055 
0056 /**
0057  * Unlock, unset G_ubf_tls, return pointer to G_ubf_tls
0058  * @return 
0059  */
0060 expublic void * ndrx_ubf_tls_get(void)
0061 {
0062     ubf_tls_t *tmp = G_ubf_tls;
0063     
0064     G_ubf_tls = NULL;
0065     
0066     if (NULL!=tmp)
0067     {
0068         /*
0069          * Unset the destructor
0070          */
0071         if (tmp->is_auto)
0072         {
0073             pthread_setspecific( M_ubf_tls_key, NULL );
0074         }
0075 
0076         /* unlock object */
0077         MUTEX_UNLOCK_V(tmp->mutex);
0078     }
0079     
0080     return (void *)tmp;
0081 }
0082 
0083 /**
0084  * Get the lock & set the G_ubf_tls to this one
0085  * @param tls
0086  */
0087 expublic int ndrx_ubf_tls_set(void *data)
0088 {
0089     ubf_tls_t *tls = (ubf_tls_t *)data;
0090     
0091     if (NULL!=tls)
0092     {
0093         /* extra control... */
0094         if (UBF_TLS_MAGIG!=tls->magic)
0095         {
0096             userlog("ubf_tls_set: invalid magic! expected: %x got %x", 
0097                     UBF_TLS_MAGIG, tls->magic);
0098         }
0099 
0100         /* Lock the object */
0101         MUTEX_LOCK_V(tls->mutex);
0102 
0103         G_ubf_tls = tls;
0104 
0105         /*
0106          * Destruct automatically if it was auto-tls 
0107          */
0108         if (tls->is_auto)
0109         {
0110             pthread_setspecific( M_ubf_tls_key, (void *)tls );
0111         }
0112     }
0113     else
0114     {
0115         G_ubf_tls = NULL;
0116     }
0117     
0118     return EXSUCCEED;
0119     
0120 }
0121 
0122 /**
0123  * Free up the TLS data
0124  * @param tls
0125  * @return 
0126  */
0127 expublic void ndrx_ubf_tls_free(void *data)
0128 {    
0129     if (NULL!=data)
0130     {
0131         ubf_tls_t *tls = (ubf_tls_t *)data;
0132         
0133         if (data==G_ubf_tls)
0134         {
0135             if (G_ubf_tls->is_auto)
0136             {
0137                 pthread_setspecific( M_ubf_tls_key, NULL );
0138             }
0139             G_ubf_tls=NULL;
0140         }
0141         
0142         /* Bug #381 */
0143         if (NULL!=tls->str_buf_ptr)
0144         {
0145             NDRX_FREE(tls->str_buf_ptr);
0146         }
0147         
0148         NDRX_FREE((char*)data);
0149     }
0150 }
0151 
0152 /**
0153  * Get the lock & init the data
0154  * @param auto_destroy if set to 1 then when tried exits, thread data will be made free
0155  * @return 
0156  */
0157 expublic void * ndrx_ubf_tls_new(int auto_destroy, int auto_set)
0158 {
0159     int ret = EXSUCCEED;
0160     ubf_tls_t *tls  = NULL;
0161     char fn[] = "ubf_context_new";
0162     
0163     /* init they key storage */
0164     if (M_first)
0165     {
0166         MUTEX_LOCK_V(M_thdata_init);
0167         if (M_first)
0168         {
0169             pthread_key_create( &M_ubf_tls_key, 
0170                     &ndrx_ubf_tls_free );
0171             M_first = EXFALSE;
0172         }
0173         MUTEX_UNLOCK_V(M_thdata_init);
0174     }
0175     
0176     if (NULL==(tls = (ubf_tls_t *)NDRX_MALLOC(sizeof(ubf_tls_t))))
0177     {
0178         userlog ("%s: failed to malloc", fn);
0179         EXFAIL_OUT(ret);
0180     }
0181     
0182     /* do the common init... */
0183     tls->magic = UBF_TLS_MAGIG;
0184     
0185     tls->tbuf_s =0;
0186     tls->tbuf_l =0;
0187     tls->tbuf_c =0;
0188     tls->tbuf_f =0.0f;
0189     tls->tbuf_d =0.0f;
0190     tls->tbuf_p =0.0f;
0191     
0192     tls->str_buf_ptr = NULL;
0193     tls->str_dat_len = 0;
0194      
0195     tls->carray_buf_ptr= NULL;
0196     tls->carray_dat_len = 0;
0197     
0198     tls->M_ubf_error_msg_buf[0]= EXEOS;
0199     tls->M_ubf_error = BMINVAL;
0200     
0201     
0202     pthread_mutex_init(&tls->mutex, NULL);
0203     
0204     /* set callback, when thread dies, we need to get the destructor 
0205      * to be called
0206      */
0207     if (auto_destroy)
0208     {
0209         tls->is_auto = EXTRUE;
0210         pthread_setspecific( M_ubf_tls_key, (void *)tls );
0211     }
0212     else
0213     {
0214         tls->is_auto = EXFALSE;
0215     }
0216     
0217     if (auto_set)
0218     {
0219         ndrx_ubf_tls_set(tls);
0220     }
0221     
0222 out:
0223 
0224     if (EXSUCCEED!=ret && NULL!=tls)
0225     {
0226         ndrx_ubf_tls_free((char *)tls);
0227     }
0228 
0229     return (void *)tls;
0230 }
0231 
0232 /* vim: set ts=4 sw=4 et smartindent: */