1 /**************************************************************************/
2 /*                                                                        */
3 /*       Copyright (c) Microsoft Corporation. All rights reserved.        */
4 /*                                                                        */
5 /*       This software is licensed under the Microsoft Software License   */
6 /*       Terms for Microsoft Azure RTOS. Full text of the license can be  */
7 /*       found in the LICENSE file at https://aka.ms/AzureRTOS_EULA       */
8 /*       and in the root directory of this software.                      */
9 /*                                                                        */
10 /**************************************************************************/
11 
12 
13 /**************************************************************************/
14 /**************************************************************************/
15 /**                                                                       */
16 /** POSIX wrapper for THREADX                                             */
17 /**                                                                       */
18 /**                                                                       */
19 /**                                                                       */
20 /**************************************************************************/
21 /**************************************************************************/
22 
23 /* Include necessary system files.  */
24 
25 #include "tx_api.h"     /* Threadx API */
26 #include "pthread.h"    /* Posix API */
27 #include "px_int.h"     /* Posix helper functions */
28 #include "tx_thread.h"  /* Internal ThreadX thread management.  */
29 
30 /**************************************************************************/
31 /*                                                                        */
32 /*  FUNCTION                                               RELEASE        */
33 /*                                                                        */
34 /*    internal_signal_dispatch                            PORTABLE C      */
35 /*                                                           6.1.7        */
36 /*  AUTHOR                                                                */
37 /*                                                                        */
38 /*    William E. Lamie, Microsoft Corporation                             */
39 /*                                                                        */
40 /*  DESCRIPTION                                                           */
41 /*                                                                        */
42 /*     Signal handler thread.                                             */
43 /*                                                                        */
44 /*  INPUT                                                                 */
45 /*                                                                        */
46 /*    id                             Signal                               */
47 /*                                                                        */
48 /*  OUTPUT                                                                */
49 /*                                                                        */
50 /*     none                                                               */
51 /*                                                                        */
52 /*  CALLS                                                                 */
53 /*                                                                        */
54 /*    posix_internal_error                  Generic error Handler         */
55 /*    tx_thread_identify                                                  */
56 /*    tx_event_flags_set                                                  */
57 /*    tx_thread_resume                                                    */
58 /*    posix_destroy_pthread                                               */
59 /*    tx_thread_suspend                                                   */
60 /*                                                                        */
61 /*  CALLED BY                                                             */
62 /*                                                                        */
63 /*    Internal Code                                                       */
64 /*                                                                        */
65 /*  RELEASE HISTORY                                                       */
66 /*                                                                        */
67 /*    DATE              NAME                      DESCRIPTION             */
68 /*                                                                        */
69 /*  06-02-2021     William E. Lamie         Initial Version 6.1.7         */
70 /*                                                                        */
71 /**************************************************************************/
internal_signal_dispatch(ULONG id)72 void  internal_signal_dispatch(ULONG id)
73 {
74 
75 TX_INTERRUPT_SAVE_AREA
76 
77 POSIX_TCB   *signal_thread;
78 POSIX_TCB   *target_thread;
79 VOID        (*handler)(int);
80 
81 
82     /* Determine if the desired signal is valid.  */
83     if (id > SIGRTMAX)
84     {
85 
86         /* System error!  */
87         posix_internal_error(444);
88         return;
89     }
90 
91     /* Pickup signal thread.  */
92     signal_thread =  (POSIX_TCB *) tx_thread_identify();
93 
94     /* Is it non-NULL?  */
95     if (!signal_thread)
96     {
97 
98         /* System error!  */
99         posix_internal_error(444);
100         return;
101     }
102 
103     /* Pickup target thread.  */
104     target_thread =  signal_thread -> signals.base_thread_ptr;
105 
106     /* Pickup signal handler function pointer.  */
107     handler =  target_thread -> signals.signal_func[id];
108 
109     /* See if there is a signal handler setup for this signal.  */
110     if (handler)
111     {
112 
113         /* Yes, there is a signal handler - call it!  */
114         (handler)((int) id);
115     }
116 
117     /* Set the event flag corresponding the signal.  */
118     tx_event_flags_set(&(target_thread -> signals.signal_event_flags), (((ULONG) 1) << id), TX_OR);
119 
120     /* Ensure the flag is left in a clear state.  */
121     tx_event_flags_set(&(target_thread -> signals.signal_event_flags), ~(((ULONG) 1) << id), TX_AND);
122 
123     /* Now we need to clear this signal and terminate this signal handler thread.  */
124 
125     /* Disable interrupts.  */
126     TX_DISABLE
127 
128     /* Clear this signal from the pending list.  */
129     target_thread -> signals.signal_pending.signal_set =  target_thread -> signals.signal_pending.signal_set & ~(((unsigned long) 1) << id);
130 
131     /* Decrement the signal nesting count.  */
132     target_thread -> signals.signal_nesting_depth--;
133 
134     /* Is this the last nested signal leaving?  */
135     if (target_thread -> signals.signal_nesting_depth == 0)
136     {
137 
138         /* Clear the top signal thread link and resume the target thread.  */
139         target_thread -> signals.top_signal_thread =  NULL;
140 
141         /* Restore interrupts.  */
142         TX_RESTORE
143 
144         /* Resume the target thread.  */
145         tx_thread_resume((TX_THREAD *) target_thread);
146     }
147     else
148     {
149 
150         /* Otherwise, there are more signal threads still active.   */
151 
152         /* Setup the new top signal thread pointer.  */
153         target_thread -> signals.top_signal_thread =  signal_thread -> signals.next_signal_thread;
154 
155         /* Restore interrupts.  */
156         TX_RESTORE
157 
158         /* Resume the signal handler thread.  */
159         tx_thread_resume((TX_THREAD *) signal_thread -> signals.next_signal_thread);
160     }
161 
162     /* Now we need to mark this signal thread for destruction.  */
163     posix_destroy_pthread(signal_thread,(VOID *) 0);
164 
165     /* Self-suspend the current signal thread.  */
166     tx_thread_suspend((TX_THREAD *) signal_thread);
167 }
168