1 /***************************************************************************
2  * Copyright (c) 2024 Microsoft Corporation
3  *
4  * This program and the accompanying materials are made available under the
5  * terms of the MIT License which is available at
6  * https://opensource.org/licenses/MIT.
7  *
8  * SPDX-License-Identifier: MIT
9  **************************************************************************/
10 
11 
12 /**************************************************************************/
13 /**************************************************************************/
14 /**                                                                       */
15 /** ThreadX Component                                                     */
16 /**                                                                       */
17 /**   IAR Multithreaded Library Support                                   */
18 /**                                                                       */
19 /**************************************************************************/
20 /**************************************************************************/
21 
22 #define TX_SOURCE_CODE
23 
24 
25 /* Define IAR library for tools prior to version 8.  */
26 
27 #if (__VER__ < 8000000)
28 
29 
30 /* IAR version 7 and below.  */
31 
32 /* Include necessary system files.  */
33 
34 #include "tx_api.h"
35 #include "tx_initialize.h"
36 #include "tx_thread.h"
37 #include "tx_mutex.h"
38 
39 
40 /* This implementation requires that the following macros are defined in the
41    tx_port.h file and <yvals.h> is included with the following code segments:
42 
43 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
44 #include <yvals.h>
45 #endif
46 
47 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
48 #define TX_THREAD_EXTENSION_2           VOID    *tx_thread_iar_tls_pointer;
49 #else
50 #define TX_THREAD_EXTENSION_2
51 #endif
52 
53 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
54 #define TX_THREAD_CREATE_EXTENSION(thread_ptr)                      thread_ptr -> tx_thread_iar_tls_pointer =  __iar_dlib_perthread_allocate();
55 #define TX_THREAD_DELETE_EXTENSION(thread_ptr)                      __iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
56                                                                     thread_ptr -> tx_thread_iar_tls_pointer =  TX_NULL;
57 #define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION               __iar_dlib_perthread_access(0);
58 #else
59 #define TX_THREAD_CREATE_EXTENSION(thread_ptr)
60 #define TX_THREAD_DELETE_EXTENSION(thread_ptr)
61 #endif
62 
63     This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
64     application.
65 
66     Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
67 */
68 
69 #ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
70 
71 #include <yvals.h>
72 
73 
74 #if _MULTI_THREAD
75 
76 TX_MUTEX    __tx_iar_system_lock_mutexes[_MAX_LOCK];
77 UINT        __tx_iar_system_lock_next_free_mutex =  0;
78 
79 
80 /* Define error counters, just for debug purposes.  */
81 
82 UINT        __tx_iar_system_lock_no_mutexes;
83 UINT        __tx_iar_system_lock_internal_errors;
84 UINT        __tx_iar_system_lock_isr_caller;
85 
86 
87 /* Define the TLS access function for the IAR library.  */
88 
__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY * symbp)89 void _DLIB_TLS_MEMORY *__iar_dlib_perthread_access(void _DLIB_TLS_MEMORY *symbp)
90 {
91 
92 char _DLIB_TLS_MEMORY   *p = 0;
93 
94     /* Is there a current thread?  */
95     if (_tx_thread_current_ptr)
96       p = (char _DLIB_TLS_MEMORY *) _tx_thread_current_ptr -> tx_thread_iar_tls_pointer;
97     else
98       p = (void _DLIB_TLS_MEMORY *) __segment_begin("__DLIB_PERTHREAD");
99     p += __IAR_DLIB_PERTHREAD_SYMBOL_OFFSET(symbp);
100     return (void _DLIB_TLS_MEMORY *) p;
101 }
102 
103 
104 /* Define mutexes for IAR library.  */
105 
__iar_system_Mtxinit(__iar_Rmtx * m)106 void __iar_system_Mtxinit(__iar_Rmtx *m)
107 {
108 
109 UINT        i;
110 UINT        status;
111 TX_MUTEX    *mutex_ptr;
112 
113 
114     /* First, find a free mutex in the list.  */
115     for (i = 0; i < _MAX_LOCK; i++)
116     {
117 
118         /* Setup a pointer to the start of the next free mutex.  */
119         mutex_ptr =  &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
120 
121         /* Check for wrap-around on the next free mutex.  */
122         if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
123         {
124 
125             /* Yes, set the free index back to 0.  */
126             __tx_iar_system_lock_next_free_mutex =  0;
127         }
128 
129         /* Is this mutex free?  */
130         if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
131         {
132 
133             /* Yes, this mutex is free, get out of the loop!  */
134             break;
135         }
136     }
137 
138     /* Determine if a free mutex was found.   */
139     if (i >= _MAX_LOCK)
140     {
141 
142         /* Error!  No more free mutexes!  */
143 
144         /* Increment the no mutexes error counter.  */
145         __tx_iar_system_lock_no_mutexes++;
146 
147         /* Set return pointer to NULL.  */
148         *m =  TX_NULL;
149 
150         /* Return.  */
151         return;
152     }
153 
154     /* Now create the ThreadX mutex for the IAR library.  */
155     status =  _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
156 
157     /* Determine if the creation was successful.  */
158     if (status == TX_SUCCESS)
159     {
160 
161         /* Yes, successful creation, return mutex pointer.  */
162         *m =  (VOID *) mutex_ptr;
163     }
164     else
165     {
166 
167         /* Increment the internal error counter.  */
168         __tx_iar_system_lock_internal_errors++;
169 
170         /* Return a NULL pointer to indicate an error.  */
171         *m =  TX_NULL;
172     }
173 }
174 
__iar_system_Mtxdst(__iar_Rmtx * m)175 void __iar_system_Mtxdst(__iar_Rmtx *m)
176 {
177 
178     /* Simply delete the mutex.  */
179     _tx_mutex_delete((TX_MUTEX *) *m);
180 }
181 
__iar_system_Mtxlock(__iar_Rmtx * m)182 void __iar_system_Mtxlock(__iar_Rmtx *m)
183 {
184 
185 UINT    status;
186 
187 
188     /* Determine the caller's context. Mutex locks are only available from initialization and
189        threads.  */
190     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
191     {
192 
193         /* Get the mutex.  */
194         status =  _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
195 
196         /* Check the status of the mutex release.  */
197         if (status)
198         {
199 
200             /* Internal error, increment the counter.  */
201             __tx_iar_system_lock_internal_errors++;
202         }
203     }
204     else
205     {
206 
207         /* Increment the ISR caller error.  */
208         __tx_iar_system_lock_isr_caller++;
209     }
210 }
211 
__iar_system_Mtxunlock(__iar_Rmtx * m)212 void __iar_system_Mtxunlock(__iar_Rmtx *m)
213 {
214 
215 UINT    status;
216 
217 
218     /* Determine the caller's context. Mutex unlocks are only available from initialization and
219        threads.  */
220     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
221     {
222 
223         /* Release the mutex.  */
224         status =  _tx_mutex_put((TX_MUTEX *) *m);
225 
226         /* Check the status of the mutex release.  */
227         if (status)
228         {
229 
230             /* Internal error, increment the counter.  */
231             __tx_iar_system_lock_internal_errors++;
232         }
233     }
234     else
235     {
236 
237         /* Increment the ISR caller error.  */
238         __tx_iar_system_lock_isr_caller++;
239     }
240 }
241 
242 
243 #if _DLIB_FILE_DESCRIPTOR
244 
245 TX_MUTEX    __tx_iar_file_lock_mutexes[_MAX_FLOCK];
246 UINT        __tx_iar_file_lock_next_free_mutex =  0;
247 
248 
249 /* Define error counters, just for debug purposes.  */
250 
251 UINT        __tx_iar_file_lock_no_mutexes;
252 UINT        __tx_iar_file_lock_internal_errors;
253 UINT        __tx_iar_file_lock_isr_caller;
254 
255 
__iar_file_Mtxinit(__iar_Rmtx * m)256 void __iar_file_Mtxinit(__iar_Rmtx *m)
257 {
258 
259 UINT        i;
260 UINT        status;
261 TX_MUTEX    *mutex_ptr;
262 
263 
264     /* First, find a free mutex in the list.  */
265     for (i = 0; i < _MAX_FLOCK; i++)
266     {
267 
268         /* Setup a pointer to the start of the next free mutex.  */
269         mutex_ptr =  &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
270 
271         /* Check for wrap-around on the next free mutex.  */
272         if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
273         {
274 
275             /* Yes, set the free index back to 0.  */
276             __tx_iar_file_lock_next_free_mutex =  0;
277         }
278 
279         /* Is this mutex free?  */
280         if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
281         {
282 
283             /* Yes, this mutex is free, get out of the loop!  */
284             break;
285         }
286     }
287 
288     /* Determine if a free mutex was found.   */
289     if (i >= _MAX_LOCK)
290     {
291 
292         /* Error!  No more free mutexes!  */
293 
294         /* Increment the no mutexes error counter.  */
295         __tx_iar_file_lock_no_mutexes++;
296 
297         /* Set return pointer to NULL.  */
298         *m =  TX_NULL;
299 
300         /* Return.  */
301         return;
302     }
303 
304     /* Now create the ThreadX mutex for the IAR library.  */
305     status =  _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
306 
307     /* Determine if the creation was successful.  */
308     if (status == TX_SUCCESS)
309     {
310 
311         /* Yes, successful creation, return mutex pointer.  */
312         *m =  (VOID *) mutex_ptr;
313     }
314     else
315     {
316 
317         /* Increment the internal error counter.  */
318         __tx_iar_file_lock_internal_errors++;
319 
320         /* Return a NULL pointer to indicate an error.  */
321         *m =  TX_NULL;
322     }
323 }
324 
__iar_file_Mtxdst(__iar_Rmtx * m)325 void __iar_file_Mtxdst(__iar_Rmtx *m)
326 {
327 
328     /* Simply delete the mutex.  */
329     _tx_mutex_delete((TX_MUTEX *) *m);
330 }
331 
__iar_file_Mtxlock(__iar_Rmtx * m)332 void __iar_file_Mtxlock(__iar_Rmtx *m)
333 {
334 
335 UINT    status;
336 
337 
338     /* Determine the caller's context. Mutex locks are only available from initialization and
339        threads.  */
340     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
341     {
342 
343         /* Get the mutex.  */
344         status =  _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
345 
346         /* Check the status of the mutex release.  */
347         if (status)
348         {
349 
350             /* Internal error, increment the counter.  */
351             __tx_iar_file_lock_internal_errors++;
352         }
353     }
354     else
355     {
356 
357         /* Increment the ISR caller error.  */
358         __tx_iar_file_lock_isr_caller++;
359     }
360 }
361 
__iar_file_Mtxunlock(__iar_Rmtx * m)362 void __iar_file_Mtxunlock(__iar_Rmtx *m)
363 {
364 
365 UINT    status;
366 
367 
368     /* Determine the caller's context. Mutex unlocks are only available from initialization and
369        threads.  */
370     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
371     {
372 
373         /* Release the mutex.  */
374         status =  _tx_mutex_put((TX_MUTEX *) *m);
375 
376         /* Check the status of the mutex release.  */
377         if (status)
378         {
379 
380             /* Internal error, increment the counter.  */
381             __tx_iar_file_lock_internal_errors++;
382         }
383     }
384     else
385     {
386 
387         /* Increment the ISR caller error.  */
388         __tx_iar_file_lock_isr_caller++;
389     }
390 }
391 #endif  /* _DLIB_FILE_DESCRIPTOR */
392 
393 #endif  /* _MULTI_THREAD  */
394 
395 #endif  /* TX_ENABLE_IAR_LIBRARY_SUPPORT  */
396 
397 #else   /* IAR version 8 and above.  */
398 
399 
400 /* Include necessary system files.  */
401 
402 #include "tx_api.h"
403 #include "tx_initialize.h"
404 #include "tx_thread.h"
405 #include "tx_mutex.h"
406 
407 /* This implementation requires that the following macros are defined in the
408    tx_port.h file and <yvals.h> is included with the following code segments:
409 
410 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
411 #include <yvals.h>
412 #endif
413 
414 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
415 #define TX_THREAD_EXTENSION_2           VOID    *tx_thread_iar_tls_pointer;
416 #else
417 #define TX_THREAD_EXTENSION_2
418 #endif
419 
420 #ifdef  TX_ENABLE_IAR_LIBRARY_SUPPORT
421 void    *_tx_iar_create_per_thread_tls_area(void);
422 void    _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
423 void    __iar_Initlocks(void);
424 
425 #define TX_THREAD_CREATE_EXTENSION(thread_ptr)                      thread_ptr -> tx_thread_iar_tls_pointer =  __iar_dlib_perthread_allocate();
426 #define TX_THREAD_DELETE_EXTENSION(thread_ptr)                      do {__iar_dlib_perthread_deallocate(thread_ptr -> tx_thread_iar_tls_pointer); \
427                                                                         thread_ptr -> tx_thread_iar_tls_pointer =  TX_NULL; } while(0);
428 #define TX_PORT_SPECIFIC_PRE_SCHEDULER_INITIALIZATION               do {__iar_Initlocks();} while(0);
429 #else
430 #define TX_THREAD_CREATE_EXTENSION(thread_ptr)
431 #define TX_THREAD_DELETE_EXTENSION(thread_ptr)
432 #endif
433 
434     This should be done automatically if TX_ENABLE_IAR_LIBRARY_SUPPORT is defined while building the ThreadX library and the
435     application.
436 
437     Finally, the project options General Options -> Library Configuration should have the "Enable thread support in library" box selected.
438 */
439 
440 #ifdef TX_ENABLE_IAR_LIBRARY_SUPPORT
441 
442 #include <DLib_threads.h>
443 
444 
445 void * __aeabi_read_tp();
446 
447 void* _tx_iar_create_per_thread_tls_area();
448 void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr);
449 
450 #pragma section="__iar_tls$$DATA"
451 
452 /* Define the TLS access function for the IAR library.  */
__aeabi_read_tp(void)453 void * __aeabi_read_tp(void)
454 {
455   void *p = 0;
456   TX_THREAD *thread_ptr = _tx_thread_current_ptr;
457   if (thread_ptr)
458   {
459     p = thread_ptr->tx_thread_iar_tls_pointer;
460   }
461   else
462   {
463     p = __section_begin("__iar_tls$$DATA");
464   }
465   return p;
466 }
467 
468 /* Define the TLS creation and destruction to use malloc/free.  */
469 
_tx_iar_create_per_thread_tls_area()470 void* _tx_iar_create_per_thread_tls_area()
471 {
472   UINT tls_size = __iar_tls_size();
473 
474   /* Get memory for TLS.  */
475   void *p = malloc(tls_size);
476 
477   /* Initialize TLS-area and run constructors for objects in TLS */
478   __iar_tls_init(p);
479   return p;
480 }
481 
_tx_iar_destroy_per_thread_tls_area(void * tls_ptr)482 void _tx_iar_destroy_per_thread_tls_area(void *tls_ptr)
483 {
484   /* Destroy objects living in TLS */
485   __call_thread_dtors();
486   free(tls_ptr);
487 }
488 
489 #ifndef _MAX_LOCK
490 #define _MAX_LOCK 4
491 #endif
492 
493 static TX_MUTEX    __tx_iar_system_lock_mutexes[_MAX_LOCK];
494 static UINT        __tx_iar_system_lock_next_free_mutex =  0;
495 
496 
497 /* Define error counters, just for debug purposes.  */
498 
499 UINT        __tx_iar_system_lock_no_mutexes;
500 UINT        __tx_iar_system_lock_internal_errors;
501 UINT        __tx_iar_system_lock_isr_caller;
502 
503 
504 /* Define mutexes for IAR library.  */
505 
__iar_system_Mtxinit(__iar_Rmtx * m)506 void __iar_system_Mtxinit(__iar_Rmtx *m)
507 {
508 
509 UINT        i;
510 UINT        status;
511 TX_MUTEX    *mutex_ptr;
512 
513 
514     /* First, find a free mutex in the list.  */
515     for (i = 0; i < _MAX_LOCK; i++)
516     {
517 
518         /* Setup a pointer to the start of the next free mutex.  */
519         mutex_ptr =  &__tx_iar_system_lock_mutexes[__tx_iar_system_lock_next_free_mutex++];
520 
521         /* Check for wrap-around on the next free mutex.  */
522         if (__tx_iar_system_lock_next_free_mutex >= _MAX_LOCK)
523         {
524 
525             /* Yes, set the free index back to 0.  */
526             __tx_iar_system_lock_next_free_mutex =  0;
527         }
528 
529         /* Is this mutex free?  */
530         if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
531         {
532 
533             /* Yes, this mutex is free, get out of the loop!  */
534             break;
535         }
536     }
537 
538     /* Determine if a free mutex was found.   */
539     if (i >= _MAX_LOCK)
540     {
541 
542         /* Error!  No more free mutexes!  */
543 
544         /* Increment the no mutexes error counter.  */
545         __tx_iar_system_lock_no_mutexes++;
546 
547         /* Set return pointer to NULL.  */
548         *m =  TX_NULL;
549 
550         /* Return.  */
551         return;
552     }
553 
554     /* Now create the ThreadX mutex for the IAR library.  */
555     status =  _tx_mutex_create(mutex_ptr, "IAR System Library Lock", TX_NO_INHERIT);
556 
557     /* Determine if the creation was successful.  */
558     if (status == TX_SUCCESS)
559     {
560 
561         /* Yes, successful creation, return mutex pointer.  */
562         *m =  (VOID *) mutex_ptr;
563     }
564     else
565     {
566 
567         /* Increment the internal error counter.  */
568         __tx_iar_system_lock_internal_errors++;
569 
570         /* Return a NULL pointer to indicate an error.  */
571         *m =  TX_NULL;
572     }
573 }
574 
__iar_system_Mtxdst(__iar_Rmtx * m)575 void __iar_system_Mtxdst(__iar_Rmtx *m)
576 {
577 
578     /* Simply delete the mutex.  */
579     _tx_mutex_delete((TX_MUTEX *) *m);
580 }
581 
__iar_system_Mtxlock(__iar_Rmtx * m)582 void __iar_system_Mtxlock(__iar_Rmtx *m)
583 {
584   if (*m)
585   {
586     UINT    status;
587 
588     /* Determine the caller's context. Mutex locks are only available from initialization and
589        threads.  */
590     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
591     {
592 
593         /* Get the mutex.  */
594         status =  _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
595 
596         /* Check the status of the mutex release.  */
597         if (status)
598         {
599 
600             /* Internal error, increment the counter.  */
601             __tx_iar_system_lock_internal_errors++;
602         }
603     }
604     else
605     {
606 
607         /* Increment the ISR caller error.  */
608         __tx_iar_system_lock_isr_caller++;
609     }
610   }
611 }
612 
__iar_system_Mtxunlock(__iar_Rmtx * m)613 void __iar_system_Mtxunlock(__iar_Rmtx *m)
614 {
615   if (*m)
616   {
617     UINT    status;
618 
619     /* Determine the caller's context. Mutex unlocks are only available from initialization and
620        threads.  */
621     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
622     {
623 
624         /* Release the mutex.  */
625         status =  _tx_mutex_put((TX_MUTEX *) *m);
626 
627         /* Check the status of the mutex release.  */
628         if (status)
629         {
630 
631             /* Internal error, increment the counter.  */
632             __tx_iar_system_lock_internal_errors++;
633         }
634     }
635     else
636     {
637 
638         /* Increment the ISR caller error.  */
639         __tx_iar_system_lock_isr_caller++;
640     }
641   }
642 }
643 
644 
645 #if _DLIB_FILE_DESCRIPTOR
646 
647 #include <stdio.h>                        /* Added to get access to FOPEN_MAX */
648 #ifndef _MAX_FLOCK
649 #define _MAX_FLOCK FOPEN_MAX              /* Define _MAX_FLOCK as the maximum number of open files */
650 #endif
651 
652 
653 TX_MUTEX    __tx_iar_file_lock_mutexes[_MAX_FLOCK];
654 UINT        __tx_iar_file_lock_next_free_mutex =  0;
655 
656 
657 /* Define error counters, just for debug purposes.  */
658 
659 UINT        __tx_iar_file_lock_no_mutexes;
660 UINT        __tx_iar_file_lock_internal_errors;
661 UINT        __tx_iar_file_lock_isr_caller;
662 
663 
__iar_file_Mtxinit(__iar_Rmtx * m)664 void __iar_file_Mtxinit(__iar_Rmtx *m)
665 {
666 
667 UINT        i;
668 UINT        status;
669 TX_MUTEX    *mutex_ptr;
670 
671 
672     /* First, find a free mutex in the list.  */
673     for (i = 0; i < _MAX_FLOCK; i++)
674     {
675 
676         /* Setup a pointer to the start of the next free mutex.  */
677         mutex_ptr =  &__tx_iar_file_lock_mutexes[__tx_iar_file_lock_next_free_mutex++];
678 
679         /* Check for wrap-around on the next free mutex.  */
680         if (__tx_iar_file_lock_next_free_mutex >= _MAX_LOCK)
681         {
682 
683             /* Yes, set the free index back to 0.  */
684             __tx_iar_file_lock_next_free_mutex =  0;
685         }
686 
687         /* Is this mutex free?  */
688         if (mutex_ptr -> tx_mutex_id != TX_MUTEX_ID)
689         {
690 
691             /* Yes, this mutex is free, get out of the loop!  */
692             break;
693         }
694     }
695 
696     /* Determine if a free mutex was found.   */
697     if (i >= _MAX_LOCK)
698     {
699 
700         /* Error!  No more free mutexes!  */
701 
702         /* Increment the no mutexes error counter.  */
703         __tx_iar_file_lock_no_mutexes++;
704 
705         /* Set return pointer to NULL.  */
706         *m =  TX_NULL;
707 
708         /* Return.  */
709         return;
710     }
711 
712     /* Now create the ThreadX mutex for the IAR library.  */
713     status =  _tx_mutex_create(mutex_ptr, "IAR File Library Lock", TX_NO_INHERIT);
714 
715     /* Determine if the creation was successful.  */
716     if (status == TX_SUCCESS)
717     {
718 
719         /* Yes, successful creation, return mutex pointer.  */
720         *m =  (VOID *) mutex_ptr;
721     }
722     else
723     {
724 
725         /* Increment the internal error counter.  */
726         __tx_iar_file_lock_internal_errors++;
727 
728         /* Return a NULL pointer to indicate an error.  */
729         *m =  TX_NULL;
730     }
731 }
732 
__iar_file_Mtxdst(__iar_Rmtx * m)733 void __iar_file_Mtxdst(__iar_Rmtx *m)
734 {
735 
736     /* Simply delete the mutex.  */
737     _tx_mutex_delete((TX_MUTEX *) *m);
738 }
739 
__iar_file_Mtxlock(__iar_Rmtx * m)740 void __iar_file_Mtxlock(__iar_Rmtx *m)
741 {
742 
743 UINT    status;
744 
745 
746     /* Determine the caller's context. Mutex locks are only available from initialization and
747        threads.  */
748     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
749     {
750 
751         /* Get the mutex.  */
752         status =  _tx_mutex_get((TX_MUTEX *) *m, TX_WAIT_FOREVER);
753 
754         /* Check the status of the mutex release.  */
755         if (status)
756         {
757 
758             /* Internal error, increment the counter.  */
759             __tx_iar_file_lock_internal_errors++;
760         }
761     }
762     else
763     {
764 
765         /* Increment the ISR caller error.  */
766         __tx_iar_file_lock_isr_caller++;
767     }
768 }
769 
__iar_file_Mtxunlock(__iar_Rmtx * m)770 void __iar_file_Mtxunlock(__iar_Rmtx *m)
771 {
772 
773 UINT    status;
774 
775 
776     /* Determine the caller's context. Mutex unlocks are only available from initialization and
777        threads.  */
778     if ((_tx_thread_system_state == 0) || (_tx_thread_system_state >= TX_INITIALIZE_IN_PROGRESS))
779     {
780 
781         /* Release the mutex.  */
782         status =  _tx_mutex_put((TX_MUTEX *) *m);
783 
784         /* Check the status of the mutex release.  */
785         if (status)
786         {
787 
788             /* Internal error, increment the counter.  */
789             __tx_iar_file_lock_internal_errors++;
790         }
791     }
792     else
793     {
794 
795         /* Increment the ISR caller error.  */
796         __tx_iar_file_lock_isr_caller++;
797     }
798 }
799 #endif  /* _DLIB_FILE_DESCRIPTOR */
800 
801 #endif  /* TX_ENABLE_IAR_LIBRARY_SUPPORT  */
802 
803 #endif /* IAR version 8 and above.  */
804