LPCOpen Platform  v1.03
LPCOpen Platform for NXP LPC Microcontrollers
 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 * IAR 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 #include <yvals.h>
37 #include <stdint.h>
38 
39 
40 #ifdef VSC_INCLUDE_SOURCE_FILE_NAMES
41 const CPU_CHAR *os_tls__c = "$Id: $";
42 #endif
43 
44 #if defined(OS_CFG_TLS_TBL_SIZE) && (OS_CFG_TLS_TBL_SIZE > 0u)
45 /*
46 ************************************************************************************************************************
47 * LOCAL DEFINES
48 ************************************************************************************************************************
49 */
50 
51 
52 #if (_DLIB_FILE_DESCRIPTOR > 0) && (_FILE_OP_LOCKS > 0)
53 #define OS_TLS_LOCK_MAX ((_MAX_LOCK) + (_FOPEN_MAX)) /* _MAX_LOCK and _FOPEN_MAX defined by IAR */
54 #else
55 #define OS_TLS_LOCK_MAX (_MAX_LOCK)
56 #endif
57 
58 /*
59 ************************************************************************************************************************
60 * LOCAL DATA TYPES
61 ************************************************************************************************************************
62 */
63 
64 typedef struct os_tls_lock OS_TLS_LOCK;
65 
66 
67 struct os_tls_lock {
68  OS_MUTEX Mutex; /* OS Mutex object. */
69  OS_TLS_LOCK *NextPtr; /* Pointer to the next object in the pool. */
70 };
71 
72 /*
73 ************************************************************************************************************************
74 * LOCAL VARIABLES
75 ************************************************************************************************************************
76 */
77 
78 static CPU_DATA OS_TLS_NextAvailID; /* Next available TLS ID */
79 
80 static CPU_DATA OS_TLS_LibID; /* ID used to store library space pointer */
81 
82 static OS_TLS_LOCK OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX];
83 static OS_TLS_LOCK *OS_TLS_LockPoolListPtr = (OS_TLS_LOCK *)0; /* Pointer to head of 'OS_TLS_LOCK' list */
84 
85 /*
86 ************************************************************************************************************************
87 * LOCAL FUNCTIONS
88 ************************************************************************************************************************
89 */
90 
91 static void OS_TLS_LockCreate (void **p_lock);
92 static void OS_TLS_LockDel (void *p_lock);
93 static void OS_TLS_LockAcquire (void *p_lock);
94 static void OS_TLS_LockRelease (void *p_lock);
95 
96 /*$PAGE*/
97 /*
98 ************************************************************************************************************************
99 * ALLOCATE THE NEXT AVAILABLE TLS ID
100 *
101 * Description: This function is called to obtain the ID of the next free TLS (Task Local Storage) register 'id'
102 *
103 * Arguments : p_err is a pointer to a variable that will hold an error code related to this call.
104 *
105 * OS_ERR_NONE if the call was successful
106 * OS_ERR_TLS_NO_MORE_AVAIL if you are attempting to assign more TLS than you declared
107 * available through OS_CFG_TLS_TBL_SIZE.
108 *
109 * Returns : The next available TLS 'id' or OS_CFG_TLS_TBL_SIZE if an error is detected.
110 *
111 * Caller(s) : OS_TLS_Init()
112 ************************************************************************************************************************
113 */
114 
115 OS_TLS_ID OS_TLS_GetID (OS_ERR *p_err)
116 {
117  OS_TLS_ID id;
118  CPU_SR_ALLOC();
119 
120 
121 
122 #ifdef OS_SAFETY_CRITICAL
123  if (p_err == (OS_ERR *)0) {
124  OS_SAFETY_CRITICAL_EXCEPTION();
125  return ((OS_TLS_ID)OS_CFG_TLS_TBL_SIZE);
126  }
127 #endif
128 
130  if (OS_TLS_NextAvailID >= OS_CFG_TLS_TBL_SIZE) { /* See if we exceeded the number of IDs available */
131  *p_err = OS_ERR_TLS_NO_MORE_AVAIL; /* Yes, cannot allocate more TLS */
133  return ((OS_TLS_ID)OS_CFG_TLS_TBL_SIZE);
134  }
135 
136  id = OS_TLS_NextAvailID; /* Assign the next available ID */
137  OS_TLS_NextAvailID++; /* Increment available ID for next request */
139  *p_err = OS_ERR_NONE;
140  return (id);
141 }
142 
143 /*$PAGE*/
144 /*
145 ************************************************************************************************************************
146 * GET THE CURRENT VALUE OF A TLS REGISTER
147 *
148 * Description: This function is called to obtain the current value of a TLS register
149 *
150 * 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
151 * a NULL pointer then you will get the TLS register of the current task.
152 *
153 * id is the 'id' of the desired TLS register. Note that the 'id' must be less than
154 * 'OS_TLS_NextAvailID'
155 *
156 * p_err is a pointer to a variable that will hold an error code related to this call.
157 *
158 * OS_ERR_NONE if the call was successful
159 * OS_ERR_OS_NOT_RUNNING if the kernel has not started yet
160 * OS_ERR_TLS_ID_INVALID if the 'id' is greater or equal to OS_TLS_NextAvailID
161 * OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not
162 * needed for the task
163 *
164 * Returns : The current value of the task's TLS register or 0 if an error is detected.
165 *
166 * Note(s) : 1) p_tcb->Opt contains options passed to OSTaskCreate(). One of these options (OS_OPT_TASK_NO_TLS) is
167 * used to specify that the user doesn't want TLS support for the task being created. In other words,
168 * by default, TLS support is enabled if OS_CFG_TLS_TBL_SIZE is defined and > 0 so the user must
169 * specifically indicate that he/she doesn't want TLS supported for a task.
170 ************************************************************************************************************************
171 */
172 
173 OS_TLS OS_TLS_GetValue (OS_TCB *p_tcb,
174  OS_TLS_ID id,
175  OS_ERR *p_err)
176 {
177  OS_TLS value;
178  CPU_SR_ALLOC();
179 
180 
181 
182 #ifdef OS_SAFETY_CRITICAL
183  if (p_err == (OS_ERR *)0) {
184  OS_SAFETY_CRITICAL_EXCEPTION();
185  return ((OS_TLS)0);
186  }
187 #endif
188 
189 
190 #if OS_CFG_ARG_CHK_EN > 0u
191  if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */
192  *p_err = OS_ERR_TLS_ID_INVALID;
193  return ((OS_TLS)0);
194  }
195 #endif
196 
198  if (p_tcb == (OS_TCB *)0) { /* Does caller want to use current task's TCB? */
199  p_tcb = OSTCBCurPtr; /* Yes */
200  if (OSTCBCurPtr == (OS_TCB *)0) { /* Is the kernel running? */
201  CPU_CRITICAL_EXIT(); /* No, then caller cannot specify NULL */
202  *p_err = OS_ERR_OS_NOT_RUNNING;
203  return ((OS_TLS)0);
204  }
205  }
206  if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
207  value = p_tcb->TLS_Tbl[id]; /* Yes */
209  *p_err = OS_ERR_NONE;
210  return ((OS_TLS)value);
211  } else {
212  CPU_CRITICAL_EXIT(); /* No */
213  *p_err = OS_ERR_TLS_NOT_EN;
214  return ((OS_TLS)0);
215  }
216 }
217 
218 /*$PAGE*/
219 /*
220 ************************************************************************************************************************
221 * DEFINE TLS DESTRUCTOR FUNCTION
222 *
223 * Description: This function is called by the user to assign a 'destructor' function to a specific TLS. When a task is
224 * deleted, all the destructors are called for all the task's TLS for which there is a destructor function
225 * defined. In other when a task is deleted, all the non-NULL functions present in OS_TLS_DestructPtrTbl[]
226 * will be called.
227 *
228 * Arguments : id is the ID of the TLS destructor to set
229 *
230 * p_destruct is a pointer to a function that is associated with a specific TLS register and is called when
231 * a task is deleted. The prototype of such functions is:
232 *
233 * void MyDestructFunction (OS_TCB *p_tcb,
234 * OS_TLS_ID id,
235 * OS_TLS value);
236 *
237 * you can specify a NULL pointer if you don't want to have a fucntion associated with a TLS
238 * register. A NULL pointer (i.e. no function associated with a TLS register) is the default
239 * value placed in OS_TLS_DestructPtrTbl[].
240 *
241 * p_err is a pointer to an error return code. The possible values are:
242 *
243 * OS_ERR_NONE The call was successful.
244 * OS_ERR_TLS_ID_INVALID You you specified an invalid TLS ID
245 *
246 * Returns : none
247 *
248 * Note : none
249 ************************************************************************************************************************
250 */
251 
252 void OS_TLS_SetDestruct (OS_TLS_ID id,
253  OS_TLS_DESTRUCT_PTR p_destruct,
254  OS_ERR *p_err)
255 {
256  (void)&id;
257  (void)&p_destruct;
258  *p_err = OS_ERR_NONE;
259 }
260 
261 /*$PAGE*/
262 /*
263 ************************************************************************************************************************
264 * SET THE CURRENT VALUE OF A TASK TLS REGISTER
265 *
266 * Description: This function is called to change the current value of a task TLS register.
267 *
268 * 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'
269 * is a NULL pointer then you will change the TLS register of the current task.
270 *
271 * id is the 'id' of the desired task TLS register. Note that the 'id' must be less than
272 * 'OS_TLS_NextAvailID'
273 *
274 * value is the desired value for the task TLS register.
275 *
276 * p_err is a pointer to a variable that will hold an error code related to this call.
277 *
278 * OS_ERR_NONE if the call was successful
279 * OS_ERR_OS_NOT_RUNNING if the kernel has not started yet
280 * OS_ERR_TLS_ID_INVALID if you specified an invalid TLS ID
281 * OS_ERR_TLS_NOT_EN if the task was created by specifying that TLS support was not
282 * needed for the task
283 *
284 * Returns : none
285 *
286 * Note(s) : 1) p_tcb->Opt contains options passed to OSTaskCreate(). One of these options (OS_OPT_TASK_NO_TLS) is
287 * used to specify that the user doesn't want TLS support for the task being created. In other words,
288 * by default, TLS support is enabled if OS_CFG_TLS_TBL_SIZE is defined and > 0 so the user must
289 * specifically indicate that he/she doesn't want TLS supported for a task.
290 ************************************************************************************************************************
291 */
292 
293 void OS_TLS_SetValue (OS_TCB *p_tcb,
294  OS_TLS_ID id,
295  OS_TLS value,
296  OS_ERR *p_err)
297 {
298  CPU_SR_ALLOC();
299 
300 
301 
302 #ifdef OS_SAFETY_CRITICAL
303  if (p_err == (OS_ERR *)0) {
304  OS_SAFETY_CRITICAL_EXCEPTION();
305  return;
306  }
307 #endif
308 
309 #if OS_CFG_ARG_CHK_EN > 0u
310  if (id >= OS_TLS_NextAvailID) { /* Caller must specify an ID that's been assigned */
311  *p_err = OS_ERR_TLS_ID_INVALID;
312  return;
313  }
314 #endif
315 
316  CPU_CRITICAL_ENTER(); /* Does caller want to use current task's TCB? */
317  if (p_tcb == (OS_TCB *)0) { /* Yes */
318  p_tcb = OSTCBCurPtr; /* Is the kernel running? */
319  if (OSTCBCurPtr == (OS_TCB *)0) { /* No, then caller cannot specify NULL */
321  *p_err = OS_ERR_OS_NOT_RUNNING;
322  return;
323  }
324  }
325  if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
326  p_tcb->TLS_Tbl[id] = value; /* Yes */
328  *p_err = OS_ERR_NONE;
329  } else {
330  CPU_CRITICAL_EXIT(); /* No */
331  *p_err = OS_ERR_TLS_NOT_EN;
332  }
333 }
334 
335 /*$PAGE*/
336 /*
337 ************************************************************************************************************************
338 ************************************************************************************************************************
339 * uC/OS-III INTERNAL FUNCTIONS
340 * DO NOT CALL FROM THE APPLICATION CODE
341 ************************************************************************************************************************
342 ************************************************************************************************************************
343 */
344 
345 /*
346 ************************************************************************************************************************
347 * INITIALIZE THE TASK LOCAL STORAGE SERVICES
348 *
349 * Description: This function is called by uC/OS-III to initialize the TLS id allocator.
350 *
351 * This function also initializes an array containing function pointers. There is one function associated
352 * to each task TLS register and all the functions (assuming non-NULL) will be called when the task is
353 * deleted.
354 *
355 * Arguments : none
356 *
357 * Returns : none
358 *
359 * Caller(s) : OSInit()
360 *
361 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
362 ************************************************************************************************************************
363 */
364 
365 void OS_TLS_Init (OS_ERR *p_err)
366 {
367  CPU_INT16U ix;
368  OS_TLS_LOCK *p_lock;
369  CPU_SR_ALLOC();
370 
371 
372 
373  OS_TLS_NextAvailID = 0u;
374  OS_TLS_LibID = OS_TLS_GetID(p_err);
375 
377  /* Create the link list of OS_TLS_LOCK objects. */
378  for (ix = 0u; ix < (OS_TLS_LOCK_MAX - 1u); ix++) {
379  p_lock = &OS_TLS_LockPoolTbl[ix];
380  p_lock->NextPtr = &OS_TLS_LockPoolTbl[ix + 1u];
381  }
382 
383  p_lock = &OS_TLS_LockPoolTbl[OS_TLS_LOCK_MAX - 1u];
384  p_lock->NextPtr = (OS_TLS_LOCK *)0; /* Last node points to 'NULL' */
385 
386  OS_TLS_LockPoolListPtr = &OS_TLS_LockPoolTbl[0]; /* Initialize the list head pointer. */
387 
389 }
390 
391 /*$PAGE*/
392 /*
393 ************************************************************************************************************************
394 * TASK CREATE HOOK
395 *
396 * Description: This function is called by OSTaskCreate()
397 *
398 * Arguments : p_tcb is a pointer to the OS_TCB of the task being created.
399 *
400 * Returns : none
401 *
402 *
403 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
404 *
405 * 2) OSTaskCreate() clears all entries in p_tcb->TLS_Tbl[] before calling OS_TLS_TaskCreate() so no need
406 * to this here.
407 ************************************************************************************************************************
408 */
409 
410 void OS_TLS_TaskCreate (OS_TCB *p_tcb)
411 {
412  OS_TLS p_tls;
413 
414 
415  if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
416  /* Get TLS segment from the HEAP. */
417  p_tls = (OS_TLS)__iar_dlib_perthread_allocate();
418  __iar_dlib_perthread_initialize(p_tls); /* Initialize the TLS segment. */
419  p_tcb->TLS_Tbl[OS_TLS_LibID] = p_tls; /* Set the TLS segment pointer in the task. */
420  }
421 }
422 
423 /*$PAGE*/
424 /*
425 ************************************************************************************************************************
426 * TASK DELETE HOOK
427 *
428 * Description: This function is called by OSTaskDel()
429 *
430 * Arguments : p_tcb is a pointer to the OS_TCB of the task being deleted.
431 *
432 * Returns : none
433 *
434 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
435 ************************************************************************************************************************
436 */
437 
438 void OS_TLS_TaskDel (OS_TCB *p_tcb)
439 {
440  OS_TLS p_tls;
441 
442 
443  if ((p_tcb->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
444  p_tls = p_tcb->TLS_Tbl[OS_TLS_LibID];
445  __iar_dlib_perthread_destroy();
446  __iar_dlib_perthread_deallocate((void *)p_tls); /* De-allocate the TLS segment. */
447  p_tcb->TLS_Tbl[OS_TLS_LibID] = (OS_TLS)0; /* Remove the TLS segment pointer from the task. */
448  }
449 }
450 
451 /*$PAGE*/
452 /*
453 ************************************************************************************************************************
454 * TASK SWITCH HOOK
455 *
456 * Description: This function is called by OSSched() and OSIntExit() just prior to calling the context switch code
457 *
458 * Arguments : none
459 *
460 * Returns : none
461 *
462 * Note(s) : 1) This function is INTERNAL to uC/OS-III and your application should not call it.
463 *
464 * 2) It's assumed that OSTCBCurPtr points to the task being switched out and OSTCBHighRdyPtr points to the
465 * task being switched in.
466 ************************************************************************************************************************
467 */
468 
469 void OS_TLS_TaskSw (void)
470 {
471  if ((OSTCBHighRdyPtr->Opt & OS_OPT_TASK_NO_TLS) == OS_OPT_NONE) { /* See if TLS is available for this task */
472  }
473 }
474 
475 /*$PAGE*/
476 /*
477 ************************************************************************************************************************
478 ************************************************************************************************************************
479 * uC/OS-III MUTEX IMPLEMENTATION
480 ************************************************************************************************************************
481 ************************************************************************************************************************
482 */
483 
484 /*
485 ************************************************************************************************************************
486 * OS LOCK CREATE
487 *
488 * Description : Allocate a new 'OS_TLS_LOCK' object from the free pool and create a 'OS_MUTEX' in the kernel.
489 *
490 * Argument(s) : p_lock Pointer to the DLIB lock handler.
491 *
492 * Return(s) : None.
493 *
494 * Caller(s) : __iar_system_Mtxinit()
495 * __iar_file_Mtxinit()
496 *
497 * Note(s) : None.
498 ************************************************************************************************************************
499 */
500 
501 void OS_TLS_LockCreate (void **p_lock)
502 {
503  OS_TLS_LOCK *p_tls_lock;
504  OS_ERR os_err;
505  CPU_SR_ALLOC();
506 
507 
508  if (p_lock == (void **)0) {
509  return;
510  }
511 
512  if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) { /* If 'OS_TLS_LOCK' object pool is empty? */
513  *p_lock = (void *)0; /* return a 'NULL' pointer. */
514  return;
515  }
516 
517  p_tls_lock = OS_TLS_LockPoolListPtr; /* Get the first object in the list. */
518 
519  OSMutexCreate((OS_MUTEX *)&p_tls_lock->Mutex, /* Create the mutex in the kernel. */
520  (CPU_CHAR *) 0,
521  (OS_ERR *)&os_err);
522 
523  if (os_err != OS_ERR_NONE) { /* If the mutex create funtion fail? */
524  *p_lock = (void *)0; /* ... return a 'NULL' pointer. */
525  return;
526  }
527 
529  OS_TLS_LockPoolListPtr = p_tls_lock->NextPtr; /* Move HEAD pointer to the next object in the list.*/
531 
532  *p_lock = (void *)p_tls_lock; /* Return the new 'OS_TLS_LOCK' object pointer. */
533 }
534 
535 
536 /*
537 ************************************************************************************************************************
538 * OS LOCK DELETE
539 *
540 * Description : Delete a 'OS_MUTEX' from the kernel and return the allocated 'OS_TLS_LOCK'
541 * to the free pool.
542 *
543 * Argument(s) : p_lock DLIB lock handler.
544 *
545 * Return(s) : Return the current task TLS pointer.
546 *
547 * Caller(s) : __iar_system_Mtxdst()
548 * __iar_file_Mtxdst()
549 *
550 * Note(s) : None.
551 ************************************************************************************************************************
552 */
553 
554 void OS_TLS_LockDel (void *p_lock)
555 {
556  OS_TLS_LOCK *p_tls_lock;
557  OS_ERR os_err;
558  CPU_SR_ALLOC();
559 
560 
561  if (p_lock == (void *)0) {
562  return;
563  }
564 
565  p_tls_lock = (OS_TLS_LOCK *)p_lock;
566 
567  (void)OSMutexDel((OS_MUTEX *)&p_tls_lock->Mutex,
569  (OS_ERR *)&os_err);
570  (void)&os_err;
571 
573  /* Return the OS_TLS_LOCK in front of the list */
574  if (OS_TLS_LockPoolListPtr == (OS_TLS_LOCK *)0) {
575  p_tls_lock->NextPtr = (OS_TLS_LOCK *)0;
576  } else {
577  p_tls_lock->NextPtr = OS_TLS_LockPoolListPtr;
578  }
579  OS_TLS_LockPoolListPtr = p_tls_lock;
580 
582 }
583 
584 
585 /*
586 ************************************************************************************************************************
587 * OS LOCK PEND
588 *
589 * Description : Wait indefinitely until the lock become available
590 *
591 * Arguments : p_lock DLIB lock handler.
592 *
593 * Return(s) : Return the current task TLS pointer.
594 *
595 * Caller(s) : __iar_system_Mtxlock()
596 * __iar_file_Mtxlock()
597 
598 * Note(s) : None.
599 ************************************************************************************************************************
600 */
601 
602 void OS_TLS_LockAcquire (void *p_lock)
603 {
604  OS_TLS_LOCK *p_tls_lock;
605  OS_ERR os_err;
606 
607 
608  if ((p_lock == (void *)0 ) || /* Return if the lock handler is 'NULL' or the ... */
609  (OSRunning != OS_STATE_OS_RUNNING)) { /* ... kernel is not running. */
610  return;
611  }
612 
613  p_tls_lock = (OS_TLS_LOCK *)p_lock;
614  OSMutexPend((OS_MUTEX *)&p_tls_lock->Mutex,
615  (OS_TICK ) 0u,
617  (CPU_TS *) 0,
618  (OS_ERR *)&os_err);
619  (void)&os_err;
620 }
621 
622 
623 /*
624 ************************************************************************************************************************
625 * OS LOCK POST
626 *
627 * Description : Signal the lock.
628 *
629 * Argument(s) : p_lock DLIB lock handler.
630 *
631 * Return(s) : Return the current task TLS pointer.
632 *
633 * Caller(s) : __iar_system_Mtxunlock()
634 * __iar_file_Mtxunlock()
635 *
636 * Note(s) : None.
637 ************************************************************************************************************************
638 */
639 
640 static void OS_TLS_LockRelease (void *p_lock)
641 {
642  OS_TLS_LOCK *p_tls_lock;
643  OS_ERR os_err;
644 
645 
646  if ((p_lock == (void *)0 ) || /* Return if the lock handler is 'NULL' or the ... */
647  (OSRunning != OS_STATE_OS_RUNNING)) { /* ... kernel is not running. */
648  return;
649  }
650 
651  p_tls_lock = (OS_TLS_LOCK *)p_lock;
652  OSMutexPost((OS_MUTEX *)&p_tls_lock->Mutex,
654  (OS_ERR *)&os_err);
655 
656  (void)&os_err;
657 }
658 
659 /*$PAGE*/
660 _STD_BEGIN
661 /*
662 ************************************************************************************************************************
663 ************************************************************************************************************************
664 * IAR FUNCTIONS IMPLEMENTATIONS
665 ************************************************************************************************************************
666 ************************************************************************************************************************
667 */
668 
669 /*
670 ************************************************************************************************************************
671 * SYSTEM LOCK INITIALIZATION
672 *
673 * Description: Initialize a system lock.
674 *
675 * Arguments : p_lock Pointer to the lock info object pointer.
676 *
677 * Note(s) : none.
678 ************************************************************************************************************************
679 */
680 
681 void __iar_system_Mtxinit (__iar_Rmtx *p_lock)
682 {
683  OS_TLS_LockCreate((void **)p_lock);
684 }
685 
686 
687 /*
688 ************************************************************************************************************************
689 * SYSTEM LOCK DELETE
690 *
691 * Description: Delete a system lock.
692 *
693 * Arguments : p_lock Pointer to the lock info object.
694 *
695 * Note(s) : none.
696 ************************************************************************************************************************
697 */
698 
699 void __iar_system_Mtxdst(__iar_Rmtx *p_lock)
700 {
701  OS_TLS_LockDel((void *)*p_lock);
702 }
703 
704 
705 /*
706 ************************************************************************************************************************
707 * SYSTEM LOCK PEND
708 *
709 * Description: Pend on a system lock.
710 *
711 * Arguments : p_lock Pointer to the lock info object.
712 *
713 * Note(s) : none.
714 ************************************************************************************************************************
715 */
716 
717 void __iar_system_Mtxlock(__iar_Rmtx *p_lock)
718 {
719  OS_TLS_LockAcquire((void *)*p_lock);
720 }
721 
722 
723 /*
724 ************************************************************************************************************************
725 * SYSTEM LOCK POST
726 *
727 * Description: Signal a system lock.
728 *
729 * Arguments : p_lock Pointer to the lock info object.
730 *
731 * Note(s) : none.
732 ************************************************************************************************************************
733 */
734 
735 void __iar_system_Mtxunlock(__iar_Rmtx *p_lock)
736 {
737  OS_TLS_LockRelease((void *)*p_lock);
738 }
739 
740 /*$PAGE*/
741 /*
742 ************************************************************************************************************************
743 * FILE LOCK INITIALIZATION
744 *
745 * Description: Initialize a file lock.
746 *
747 * Arguments : p_lock Pointer to the lock info object pointer.
748 *
749 * Note(s) : none.
750 ************************************************************************************************************************
751 */
752 
753 void __iar_file_Mtxinit (__iar_Rmtx *p_lock)
754 {
755  OS_TLS_LockCreate((void **)p_lock);
756 }
757 
758 
759 /*
760 ************************************************************************************************************************
761 * FILE LOCK DELETE
762 *
763 * Description: Delete a system lock.
764 *
765 * Arguments : p_lock Pointer to the lock info object.
766 *
767 * Note(s) : none.
768 ************************************************************************************************************************
769 */
770 
771 void __iar_file_Mtxdst(__iar_Rmtx *p_lock)
772 {
773  OS_TLS_LockDel((void *)*p_lock);
774 }
775 
776 
777 /*
778 ************************************************************************************************************************
779 * FILE LOCK PEND
780 *
781 * Description: Pend on a file lock.
782 *
783 * Arguments : p_lock Pointer to the lock info object.
784 *
785 * Note(s) : none.
786 ************************************************************************************************************************
787 */
788 
789 void __iar_file_Mtxlock(__iar_Rmtx *p_lock)
790 {
791  OS_TLS_LockAcquire((void *)*p_lock);
792 }
793 
794 
795 /*
796 ************************************************************************************************************************
797 * FILE LOCK POST
798 *
799 * Description: Signal in a file lock.
800 *
801 * Arguments : p_lock Pointer to the lock info object.
802 *
803 * Note(s) : none.
804 ************************************************************************************************************************
805 */
806 
807 void __iar_file_Mtxunlock(__iar_Rmtx *p_lock)
808 {
809  OS_TLS_LockRelease((void *)*p_lock);
810 }
811 
812 
813 
814 /*
815 ************************************************************************************************************************
816 * GET CURRENT TLS POINTER
817 *
818 * Description : Get the current TLS pointer.
819 *
820 * Argument(s) : symbp Pointer to the symbol in the segment.
821 *
822 * Return(s) : Returns symbol address in the current TLS segment.
823 *
824 * Note(s) : None.
825 ************************************************************************************************************************
826 */
827 
828 void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access (void _DLIB_TLS_MEMORY *symbp)
829 {
830  void _DLIB_TLS_MEMORY *p_tls;
831  uintptr_t tls_start;
832  uintptr_t tls_offset;
833 
834 
835 
836  if (OSRunning != OS_STATE_OS_RUNNING) { /* If the kernel is not running yet? */
837  p_tls = (OS_TLS)__segment_begin("__DLIB_PERTHREAD"); /* ... return the pointer to the main TLS segment. */
838  } else {
839  p_tls = (void *)OSTCBCurPtr->TLS_Tbl[OS_TLS_LibID]; /* Get the pointer to the TLS for the task */
840  }
841 
842  tls_start = (uintptr_t)(p_tls);
843  tls_offset = (uintptr_t)(__IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp));
844  p_tls = (void _DLIB_TLS_MEMORY *)(tls_start + tls_offset);
845 
846  return (p_tls);
847 }
848 
849 _STD_END
850 #endif
851 
852