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