openbcm

Git mirror of https://github.com/Broadcom-Network-Switching-Software/OpenBCM
git clone git://git.finwo.net/mirror/broadcom/openbcm
Log | Files | Refs | README

spl.c (3787B)


      1 /*
      2  * 
      3  * This license is set out in https://raw.githubusercontent.com/Broadcom-Network-Switching-Software/OpenBCM/master/Legal/LICENSE file.
      4  * 
      5  * Copyright 2007-2019 Broadcom Inc. All rights reserved.
      6  *
      7  * File: 	spl.c
      8  * Purpose:	Interrupt Blocking
      9  */
     10 #if defined(LINUX) || defined(linux) || defined(__linux__)
     11 #define _XOPEN_SOURCE 600
     12 #endif
     13 #include <sys/types.h>
     14 #include <signal.h>
     15 #include <assert.h>
     16 #include <sal/core/sync.h>
     17 #include <pthread.h>
     18 
     19 /*
     20  *  To improve spl lock performance, pthread_mutex_lock/pthread_mutex_unlock
     21  *  is used by default.
     22  *  Define SAL_SPL_USE_SAL_MUTEX to use sal_mutex on the spl lock.
     23  */
     24 #ifdef SAL_SPL_USE_SAL_MUTEX
     25 static sal_mutex_t spl_mutex;
     26 #define SAL_SPL_LOCK_INIT(m) m = sal_mutex_create("spl mutex")
     27 #define SAL_SPL_LOCK(m)      sal_mutex_take(m, sal_mutex_FOREVER)
     28 #define SAL_SPL_UNLOCK(m)    sal_mutex_give(m)
     29 #else
     30 static pthread_mutex_t spl_mutex;
     31 #define SAL_SPL_LOCK_INIT(m) \
     32     do {\
     33         pthread_mutexattr_t attr;\
     34         pthread_mutexattr_init(&attr);\
     35         pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);\
     36         pthread_mutex_init(&m, &attr);\
     37     } while(0)
     38 #define SAL_SPL_LOCK(m)      pthread_mutex_lock(&m)
     39 #define SAL_SPL_UNLOCK(m)    pthread_mutex_unlock(&m)
     40 #endif /* SAL_SPL_USE_SAL_MUTEX */
     41 
     42 static int spl_level;
     43 
     44 /*
     45  * Function:
     46  *	sal_spl_init
     47  * Purpose:
     48  *	Initialize the synchronization portion of the SAL
     49  * Returns:
     50  *	0 on success, -1 on failure
     51  */
     52 
     53 int
     54 sal_spl_init(void)
     55 {
     56     /* Initialize spl */
     57     SAL_SPL_LOCK_INIT(spl_mutex);
     58     spl_level = 0;
     59 
     60     return 0;
     61 }
     62 
     63 /*
     64  * Function:
     65  *	sal_spl
     66  * Purpose:
     67  *	Set interrupt level.
     68  * Parameters:
     69  *	level - interrupt level to set.
     70  * Returns:
     71  *	Value of interrupt level in effect prior to the call.
     72  * Notes:
     73  *	Used most often to restore interrupts blocked by sal_splhi.
     74  */
     75 
     76 int
     77 sal_spl(int level)
     78 {
     79 #ifdef SAL_SPL_NO_PREEMPT
     80     struct sched_param param;
     81     int policy;
     82 
     83     if (pthread_getschedparam(pthread_self(), &policy, &param) == 0) {
     84         /* Interrupt thread uses SCHED_RR and should be left alone */
     85         if (policy != SCHED_RR) {
     86             /* setting sched_priority to 0 will only change the real time priority
     87                of the thread. For a non real time thread it should be 0. This is
     88                very Linux specific.
     89              */  
     90             param.sched_priority = 0;
     91             pthread_setschedparam(pthread_self(), SCHED_OTHER, &param);
     92         }
     93     }
     94 #endif
     95     assert(level == spl_level);
     96     spl_level--;
     97     SAL_SPL_UNLOCK(spl_mutex);
     98     return 0;
     99 }
    100 
    101 /*
    102  * Function:
    103  *	sal_splhi
    104  * Purpose:
    105  *	Set interrupt mask to highest level.
    106  * Parameters:
    107  *	None
    108  * Returns:
    109  *	Value of interrupt level in effect prior to the call.
    110  */
    111 
    112 int
    113 sal_splhi(void)
    114 {
    115 #ifdef SAL_SPL_NO_PREEMPT
    116     struct sched_param param;
    117     int policy;
    118 
    119     if (pthread_getschedparam(pthread_self(), &policy, &param) == 0) {
    120         /* Interrupt thread uses SCHED_RR and should be left alone */
    121         if (policy != SCHED_RR) {
    122             param.sched_priority = 90;
    123             pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
    124         }
    125     }
    126 #endif
    127     SAL_SPL_LOCK(spl_mutex);
    128     return ++spl_level;
    129 }
    130 
    131 /*
    132  * Function:
    133  *	sal_int_context
    134  * Purpose:
    135  *	Return TRUE if running in interrupt context.
    136  * Parameters:
    137  *	None
    138  * Returns:
    139  *	Boolean
    140  */
    141 
    142 int
    143 sal_int_context(void)
    144 {
    145     /* Must be provided by the virtual interrupt controller */
    146     extern int intr_int_context() __attribute__((weak)); 
    147     
    148     if (intr_int_context) {
    149         return intr_int_context();
    150     } else {
    151         return 0;
    152     }
    153 }
    154 
    155 /*
    156  * Function:
    157  *	sal_no_sleep
    158  * Purpose:
    159  *	Return TRUE if current context cannot sleep.
    160  * Parameters:
    161  *	None
    162  * Returns:
    163  *	Boolean
    164  */
    165 
    166 int
    167 sal_no_sleep(void)
    168 {
    169     return 0;
    170 }