Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief System tests, firstly Thread Local Storage (TLS) must work
0003  *
0004  * @file atmiclt0.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 #include <string.h>
0035 #include <stdio.h>
0036 #include <stdlib.h>
0037 #include <memory.h>
0038 #include <pthread.h>
0039 #include <unistd.h>
0040 #include <ndrstandard.h>
0041 #include <errno.h>
0042 #include <sys/time.h>
0043 
0044 #include <ndebug.h>
0045 #include <sys_unix.h>
0046 
0047 #include "test000.h"
0048 
0049 /*---------------------------Externs------------------------------------*/
0050 /*---------------------------Macros-------------------------------------*/
0051 /*---------------------------Enums--------------------------------------*/
0052 /*---------------------------Typedefs-----------------------------------*/
0053 /*---------------------------Globals------------------------------------*/
0054 /*---------------------------Statics------------------------------------*/
0055 /* for osx tests: */
0056 exprivate pthread_mutex_t M_mut = PTHREAD_MUTEX_INITIALIZER;
0057 exprivate pthread_cond_t M_cond = PTHREAD_COND_INITIALIZER;
0058 /*---------------------------Prototypes---------------------------------*/
0059 
0060 __thread int M_field;
0061 
0062 void *M_ptrs[3] = {NULL, NULL, NULL};
0063 
0064 void* t1(void *arg)
0065 {    
0066     M_ptrs[1] = &M_field;
0067     sleep(1);
0068     return NULL;
0069 }
0070 
0071 void* t2(void *arg)
0072 {   
0073     M_ptrs[2] = &M_field;
0074     sleep(1);
0075     return NULL;
0076 }
0077 
0078 #ifdef EX_OS_DARWIN
0079 
0080 void tim(void)
0081 {
0082  time_t timer;
0083     char buffer[26];
0084     struct tm* tm_info;
0085 
0086     timer = time(NULL);
0087     tm_info = localtime(&timer);
0088 
0089     strftime(buffer, 26, "%Y-%m-%d %H:%M:%S", tm_info);
0090     fprintf(stderr, "%s\n", buffer);
0091 
0092 }
0093 
0094 /**
0095  * Check the busy field..
0096  * ptrs shall match..
0097  */
0098 void* osx_chk_thread(void *arg)
0099 {
0100     ndrx_osx_pthread_cond_t *p_cond;
0101     p_cond = (ndrx_osx_pthread_cond_t *)&M_cond;
0102 
0103     /* wait on thread */
0104     MUTEX_LOCK_V(M_mut);
0105 
0106     /*let other thread to set the fields.. inside of pthread_cond_wait() */
0107     sleep(1);
0108     if ((char *)p_cond->busy != (char *)&M_mut)
0109     {
0110         /* check for https://github.com/apple/darwin-libpthread/blob/master/src/pthread_cond.c updates
0111          * and fix for given OSX version, needs to add some macros...
0112          */
0113         fprintf(stderr, "Cannot access busy field of Darwin pthread library for cond var: %p vs %p\n",
0114                 p_cond->busy, &M_mut);
0115         exit(-1);
0116     }
0117     else
0118     {
0119         fprintf(stderr, "Cond var: %p vs %p OK\n", p_cond->busy, &M_mut);
0120     }
0121     
0122     pthread_cond_signal( &M_cond ); 
0123     MUTEX_UNLOCK_V( M_mut );
0124 
0125     return NULL;
0126 }
0127 
0128 /**
0129  * Check that we have access to cond variable internals...
0130  * and it still works as in 08/02/2020.
0131  * @return EXSUCCED / EXFAIL
0132  */
0133 int osx_chk_cond_work_around(void)
0134 {
0135     int ret = EXSUCCEED;
0136     ndrx_osx_pthread_cond_t *p_cond;
0137     
0138     pthread_t valth={0};
0139     p_cond = (ndrx_osx_pthread_cond_t *)&M_cond;
0140 
0141     MUTEX_LOCK_V(M_mut);
0142 
0143     if( (ret=pthread_create( &valth, NULL, osx_chk_thread, NULL)) != 0)
0144     {
0145         fprintf(stderr, "Failed to create thread: %d", ret);
0146         return EXFAIL;
0147     }
0148 
0149     p_cond->busy = NULL;
0150     ret = pthread_cond_wait(&M_cond, &M_mut);
0151     fprintf(stderr, "pthread_cond_wait 2: ret=%d (%s) mut=%p\n", ret, strerror(ret), &M_mut);
0152 
0153     if (EXSUCCEED!=ret)
0154     {
0155         fprintf(stderr, "ret=%d Expected 0\n", ret);
0156         return EXFAIL;
0157     }
0158 
0159     MUTEX_UNLOCK_V(M_mut);
0160     
0161     pthread_join( valth, NULL );
0162     
0163     ret = EXSUCCEED;
0164     
0165 out:
0166     return ret;    
0167 
0168 }
0169 #endif
0170 
0171 int main( int argc , char **argv )
0172 {
0173     pthread_t pth1={0}, pth2={0};
0174     void *mb1=0, *mb2 =0;
0175     pthread_attr_t pthrat={0};
0176     pthread_attr_init(&pthrat);
0177     pthread_attr_setstacksize(&pthrat, 1<<20);
0178     unsigned int n_pth=0;
0179     
0180     
0181 #ifdef EX_OS_DARWIN
0182     
0183     if (EXSUCCEED!=osx_chk_cond_work_around())
0184     {
0185         fprintf(stderr, "OSX PTHREAD_PROCESS_SHARED Cond variable work-a-round does not work!\n");
0186         return EXFAIL;
0187     }
0188     
0189 #endif
0190 
0191     M_ptrs[0] = &M_field;
0192 
0193     if( pthread_create( &pth1, &pthrat, t1,&mb1) == 0)
0194         n_pth += 1;
0195     if( pthread_create( &pth2, &pthrat, t2,&mb2) == 0)
0196         n_pth += 1;
0197     if( n_pth > 0 )
0198         pthread_join( pth1, &mb1 );
0199     if( n_pth > 1 )
0200         pthread_join( pth2, &mb2 );
0201     pthread_attr_destroy(&pthrat);
0202 
0203     fprintf(stderr,"main : %p %p %p\n", M_ptrs[0], M_ptrs[1], M_ptrs[2]);
0204 
0205     if (M_ptrs[0] == M_ptrs[1] || M_ptrs[0] == M_ptrs[2] ||
0206             M_ptrs[1] == M_ptrs[2])
0207     {
0208         fprintf(stderr, "TESTERROR: Thread Local Storage not working!\n");
0209         return -1;
0210     }
0211     else
0212     {
0213         fprintf(stderr, "Thread Local Storage OK!\n");
0214         return 0;
0215     }
0216 }
0217 
0218 
0219 /* vim: set ts=4 sw=4 et smartindent: */