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;