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

async_server.c (4121B)


      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  * Asynchronous BCM API Server
      8  *
      9  * Most of the support routines and header definitions for async api
     10  * routines are generated by mkdispatch:
     11  *
     12  * User access:
     13  * include/bcm/async.h		user declarations of bcm_*_async routines
     14  * src/bcm/async.c		bcm_*_async routines
     15  * include/bcmx/async.h		user declarations of bcmx_*_async routines
     16  * src/bcmx/async.c		bcmx_*_async routines
     17  *
     18  * Internal async server support:
     19  * include/bcm_int/async_req.h	bcm async request definition
     20  * include/bcm_int/xasync_req.h	bcmx async request definition
     21  * src/bcm/async_run.c		execution of bcm async request
     22  * src/bcmx/async_run.c		execution of bcmx async request
     23  *
     24  * bcmx and bcm async requests share a common header format that is used
     25  * by the routines in this file.
     26  *
     27  * This file provides the actual async execution server thread and
     28  * the queueing routines.
     29  */
     30 
     31 #ifdef	BCM_ASYNC_SUPPORT
     32 
     33 #include <sal/core/sync.h>
     34 #include <sal/core/thread.h>
     35 #include <shared/alloc.h>
     36 #include <sal/appl/sal.h>	/* sal_dma_alloc, sal_dma_free */
     37 
     38 #include <bcm/types.h>
     39 #include <bcm_int/async_server.h>
     40 
     41 #define	ASYNC_THREAD_STACK	SAL_THREAD_STKSZ
     42 #define	ASYNC_THREAD_PRIO	255
     43 
     44 #define	ASYNC_LOCK		sal_mutex_take(_async_lock, sal_mutex_FOREVER)
     45 #define	ASYNC_UNLOCK		sal_mutex_give(_async_lock)
     46 #define	ASYNC_SLEEP		sal_sem_take(_async_sem, sal_sem_FOREVER)
     47 #define	ASYNC_WAKE		sal_sem_give(_async_sem)
     48 
     49 static	sal_mutex_t	_async_lock;		/* lock access to _async_req */
     50 static	sal_sem_t	_async_sem;		/* wait for async_adds */
     51 static	sal_thread_t	_async_thread = SAL_THREAD_ERROR;
     52 static	int		_async_thread_exit;
     53 
     54 static	bcm_async_req_t	*_async_req_head;
     55 static	bcm_async_req_t	*_async_req_tail;
     56 
     57 /*
     58  * Add an async request to the end of the queue
     59  */
     60 void
     61 bcm_async_add(bcm_async_req_t *req)
     62 {
     63     if (req == NULL) {
     64 	return;
     65     }
     66     if (_async_thread == SAL_THREAD_ERROR) {
     67 	if (req->callback != NULL) {
     68 	    (*req->callback)(req->cookie, BCM_E_UNAVAIL);
     69 	}
     70 	sal_free(req);
     71 	return;
     72     }
     73     ASYNC_LOCK;
     74     if (_async_req_head == NULL) {		/* empty */
     75 	_async_req_head = _async_req_tail = req;
     76     } else {
     77 	_async_req_tail->next = req;
     78 	_async_req_tail = req;
     79     }
     80     ASYNC_UNLOCK;
     81     ASYNC_WAKE;
     82 }
     83 
     84 /*
     85  * Async Server thread.
     86  * Pull an entry off the front of the queue and run it.
     87  */
     88 STATIC void
     89 _bcm_async_thread(void *cookie)
     90 {
     91     bcm_async_req_t	*req, *nreq;
     92 
     93     COMPILER_REFERENCE(cookie);
     94 
     95     _async_thread_exit = 0;
     96     for (;;) {
     97 	ASYNC_SLEEP;
     98 
     99 	/* grab a set of requests off the queue */
    100 	ASYNC_LOCK;
    101 	req = _async_req_head;
    102 	_async_req_head = _async_req_tail = NULL;
    103 	ASYNC_UNLOCK;
    104 
    105 	/* run the requests */
    106 	while (req != NULL) {
    107 	    nreq = req->next;
    108 	    (*req->run)(req);		/* bcm_async_run or bcmx_async_run */
    109 	    req = nreq;
    110 	}
    111 	if (_async_thread_exit) {
    112 	    _async_thread = SAL_THREAD_ERROR;
    113 	    sal_thread_exit(0);
    114 	    return;
    115 	}
    116     }
    117 }
    118 
    119 /*
    120  * Start the Async thread
    121  */
    122 int
    123 bcm_async_start(void)
    124 {
    125     if (_async_thread != SAL_THREAD_ERROR) {
    126 	return BCM_E_BUSY;
    127     }
    128     _async_lock = sal_mutex_create("bcm_async");
    129     _async_sem = sal_sem_create("bcm_async", sal_sem_BINARY, 0);
    130     _async_thread = sal_thread_create("bcmASYNC",
    131 				      ASYNC_THREAD_STACK,
    132 				      ASYNC_THREAD_PRIO,
    133 				      _bcm_async_thread,
    134 				      NULL);
    135     if (_async_thread == SAL_THREAD_ERROR) {
    136 	sal_sem_destroy(_async_sem);
    137 	sal_mutex_destroy(_async_lock);
    138 	_async_lock = NULL;
    139 	return BCM_E_RESOURCE;
    140     }
    141     return BCM_E_NONE;
    142 }
    143 
    144 /*
    145  * Stop the Async thread
    146  */
    147 int
    148 bcm_async_stop(void)
    149 {
    150     if (_async_thread == SAL_THREAD_ERROR) {
    151 	return BCM_E_NONE;
    152     }
    153     _async_thread_exit = 1;
    154     ASYNC_WAKE;
    155     sal_thread_yield();
    156     while (_async_thread != SAL_THREAD_ERROR) {
    157 	ASYNC_WAKE;
    158 	sal_usleep(10000);
    159     }
    160     sal_sem_destroy(_async_sem);
    161     sal_mutex_destroy(_async_lock);
    162     _async_lock = NULL;
    163     return BCM_E_NONE;
    164 }
    165 
    166 #endif	/* BCM_ASYNC_SUPPORT */
    167 
    168 int _bcm_async_server_not_empty;