Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief System platform related utilities
0003  *
0004  * @file platform.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 <ndrstandard.h>
0037 #include <time.h>
0038 #include <sys/time.h>
0039 #include <stdlib.h>
0040 #include <string.h>
0041 #include <stdio.h>
0042 #include <sys/stat.h>
0043 #include <ctype.h>
0044 #include <pthread.h>
0045 #include <nstd_tls.h>
0046 
0047 #include "nstdutil.h"
0048 #include "ndebug.h"
0049 #include "userlog.h"
0050 #include <errno.h>
0051 #include <sys/resource.h>
0052 #include <ndrxdiag.h>
0053 /*---------------------------Externs------------------------------------*/
0054 /*---------------------------Macros-------------------------------------*/
0055 /*---------------------------Enums--------------------------------------*/
0056 /*---------------------------Typedefs-----------------------------------*/
0057 /*---------------------------Globals------------------------------------*/
0058 /*---------------------------Statics------------------------------------*/
0059 exprivate long M_stack_size = EXFAIL;    /* Current stack size */
0060 
0061 exprivate MUTEX_LOCKDECL(M_stack_size_lock);
0062 
0063 /*---------------------------Prototypes---------------------------------*/
0064 
0065 /**
0066  * Diagnostic for pthread_create
0067  * @param file source file
0068  * @param line source line
0069  * @param NDRX_DIAG_* code
0070  * @param msg module message
0071  * @param err errno after the pthread_create() failed.
0072  */
0073 expublic void ndrx_platf_diag(char *file, long line, int code, int err, char *msg)
0074 {
0075     switch (code)
0076     {
0077         case NDRX_DIAG_PTHREAD_CREATE:
0078             
0079             NDRX_LOG(log_always, "Failed to pthread_create() for %s (%d): %s, at %s:%ld", 
0080                     msg, errno, strerror(errno), file, line);
0081             userlog("Failed to pthread_create() for %s (%d): %s, at %s:%ld", 
0082                     msg, errno, strerror(errno), file, line);
0083 
0084             if (ENOMEM==err || EINVAL==err)
0085             {
0086 #ifdef EX_OS_AIX
0087                 NDRX_LOG(log_always, "Check thread specific resource "
0088                         "settings e.g. NDRX_THREADSTACKSIZE. For AIX ulimit -s "
0089                         "is setting global stack limit to all threads! Do limit "
0090                         "with NDRX_THREADSTACKSIZE", code);
0091                 userlog("Check thread specific resource "
0092                         "settings e.g. NDRX_THREADSTACKSIZE. For AIX ulimit -s "
0093                         "is setting global stack limit to all threads! Do limit "
0094                         "with NDRX_THREADSTACKSIZE", code);
0095 #else
0096                 NDRX_LOG(log_always, "Check thread specific resource "
0097                         "settings e.g. NDRX_THREADSTACKSIZE", code);
0098                 userlog("Check thread specific resource settings "
0099                         "e.g. NDRX_THREADSTACKSIZE", code);
0100 #endif
0101             }
0102         break;
0103     }
0104 }
0105 
0106 /**
0107  * Return stack size configured for system
0108  * @return EXFAIL or stack size
0109  */
0110 expublic long ndrx_platf_stack_get_size(void)
0111 {
0112     struct rlimit limit;
0113     char *p;
0114     
0115     if (EXFAIL==M_stack_size)
0116     {
0117         /* lock */
0118         MUTEX_LOCK_V(M_stack_size_lock);
0119         
0120         if (EXFAIL==M_stack_size)
0121         {
0122             if (NULL!=(p=getenv(CONF_NDRX_THREADSTACKSIZE)))
0123             {
0124                 M_stack_size=atoi(p)*1024;
0125                 
0126                 /* we use default stack size... */
0127                 if (0==M_stack_size)
0128                 {
0129                     NDRX_LOG(log_info, "Using OS Default new thread stack size...");
0130                 }
0131             }
0132             else
0133             {
0134                 /* use 8MB default, if setting not present */
0135                 M_stack_size=NDRX_STACK_MAX;
0136             }
0137             
0138             /* if it was set to -1 */
0139             if (M_stack_size < 0)
0140             {
0141                 if (EXSUCCEED!=getrlimit (RLIMIT_STACK, &limit))
0142                 {
0143                     int err = errno;
0144                     NDRX_LOG(log_error, "Failed to get stack size: %s", strerror(err));
0145                     userlog("Failed to get stack size: %s", strerror(err));
0146                 }
0147                 else
0148                 {
0149                     M_stack_size=limit.rlim_cur;
0150 
0151                     NDRX_LOG(log_info, "Current stack size: %ld, max: %ld", 
0152                             M_stack_size,  (long)limit.rlim_max);
0153                 }
0154             }
0155             
0156             if (M_stack_size<0)
0157             {
0158                 M_stack_size = NDRX_STACK_MAX;
0159                 NDRX_LOG(log_warn, "Unlimited stack, setting to %ld bytes",
0160                         M_stack_size);
0161             }
0162         }
0163         MUTEX_UNLOCK_V(M_stack_size_lock);
0164     }
0165     
0166 out:
0167     return M_stack_size;
0168 }
0169 
0170 /**
0171  * Configure the stack size in the loop
0172  * seems like AIX RLIMITS might say one value but accepts another
0173  * Thus try in loop to reduce the stack until it is accepted
0174  * @param pthread_custom_attr ptr to pthread_attr_t attr to set
0175  */
0176 expublic void ndrx_platf_stack_set(void *pthread_custom_attr)
0177 {
0178     long ssize = ndrx_platf_stack_get_size();
0179     int ret;
0180     pthread_attr_t *pattr = (pthread_attr_t *)pthread_custom_attr;
0181     
0182     if (ssize>0)
0183     {
0184         while (EXSUCCEED!=(ret = pthread_attr_setstacksize(pattr, ssize)) 
0185                 && EINVAL==ret
0186                 && ssize > 0)
0187         {
0188             ssize /= 2;
0189         }
0190 
0191         if (0==ssize)
0192         {
0193             userlog("Error ! failed to set stack value!");
0194         }
0195     }
0196     /* else use default stack... */
0197     
0198 }
0199 
0200 /* vim: set ts=4 sw=4 et smartindent: */