SimpleLink CC3120/CC3220 Host Driver  Version 2.0.1.15
Simplifies the implementation of Internet connectivity
spawn.c
1 /*
2  * Copyright (C) 2016 Texas Instruments Incorporated
3  *
4  * All rights reserved. Property of Texas Instruments Incorporated.
5  * Restricted rights to use, duplicate or disclose this code are
6  * granted through contract.
7  *
8  * The program may not be used without the written permission of
9  * Texas Instruments Incorporated or against the terms and conditions
10  * stipulated in the agreement under which this program has been supplied,
11  * and under no circumstances can it be used with non-TI connectivity device.
12  *
13  */
14 
15 
16 
17 /*****************************************************************************/
18 /* Include files */
19 /*****************************************************************************/
20 #include <ti/drivers/net/wifi/simplelink.h>
21 #include <ti/drivers/net/wifi/source/protocol.h>
22 #include <ti/drivers/net/wifi/source/driver.h>
23 
24 #if (defined (SL_PLATFORM_MULTI_THREADED)) && (!defined (SL_PLATFORM_EXTERNAL_SPAWN))
25 
26 #define _SL_MAX_INTERNAL_SPAWN_ENTRIES 10
27 
28 typedef struct _SlInternalSpawnEntry_t
29 {
30  _SlSpawnEntryFunc_t pEntry;
31  void* pValue;
32  struct _SlInternalSpawnEntry_t* pNext;
33 }_SlInternalSpawnEntry_t;
34 
35 typedef struct
36 {
37  _SlInternalSpawnEntry_t SpawnEntries[_SL_MAX_INTERNAL_SPAWN_ENTRIES];
38  _SlInternalSpawnEntry_t* pFree;
39  _SlInternalSpawnEntry_t* pWaitForExe;
40  _SlInternalSpawnEntry_t* pLastInWaitList;
41  _SlSyncObj_t SyncObj;
42  _SlLockObj_t LockObj;
43  _u8 IrqWriteCnt;
44  _u8 IrqReadCnt;
45  void* pIrqFuncValue;
46 }_SlInternalSpawnCB_t;
47 
48 _SlInternalSpawnCB_t g_SlInternalSpawnCB;
49 
50 
51 
52 void* _SlInternalSpawnTaskEntry()
53 {
54  _i16 i;
55  _SlInternalSpawnEntry_t* pEntry;
56  _u8 LastEntry;
57 
58  /* create and lock the locking object. lock in order to avoid race condition
59  on the first creation */
60  sl_LockObjCreate(&g_SlInternalSpawnCB.LockObj,"SlSpawnProtect");
61  sl_LockObjLock(&g_SlInternalSpawnCB.LockObj,SL_OS_NO_WAIT);
62 
63  /* create and clear the sync object */
64  sl_SyncObjCreate(&g_SlInternalSpawnCB.SyncObj,"SlSpawnSync");
65  sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_NO_WAIT);
66 
67  g_SlInternalSpawnCB.pFree = &g_SlInternalSpawnCB.SpawnEntries[0];
68  g_SlInternalSpawnCB.pWaitForExe = NULL;
69  g_SlInternalSpawnCB.pLastInWaitList = NULL;
70 
71  /* create the link list between the entries */
72  for (i=0 ; i<_SL_MAX_INTERNAL_SPAWN_ENTRIES - 1 ; i++)
73  {
74  g_SlInternalSpawnCB.SpawnEntries[i].pNext = &g_SlInternalSpawnCB.SpawnEntries[i+1];
75  g_SlInternalSpawnCB.SpawnEntries[i].pEntry = NULL;
76  }
77  g_SlInternalSpawnCB.SpawnEntries[i].pNext = NULL;
78 
79  g_SlInternalSpawnCB.IrqWriteCnt =0;
80  g_SlInternalSpawnCB.IrqReadCnt = 0;
81  g_SlInternalSpawnCB.pIrqFuncValue = NULL;
82 
83  SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
84 
85  /* here we ready to execute entries */
86 
87  while (TRUE)
88  {
89  sl_SyncObjWait(&g_SlInternalSpawnCB.SyncObj,SL_OS_WAIT_FOREVER);
90 
91  /* handle IRQ requests */
92  while (g_SlInternalSpawnCB.IrqWriteCnt != g_SlInternalSpawnCB.IrqReadCnt)
93  {
94  /* handle the ones that came from ISR context*/
95  _SlDrvMsgReadSpawnCtx(g_SlInternalSpawnCB.pIrqFuncValue);
96  g_SlInternalSpawnCB.IrqReadCnt++;
97  }
98 
99  /* go over all entries that already waiting for execution */
100  LastEntry = FALSE;
101 
102  do
103  {
104  /* get entry to execute */
105  SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
106 
107  pEntry = g_SlInternalSpawnCB.pWaitForExe;
108  if ( NULL == pEntry )
109  {
110  SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
111 
112  break;
113  }
114 
115  g_SlInternalSpawnCB.pWaitForExe = pEntry->pNext;
116  if (pEntry == g_SlInternalSpawnCB.pLastInWaitList)
117  {
118  g_SlInternalSpawnCB.pLastInWaitList = NULL;
119  LastEntry = TRUE;
120  }
121 
122  SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
123 
124  /* pEntry could be null in case that the sync was already set by some
125  of the entries during execution of earlier entry */
126  if (NULL != pEntry)
127  {
128  pEntry->pEntry(pEntry->pValue);
129  /* free the entry */
130 
131  SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
132 
133  pEntry->pNext = g_SlInternalSpawnCB.pFree;
134  g_SlInternalSpawnCB.pFree = pEntry;
135 
136 
137  if (NULL != g_SlInternalSpawnCB.pWaitForExe)
138  {
139  /* new entry received meanwhile */
140  LastEntry = FALSE;
141  }
142 
143  SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
144 
145  }
146 
147  }while (!LastEntry);
148  }
149 }
150 
151 
152 _i16 _SlInternalSpawn(_SlSpawnEntryFunc_t pEntry , void* pValue , _u32 flags)
153 {
154  _i16 Res = 0;
155  _SlInternalSpawnEntry_t* pSpawnEntry;
156 
157 
158  /* Increment the counter that specifies that async event has recived
159  from interrupt context and should be handled by the internal spawn task */
160  if (flags & SL_SPAWN_FLAG_FROM_SL_IRQ_HANDLER)
161  {
162  g_SlInternalSpawnCB.IrqWriteCnt++;
163  g_SlInternalSpawnCB.pIrqFuncValue = pValue;
164  SL_DRV_SYNC_OBJ_SIGNAL(&g_SlInternalSpawnCB.SyncObj);
165  return Res;
166  }
167 
168 
169  if (NULL == pEntry || (g_SlInternalSpawnCB.pFree == NULL))
170  {
171  Res = -1;
172  }
173  else
174  {
175  SL_DRV_OBJ_LOCK_FOREVER(&g_SlInternalSpawnCB.LockObj);
176 
177  pSpawnEntry = g_SlInternalSpawnCB.pFree;
178  g_SlInternalSpawnCB.pFree = pSpawnEntry->pNext;
179 
180  pSpawnEntry->pEntry = pEntry;
181  pSpawnEntry->pValue = pValue;
182  pSpawnEntry->pNext = NULL;
183 
184  if (NULL == g_SlInternalSpawnCB.pWaitForExe)
185  {
186  g_SlInternalSpawnCB.pWaitForExe = pSpawnEntry;
187  g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry;
188  }
189  else
190  {
191  g_SlInternalSpawnCB.pLastInWaitList->pNext = pSpawnEntry;
192  g_SlInternalSpawnCB.pLastInWaitList = pSpawnEntry;
193  }
194 
195  SL_DRV_OBJ_UNLOCK(&g_SlInternalSpawnCB.LockObj);
196 
197  /* this sync is called after releasing the lock object to avoid unnecessary context switches */
198  SL_DRV_SYNC_OBJ_SIGNAL(&g_SlInternalSpawnCB.SyncObj);
199  }
200 
201  return Res;
202 }
203 
204 
205 
206 
207 
208 #endif