Serenity Operating System
at hosted 86 lines 3.3 kB view raw
1/* 2 * Copyright (c) 2019-2020, Andrew Kaster <andrewdkaster@gmail.com> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions are met: 7 * 8 * 1. Redistributions of source code must retain the above copyright notice, this 9 * list of conditions and the following disclaimer. 10 * 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 18 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER 22 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 23 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 24 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 25 */ 26 27#include <AK/Types.h> 28#include <assert.h> 29#include <stdio.h> 30#include <stdlib.h> 31 32//#define GLOBAL_DTORS_DEBUG 33 34extern "C" { 35 36typedef void (*AtExitFunction)(void*); 37 38struct __exit_entry { 39 AtExitFunction method; 40 void* parameter; 41 void* dso_handle; 42 bool has_been_called; 43}; 44 45static __exit_entry __exit_entries[1024] {}; 46static int __exit_entry_count = 0; 47 48int __cxa_atexit(AtExitFunction exit_function, void* parameter, void* dso_handle) 49{ 50 if (__exit_entry_count >= 1024) 51 return -1; 52 53 __exit_entries[__exit_entry_count++] = { exit_function, parameter, dso_handle, false }; 54 55 return 0; 56} 57 58void __cxa_finalize(void* dso_handle) 59{ 60 // From the itanium abi, https://itanium-cxx-abi.github.io/cxx-abi/abi.html#dso-dtor-runtime-api 61 // 62 // When __cxa_finalize(d) is called, it should walk the termination function list, calling each in turn 63 // if d matches __dso_handle for the termination function entry. If d == NULL, it should call all of them. 64 // Multiple calls to __cxa_finalize shall not result in calling termination function entries multiple times; 65 // the implementation may either remove entries or mark them finished. 66 67 int entry_index = __exit_entry_count; 68 69#ifdef GLOBAL_DTORS_DEBUG 70 dbgprintf("__cxa_finalize: %d entries in the finalizer list\n", entry_index); 71#endif 72 73 while (--entry_index >= 0) { 74 auto& exit_entry = __exit_entries[entry_index]; 75 bool needs_calling = !exit_entry.has_been_called && (!dso_handle || dso_handle == exit_entry.dso_handle); 76 if (needs_calling) { 77#ifdef GLOBAL_DTORS_DEBUG 78 dbgprintf("__cxa_finalize: calling entry[%d] %p(%p) dso: %p\n", entry_index, exit_entry.method, exit_entry.parameter, exit_entry.dso_handle); 79#endif 80 exit_entry.method(exit_entry.parameter); 81 exit_entry.has_been_called = true; 82 } 83 } 84} 85 86} // extern "C"