Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief Darwin Abstraction Layer (DAL)
0003  *
0004  * @file sys_darwin.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 <stdio.h>
0037 #include <stdlib.h>
0038 
0039 #include <unistd.h>
0040 #include <stdarg.h>
0041 #include <ctype.h>
0042 #include <memory.h>
0043 #include <errno.h>
0044 #include <signal.h>
0045 #include <limits.h>
0046 #include <pthread.h>
0047 #include <string.h>
0048 #include <mach/mach_time.h>
0049 
0050 #include <ndrstandard.h>
0051 #include <ndebug.h>
0052 #include <nstdutil.h>
0053 #include <limits.h>
0054 #include <sys_unix.h>
0055 #include <utlist.h>
0056 
0057 
0058 /*---------------------------Externs------------------------------------*/
0059 /*---------------------------Macros-------------------------------------*/
0060 #define MT_NANO (+1.0E-9)
0061 #define MT_GIGA UINT64_C(1000000000)
0062 /*---------------------------Enums--------------------------------------*/
0063 /*---------------------------Typedefs-----------------------------------*/
0064 /*---------------------------Globals------------------------------------*/
0065 /*---------------------------Statics------------------------------------*/
0066 /* TODO create a list of timers,*/
0067 static double mt_timebase = 0.0;
0068 static uint64_t mt_timestart = 0;
0069 /*---------------------------Prototypes---------------------------------*/
0070 
0071 /**
0072  * Return list of message queues (actually it is list of named pipes
0073  * as work around for missing posix queue listing functions.
0074  */
0075 expublic string_list_t* ndrx_sys_mqueue_list_make_pl(char *qpath, int *return_status)
0076 {
0077     return ndrx_sys_folder_list(qpath, return_status);
0078 }
0079 
0080 #ifndef EX_OS_DARWIN_HAVE_CLOCK
0081 /* TODO be more careful in a multithreaded environement */
0082 expublic int clock_gettime(clockid_t clk_id, struct timespec *tp)
0083 {
0084     kern_return_t retval = KERN_SUCCESS;
0085     if( clk_id == TIMER_ABSTIME)
0086     {
0087         if (!mt_timestart)
0088         { 
0089             /* only one timer, initilized on the first call to the TIMER */
0090             mach_timebase_info_data_t tb = { 0 };
0091             mach_timebase_info(&tb);
0092             mt_timebase = tb.numer;
0093             mt_timebase /= tb.denom;
0094             mt_timestart = mach_absolute_time();
0095         }
0096 
0097         double diff = (mach_absolute_time() - mt_timestart) * mt_timebase;
0098         tp->tv_sec = diff * MT_NANO;
0099         tp->tv_nsec = diff - (tp->tv_sec * MT_GIGA);
0100     }
0101     else
0102     {
0103         /* other clk_ids are mapped to the coresponding mach clock_service */
0104         clock_serv_t cclock;
0105         mach_timespec_t mts;
0106 
0107         host_get_clock_service(mach_host_self(), clk_id, &cclock);
0108         retval = clock_get_time(cclock, &mts);
0109         mach_port_deallocate(mach_task_self(), cclock);
0110 
0111         tp->tv_sec = mts.tv_sec;
0112         tp->tv_nsec = mts.tv_nsec;
0113     }
0114 
0115     return retval;
0116 }
0117 #endif
0118 
0119 /**
0120  * Test the pid to contain regexp 
0121  * @param pid process id to test
0122  * @param p_re compiled regexp to test against
0123  * @return -1 failed, 0 - not matched, 1 - matched
0124  */
0125 expublic int ndrx_sys_env_test(pid_t pid, regex_t *p_re)
0126 {
0127     return ndrx_sys_cmdout_test("ps eww %d", pid, p_re);
0128 }
0129 
0130 /**
0131  * Pthreads spinlock emulation, init
0132  * @param lock spinlock
0133  * @param pshared (not used)
0134  * @return EXSUCCEED
0135  */
0136 expublic int pthread_spin_init(pthread_spinlock_t *lock, int pshared)
0137 {
0138 
0139 #ifdef  __arm64__
0140    asm volatile("dmb sy");
0141 #else
0142     __asm__ __volatile__ ("" ::: "memory");
0143 #endif
0144     *lock = 0;
0145     return EXSUCCEED;
0146 }
0147 
0148 /**
0149  * Destroy spinlock (does nothing)
0150  * @param lock spinlock var
0151  * @return EXSUCCEED
0152  */
0153 expublic int pthread_spin_destroy(pthread_spinlock_t *lock)
0154 {
0155     return EXSUCCEED;
0156 }
0157 
0158 /**
0159  * Acquire spin lock
0160  * @param lock lock variable
0161  * @return EXSUCCEED
0162  */
0163 expublic int pthread_spin_lock(pthread_spinlock_t *lock)
0164 {
0165     while (1) 
0166     {
0167         int i;
0168         for (i=0; i < 10000; i++) 
0169         {
0170             if (__sync_bool_compare_and_swap(lock, 0, 1)) 
0171             {
0172                 return EXSUCCEED;
0173             }
0174         }
0175         sched_yield();
0176     }
0177     
0178 }
0179 
0180 /**
0181  * Try lock to acquire lock
0182  * @param lock lock variable
0183  * @return EXSUCCEED/EBUSY
0184  */
0185 expublic int pthread_spin_trylock(pthread_spinlock_t *lock) 
0186 {
0187     if (__sync_bool_compare_and_swap(lock, 0, 1)) 
0188     {
0189         return EXSUCCEED;
0190     }
0191     return EBUSY;
0192 }
0193 
0194 /**
0195  * Unlock variable
0196  * @param lock spin lock variable
0197  * @return EXSUCCEED
0198  */
0199 expublic int pthread_spin_unlock(pthread_spinlock_t *lock) 
0200 {
0201 #ifdef  __arm64__
0202    asm volatile("dmb sy");
0203 #else
0204     __asm__ __volatile__ ("" ::: "memory");
0205 #endif
0206     *lock = 0;
0207     return EXSUCCEED;
0208 }
0209 
0210 /* vim: set ts=4 sw=4 et smartindent: */