| LPCOpen Platform v1.03 LPCOpen Platform for NXP LPC Microcontrollers

- Main Page
- Modules
- Data Structures
- Files
- Related Pages

- File List
- Globals

All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
os_tls.c
Go to the documentation of this file.
1 /*
2 ************************************************************************************************************************
3 * uC/OS-III
4 * The Real-Time Kernel
5 *
6 * (c) Copyright 2009-2012; Micrium, Inc.; Weston, FL
7 * All rights reserved. Protected by international copyright laws.
8 *
9 * THREAD LOCAL STORAGE (TLS) MANAGEMENT
10 * Cross Core Embedded Studio (CCES) IMPLEMENTATION
11 *
12 * File : OS_TLS.C
13 * By : JJL
14 * Version : V3.03.00
15 *
16 * LICENSING TERMS:
17 * ---------------
18 * uC/OS-III is provided in source form for FREE short-term evaluation, for educational use or
19 * for peaceful research. If you plan or intend to use uC/OS-III in a commercial application/
20 * product then, you need to contact Micrium to properly license uC/OS-III for its use in your
21 * application/product. We provide ALL the source code for your convenience and to help you
22 * experience uC/OS-III. The fact that the source is provided does NOT mean that you can use
23 * it commercially without paying a licensing fee.
24 *
25 * Knowledge of the source code may NOT be used to develop a similar product.
26 *
27 * Please help us continue to provide the embedded community with the finest software available.
28 * Your honesty is greatly appreciated.
29 *
30 * You can contact us at www.micrium.com, or by phone at +1 (954) 217-2036.
31 ************************************************************************************************************************
32 */
33
34 #define MICRIUM_SOURCE
35 #include <os.h>
36
37 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
38 const CPU_CHAR *os_tls__c = "$Id: $";
39 #endif
40
41 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
42 /*
43 ************************************************************************************************************************
44 * LOCAL VARIABLES
45 ************************************************************************************************************************
46 */
47
48 static CPU_DATA OS_TLS_NextAvailID; /* Next available TLS ID */
49 static OS_TLS_DESTRUCT_PTR OS_TLS_DestructPtrTbl[OS_CFG_TLS_TBL_SIZE];
50
51 /*$PAGE*/
52 /*
53 ************************************************************************************************************************
54 * ALLOCATE THE NEXT AVAILABLE TLS ID
55 *
56 * Description: This function is called to obtain the ID of the next free TLS (Task Local Storage) register 'id'
57 *
58 * Arguments : p_err is a pointer to a variable that will hold an error code related to this call.
59 *
60 * OS_ERR_NONE if the call was successful
61 * OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS than you declared
62 * available through OS_CFG_TLS_TBL_SIZE.
63 *
64 * Returns : The next available TLS 'id' or OS_CFG_TLS_TBL_SIZE if an error is detected.
65 ************************************************************************************************************************
66 */
67
68 OS_TLS_ID OS_TLS_GetID (OS_ERR *p_err)
69 {
70 OS_TLS_ID id;
71 CPU_SR_ALLOC();
72
73
74
75 #ifdef OS_SAFETY_CRITICAL
76 if (p_err == (OS_ERR *)0) {
77 OS_SAFETY_CRITICAL_EXCEPTION();
78 return ((OS_TLS_ID)OS_CFG_TLS_TBL_SIZE);
79 }
80 #endif
81
82 CPU_CRITICAL_ENTER();
83 if (OS_TLS_NextAvailID >= OS_CFG_TLS_TBL_SIZE) { /* See if we exceeded the number of IDs available */
84 *p_err = OS_ERR_TLS_NO_MORE_AVAIL; /* Yes, cannot allocate more TLS */
85 CPU_CRITICAL_EXIT();
86 return ((OS_TLS_ID)OS_CFG_TLS_TBL_SIZE);
87 }
88
89 id = OS_TLS_NextAvailID;
90 OS_TLS_NextAvailID++;
91 CPU_CRITICAL_EXIT();
92 *p_err = OS_ERR_NONE;
93 return (id);
94 }
95
96 /*$PAGE*/
97 /*
98 ************************************************************************************************************************
99 * GET THE CURRENT VALUE OF A TLS REGISTER
100 *
101 * Description: This function is called to obtain the current value of a TLS register
102 *
103 * Arguments : p_tcb is a pointer to the OS_TCB of the task you want to read the TLS register from. If 'p_tcb' is
104 * a NULL pointer then you will get the TLS register of the current task.
105 *
106 * id is the 'id' of the desired TLS register. Note that the 'id' must be less than
107 * 'OS_TLS_NextAvailID'
108 *
109 * p_err is a pointer to a variable that will hold an error code related to this call.
110 *
111 * OS_ERR_NONE if the call was successful
112 * OS_ERR_OS_NOT_RUNNING if the kernel has not started yet
113 * OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to OS_TLS_NextAvailID
114 * OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not
115 * needed for the task
116 *
117 * Returns : The current value of the task's TLS register or 0 if an error is detected.
118 *
119 * Note(s) : 1) p_tcb->Opt contains options passed to OSTaskCreate(). One of these options (OS_OPT_TASK_NO_TLS) is
120 * used to specify that the user doesn't want TLS support for the task being created. In other words,
121 * by default, TLS support is enabled if OS_CFG_TLS_TBL_SIZE is defined and > 0 so the user must
122 * specifically indicate that he/she doesn't want TLS supported for a task.
123 ************************************************************************************************************************
124 */
125
126 OS_TLS OS_TLS_GetValue (OS_TCB *p_tcb,
127 OS_TLS_ID id,
128 OS_ERR *p_err)
129 {
130 OS_TLS value;
131 CPU_SR_ALLOC();
132
133
134
135 #ifdef OS_SAFETY_CRITICAL
136 if (p_err == (OS_ERR *)0) {
137 OS_SAFETY_CRITICAL_EXCEPTION();
138 return ((OS_TLS)0);
139 }
140 #endif
141
142
143 #if OS_CFG_ARG_CHK_EN > 0u
144 if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */
145 *p_err = OS_ERR_TLS_ID_INVALID;
146 return ((OS_TLS)0);
147 }
148 #endif
149
150 CPU_CRITICAL_ENTER();
151 if (p_tcb == (OS_TCB *)0) { /* Does caller want to use current task's TCB? */
152 p_tcb = OSTCBCurPtr; /* Yes */
153 if (OSTCBCurPtr == (OS_TCB *)0) { /* Is the kernel running? */
154 CPU_CRITICAL_EXIT(); /* No, then caller cannot specify NULL */
155 *p_err = OS_ERR_OS_NOT_RUNNING;
156 return ((OS_TLS)0);
157 }
158 }
159 if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
160 value = p_tcb->TLS_Tbl[id]; /* Yes */
161 CPU_CRITICAL_EXIT();
162 *p_err = OS_ERR_NONE;
163 return ((OS_TLS)value);
164 } else {
165 CPU_CRITICAL_EXIT(); /* No */
166 *p_err = OS_ERR_TLS_NOT_EN;
167 return ((OS_TLS)0);
168 }
169 }
170
171 /*$PAGE*/
172 /*
173 ************************************************************************************************************************
174 * DEFINE TLS DESTRUCTOR FUNCTION
175 *
176 * Description: This function is called by the user to assign a 'destructor' function to a specific TLS. When a task is
177 * deleted, all the destructors are called for all the task's TLS for which there is a destructor function
178 * defined. In other when a task is deleted, all the non-NULL functions present in OS_TLS_DestructPtrTbl[]
179 * will be called.
180 *
181 * Arguments : id is the ID of the TLS destructor to set
182 *
183 * p_destruct is a pointer to a function that is associated with a specific TLS register and is called when
184 * a task is deleted. The prototype of such functions is:
185 *
186 * void MyDestructFunction (OS_TCB *p_tcb,
187 * OS_TLS_ID id,
188 * OS_TLS value);
189 *
190 * you can specify a NULL pointer if you don't want to have a fucntion associated with a TLS
191 * register. A NULL pointer (i.e. no function associated with a TLS register) is the default
192 * value placed in OS_TLS_DestructPtrTbl[].
193 *
194 * p_err is a pointer to an error return code. The possible values are:
195 *
196 * OS_ERR_NONE The call was successful.
197 * OS_ERR_TLS_ID_INVALID You you specified an invalid TLS ID
198 * OS_ERR_TLS_DESTRUCT_ASSIGNED If a destructor has already been assigned to the TLS ID
199 *
200 * Returns : none
201 *
202 * Note : none
203 ************************************************************************************************************************
204 */
205
206 void OS_TLS_SetDestruct (OS_TLS_ID id,
207 OS_TLS_DESTRUCT_PTR p_destruct,
208 OS_ERR *p_err)
209 {
210 CPU_SR_ALLOC();
211
212
213 #ifdef OS_SAFETY_CRITICAL
214 if (p_err == (OS_ERR *)0) {
215 OS_SAFETY_CRITICAL_EXCEPTION();
216 return;
217 }
218 #endif
219
220 if (id >= OS_TLS_NextAvailID) { /* See if we exceeded the number of TLS IDs available */
221 *p_err = OS_ERR_TLS_ID_INVALID;
222 return;
223 }
224
225 if (OS_TLS_DestructPtrTbl[id] != (OS_TLS_DESTRUCT_PTR)0) { /* Can only assign a destructor once */
226 *p_err = OS_ERR_TLS_DESTRUCT_ASSIGNED;
227 return;
228 }
229
230 CPU_CRITICAL_ENTER();
231 OS_TLS_DestructPtrTbl[id] = p_destruct;
232 CPU_CRITICAL_EXIT();
233 *p_err = OS_ERR_NONE;
234 }
235
236 /*$PAGE*/
237 /*
238 ************************************************************************************************************************
239 * SET THE CURRENT VALUE OF A TASK TLS REGISTER
240 *
241 * Description: This function is called to change the current value of a task TLS register.
242 *
243 * Arguments : p_tcb is a pointer to the OS_TCB of the task you want to set the task's TLS register for. If 'p_tcb'
244 * is a NULL pointer then you will change the TLS register of the current task.
245 *
246 * id is the 'id' of the desired task TLS register. Note that the 'id' must be less than
247 * 'OS_TLS_NextAvailID'
248 *
249 * value is the desired value for the task TLS register.
250 *
251 * p_err is a pointer to a variable that will hold an error code related to this call.
252 *
253 * OS_ERR_NONE if the call was successful
254 * OS_ERR_OS_NOT_RUNNING if the kernel has not started yet
255 * OS_ERR_TLS_ID_INVALID if you specified an invalid TLS ID
256 * OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not
257 * needed for the task
258 *
259 * Returns : none
260 *
261 * Note(s) : 1) p_tcb->Opt contains options passed to OSTaskCreate(). One of these options (OS_OPT_TASK_NO_TLS) is
262 * used to specify that the user doesn't want TLS support for the task being created. In other words,
263 * by default, TLS support is enabled if OS_CFG_TLS_TBL_SIZE is defined and > 0 so the user must
264 * specifically indicate that he/she doesn't want TLS supported for a task.
265 ************************************************************************************************************************
266 */
267
268 void OS_TLS_SetValue (OS_TCB *p_tcb,
269 OS_TLS_ID id,
270 OS_TLS value,
271 OS_ERR *p_err)
272 {
273 CPU_SR_ALLOC();
274
275
276
277 #ifdef OS_SAFETY_CRITICAL
278 if (p_err == (OS_ERR *)0) {
279 OS_SAFETY_CRITICAL_EXCEPTION();
280 return;
281 }
282 #endif
283
284 #if OS_CFG_ARG_CHK_EN > 0u
285 if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */
286 *p_err = OS_ERR_TLS_ID_INVALID;
287 return;
288 }
289 #endif
290
291 CPU_CRITICAL_ENTER(); /* Does caller want to use current task's TCB? */
292 if (p_tcb == (OS_TCB *)0) { /* Yes */
293 p_tcb = OSTCBCurPtr; /* Is the kernel running? */
294 if (OSTCBCurPtr == (OS_TCB *)0) { /* No, then caller cannot specify NULL */
295 CPU_CRITICAL_EXIT();
296 *p_err = OS_ERR_OS_NOT_RUNNING;
297 return;
298 }
299 }
300 if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
301 p_tcb->TLS_Tbl[id] = value; /* Yes */
302 CPU_CRITICAL_EXIT();
303 *p_err = OS_ERR_NONE;
304 } else {
305 CPU_CRITICAL_EXIT(); /* No */
306 *p_err = OS_ERR_TLS_NOT_EN;
307 }
308 }
309
310 /*$PAGE*/
311 /*
312 ************************************************************************************************************************
313 ************************************************************************************************************************
314 * uC/OS-III INTERNAL FUNCTIONS
315 * DO NOT CALL FROM THE APPLICATION CODE
316 ************************************************************************************************************************
317 ************************************************************************************************************************
318 */
319
320 /*
321 ************************************************************************************************************************
322 * INITIALIZE THE TASK LOCAL STORAGE SERVICES
323 *
324 * Description: This function is called by uC/OS-III to initialize the TLS id allocator.
325 *
326 * This function also initializes an array containing function pointers. There is one function associated
327 * to each task TLS register and all the functions (assuming non-NULL) will be called when the task is
328 * deleted.
329 *
330 * Arguments : p_err is a pointer to an error return value. Current error can be:
331 *
332 * OS_ERR_NONE if the call was successful
333 *
334 * Returns : none
335 *
336 * Note : This function is INTERNAL to uC/OS-III and your application should not call it.
337 ************************************************************************************************************************
338 */
339
340 void OS_TLS_Init (OS_ERR *p_err)
341 {
342 OS_TLS_ID i;
343
344
345
346 OS_TLS_NextAvailID = 0u;
347
348 for (i = 0u; i < OS_CFG_TLS_TBL_SIZE; i++) {
349 OS_TLS_DestructPtrTbl[i] = (OS_TLS_DESTRUCT_PTR)0;
350 }
351 *p_err = OS_ERR_NONE;
352 }
353
354 /*$PAGE*/
355 /*
356 ************************************************************************************************************************
357 * TASK CREATE HOOK
358 *
359 * Description: This function is called by OSTaskCreate()
360 *
361 * Arguments : p_tcb is a pointer to the OS_TCB of the task being created.
362 *
363 * Returns : none
364 *
365 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
366 *
367 * 2) OSTaskCreate() clears all entries in p_tcb->TLS_Tbl[] before calling OS_TLS_TaskCreate() so no need
368 * to this here.
369 ************************************************************************************************************************
370 */
371
372 void OS_TLS_TaskCreate (OS_TCB *p_tcb)
373 {
374 (void)&p_tcb;
375 }
376
377 /*$PAGE*/
378 /*
379 ************************************************************************************************************************
380 * TASK DELETE HOOK
381 *
382 * Description: This function is called by OSTaskDel()
383 *
384 * Arguments : p_tcb is a pointer to the OS_TCB of the task being deleted.
385 *
386 * Returns : none
387 *
388 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
389 ************************************************************************************************************************
390 */
391
392 void OS_TLS_TaskDel (OS_TCB *p_tcb)
393 {
394 OS_TLS_ID id;
395 OS_TLS_DESTRUCT_PTR *p_tbl;
396
397
398 for (id = 0; id < OS_TLS_NextAvailID; id++) { /* Call all the destructors associated with the TLS IDs */
399 p_tbl = &OS_TLS_DestructPtrTbl[id];
400 if (*p_tbl != (OS_TLS_DESTRUCT_PTR)0) {
401 (*p_tbl)(p_tcb, id, p_tcb->TLS_Tbl[id]);
402 }
403 }
404 }
405
406 /*$PAGE*/
407 /*
408 ************************************************************************************************************************
409 * TASK SWITCH HOOK
410 *
411 * Description: This function is called by OSSched() and OSIntExit() just prior to calling the context switch code
412 *
413 * Arguments : none
414 *
415 * Returns : none
416 *
417 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
418 *
419 * 2) It's assumed that OSTCBCurPtr points to the task being switched out and OSTCBHighRdyPtr points to the
420 * task being switched in.
421 ************************************************************************************************************************
422 */
423
424 void OS_TLS_TaskSw (void)
425 {
426 }
427 #endif
428
429