1570af302Sopenharmony_ci#include <unistd.h> 2570af302Sopenharmony_ci#include <errno.h> 3570af302Sopenharmony_ci#include "libc.h" 4570af302Sopenharmony_ci#include "lock.h" 5570af302Sopenharmony_ci#include "pthread_impl.h" 6570af302Sopenharmony_ci#include "fork_impl.h" 7570af302Sopenharmony_ci 8570af302Sopenharmony_cistatic volatile int *const dummy_lockptr = 0; 9570af302Sopenharmony_ci 10570af302Sopenharmony_ciweak_alias(dummy_lockptr, __at_quick_exit_lockptr); 11570af302Sopenharmony_ciweak_alias(dummy_lockptr, __atexit_lockptr); 12570af302Sopenharmony_ciweak_alias(dummy_lockptr, __gettext_lockptr); 13570af302Sopenharmony_ciweak_alias(dummy_lockptr, __locale_lockptr); 14570af302Sopenharmony_ciweak_alias(dummy_lockptr, __random_lockptr); 15570af302Sopenharmony_ciweak_alias(dummy_lockptr, __sem_open_lockptr); 16570af302Sopenharmony_ciweak_alias(dummy_lockptr, __stdio_ofl_lockptr); 17570af302Sopenharmony_ciweak_alias(dummy_lockptr, __syslog_lockptr); 18570af302Sopenharmony_ciweak_alias(dummy_lockptr, __timezone_lockptr); 19570af302Sopenharmony_ciweak_alias(dummy_lockptr, __bump_lockptr); 20570af302Sopenharmony_ci 21570af302Sopenharmony_ciweak_alias(dummy_lockptr, __vmlock_lockptr); 22570af302Sopenharmony_ci 23570af302Sopenharmony_cistatic volatile int *const *const atfork_locks[] = { 24570af302Sopenharmony_ci &__at_quick_exit_lockptr, 25570af302Sopenharmony_ci &__atexit_lockptr, 26570af302Sopenharmony_ci &__gettext_lockptr, 27570af302Sopenharmony_ci &__locale_lockptr, 28570af302Sopenharmony_ci &__random_lockptr, 29570af302Sopenharmony_ci &__sem_open_lockptr, 30570af302Sopenharmony_ci &__stdio_ofl_lockptr, 31570af302Sopenharmony_ci &__syslog_lockptr, 32570af302Sopenharmony_ci &__timezone_lockptr, 33570af302Sopenharmony_ci &__bump_lockptr, 34570af302Sopenharmony_ci}; 35570af302Sopenharmony_ci 36570af302Sopenharmony_cistatic void dummy(int x) { } 37570af302Sopenharmony_ciweak_alias(dummy, __fork_handler); 38570af302Sopenharmony_ciweak_alias(dummy, __malloc_atfork); 39570af302Sopenharmony_ciweak_alias(dummy, __aio_atfork); 40570af302Sopenharmony_ciweak_alias(dummy, __pthread_key_atfork); 41570af302Sopenharmony_ciweak_alias(dummy, __ldso_atfork); 42570af302Sopenharmony_ci 43570af302Sopenharmony_cistatic void dummy_0(void) { } 44570af302Sopenharmony_ciweak_alias(dummy_0, __tl_lock); 45570af302Sopenharmony_ciweak_alias(dummy_0, __tl_unlock); 46570af302Sopenharmony_ci 47570af302Sopenharmony_cipid_t fork(void) 48570af302Sopenharmony_ci{ 49570af302Sopenharmony_ci sigset_t set; 50570af302Sopenharmony_ci __fork_handler(-1); 51570af302Sopenharmony_ci __block_app_sigs(&set); 52570af302Sopenharmony_ci int need_locks = libc.need_locks > 0; 53570af302Sopenharmony_ci if (need_locks) { 54570af302Sopenharmony_ci __ldso_atfork(-1); 55570af302Sopenharmony_ci __pthread_key_atfork(-1); 56570af302Sopenharmony_ci __aio_atfork(-1); 57570af302Sopenharmony_ci __inhibit_ptc(); 58570af302Sopenharmony_ci for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++) 59570af302Sopenharmony_ci if (*atfork_locks[i]) LOCK(*atfork_locks[i]); 60570af302Sopenharmony_ci __malloc_atfork(-1); 61570af302Sopenharmony_ci __tl_lock(); 62570af302Sopenharmony_ci } 63570af302Sopenharmony_ci pthread_t self=__pthread_self(), next=self->next; 64570af302Sopenharmony_ci pid_t ret = _Fork(); 65570af302Sopenharmony_ci int errno_save = errno; 66570af302Sopenharmony_ci if (need_locks) { 67570af302Sopenharmony_ci if (!ret) { 68570af302Sopenharmony_ci for (pthread_t td=next; td!=self; td=td->next) 69570af302Sopenharmony_ci td->tid = -1; 70570af302Sopenharmony_ci if (__vmlock_lockptr) { 71570af302Sopenharmony_ci __vmlock_lockptr[0] = 0; 72570af302Sopenharmony_ci __vmlock_lockptr[1] = 0; 73570af302Sopenharmony_ci } 74570af302Sopenharmony_ci } 75570af302Sopenharmony_ci __tl_unlock(); 76570af302Sopenharmony_ci __malloc_atfork(!ret); 77570af302Sopenharmony_ci for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++) 78570af302Sopenharmony_ci if (*atfork_locks[i]) 79570af302Sopenharmony_ci if (ret) UNLOCK(*atfork_locks[i]); 80570af302Sopenharmony_ci else **atfork_locks[i] = 0; 81570af302Sopenharmony_ci __release_ptc(); 82570af302Sopenharmony_ci if (ret) __aio_atfork(0); 83570af302Sopenharmony_ci __pthread_key_atfork(!ret); 84570af302Sopenharmony_ci __ldso_atfork(!ret); 85570af302Sopenharmony_ci } 86570af302Sopenharmony_ci __restore_sigs(&set); 87570af302Sopenharmony_ci __fork_handler(!ret); 88570af302Sopenharmony_ci if (ret<0) errno = errno_save; 89570af302Sopenharmony_ci return ret; 90570af302Sopenharmony_ci} 91