Server IP : 172.67.216.182 / Your IP : 162.158.163.213 Web Server : Apache System : Linux krdc-ubuntu-s-2vcpu-4gb-amd-blr1-01.localdomain 5.15.0-142-generic #152-Ubuntu SMP Mon May 19 10:54:31 UTC 2025 x86_64 User : www ( 1000) PHP Version : 7.4.33 Disable Function : passthru,exec,system,putenv,chroot,chgrp,chown,shell_exec,popen,proc_open,pcntl_exec,ini_alter,ini_restore,dl,openlog,syslog,readlink,symlink,popepassthru,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,imap_open,apache_setenv MySQL : OFF | cURL : ON | WGET : ON | Perl : ON | Python : OFF | Sudo : ON | Pkexec : ON Directory : /www/server/mysql/src/storage/innobase/os/ |
Upload File : |
/***************************************************************************** Copyright (c) 1995, 2023, Oracle and/or its affiliates. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License, version 2.0, as published by the Free Software Foundation. This program is also distributed with certain software (including but not limited to OpenSSL) that is licensed under separate terms, as designated in a particular file or component or in included license documentation. The authors of MySQL hereby grant you an additional permission to link the program and your derivative works with the separately licensed software that they have included with MySQL. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License, version 2.0, for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA *****************************************************************************/ /**************************************************//** @file os/os0thread.cc The interface to the operating system thread control primitives Created 9/8/1995 Heikki Tuuri *******************************************************/ #include "ha_prototypes.h" #include "os0thread.h" #include "ut0new.h" #ifdef UNIV_NONINL #include "os0thread.ic" #endif #ifndef UNIV_HOTBACKUP #include "srv0srv.h" #include "os0event.h" #include <map> /** Mutex that tracks the thread count. Used by innorwlocktest.cc FIXME: the unit tests should use APIs */ SysMutex thread_mutex; /** Number of threads active. */ ulint os_thread_count; #ifdef _WIN32 typedef std::map< DWORD, HANDLE, std::less<DWORD>, ut_allocator<std::pair<const DWORD, HANDLE> > > WinThreadMap; /** This STL map remembers the initial handle returned by CreateThread so that it can be closed when the thread exits. */ static WinThreadMap win_thread_map; #endif /* _WIN32 */ /***************************************************************//** Compares two thread ids for equality. @return TRUE if equal */ ibool os_thread_eq( /*=========*/ os_thread_id_t a, /*!< in: OS thread or thread id */ os_thread_id_t b) /*!< in: OS thread or thread id */ { #ifdef _WIN32 if (a == b) { return(TRUE); } return(FALSE); #else if (pthread_equal(a, b)) { return(TRUE); } return(FALSE); #endif } /****************************************************************//** Converts an OS thread id to a ulint. It is NOT guaranteed that the ulint is unique for the thread though! @return thread identifier as a number */ ulint os_thread_pf( /*=========*/ os_thread_id_t a) /*!< in: OS thread identifier */ { return((ulint) a); } /*****************************************************************//** Returns the thread identifier of current thread. Currently the thread identifier in Unix is the thread handle itself. Note that in HP-UX pthread_t is a struct of 3 fields. @return current thread identifier */ os_thread_id_t os_thread_get_curr_id(void) /*=======================*/ { #ifdef _WIN32 return(GetCurrentThreadId()); #else return(pthread_self()); #endif } /****************************************************************//** Creates a new thread of execution. The execution starts from the function given. NOTE: We count the number of threads in os_thread_exit(). A created thread should always use that to exit so thatthe thread count will be decremented. We do not return an error code because if there is one, we crash here. */ void os_thread_create_func( /*==================*/ os_thread_func_t func, /*!< in: pointer to function from which to start */ void* arg, /*!< in: argument to start function */ os_thread_id_t* thread_id) /*!< out: id of the created thread, or NULL */ { os_thread_id_t new_thread_id; /* the new thread should look recent changes up here so far. */ os_wmb; #ifdef _WIN32 HANDLE handle; handle = CreateThread(NULL, /* no security attributes */ 0, /* default size stack */ func, arg, 0, /* thread runs immediately */ &new_thread_id); if (!handle) { /* If we cannot start a new thread, life has no meaning. */ ib::fatal() << "CreateThread returned " << GetLastError(); } mutex_enter(&thread_mutex); std::pair<WinThreadMap::iterator, bool> ret; ret = win_thread_map.insert( std::pair<DWORD, HANDLE>(new_thread_id, handle)); ut_ad((*ret.first).first == new_thread_id); ut_ad((*ret.first).second == handle); ut_a(ret.second == true); /* true means thread_id was new */ os_thread_count++; mutex_exit(&thread_mutex); #else /* _WIN32 else */ pthread_attr_t attr; pthread_attr_init(&attr); mutex_enter(&thread_mutex); ++os_thread_count; mutex_exit(&thread_mutex); int ret = pthread_create(&new_thread_id, &attr, func, arg); if (ret != 0) { ib::fatal() << "pthread_create returned " << ret; } pthread_attr_destroy(&attr); #endif /* not _WIN32 */ ut_a(os_thread_count <= OS_THREAD_MAX_N); /* Return the thread_id if the caller requests it. */ if (thread_id != NULL) { *thread_id = new_thread_id; } } /** Waits until the specified thread completes and joins it. Its return value is ignored. @param[in,out] thread thread to join */ void os_thread_join( os_thread_id_t thread) { #ifdef _WIN32 /* Do nothing. */ #else #ifdef UNIV_DEBUG const int ret = #endif /* UNIV_DEBUG */ pthread_join(thread, NULL); /* Waiting on already-quit threads is allowed. */ ut_ad(ret == 0 || ret == ESRCH); #endif /* _WIN32 */ } /** Exits the current thread. @param[in] detach if true, the thread will be detached right before exiting. If false, another thread is responsible for joining this thread */ void os_thread_exit( bool detach) { #ifdef UNIV_DEBUG_THREAD_CREATION ib::info() << "Thread exits, id " << os_thread_pf(os_thread_get_curr_id()); #endif #ifdef UNIV_PFS_THREAD pfs_delete_thread(); #endif mutex_enter(&thread_mutex); os_thread_count--; #ifdef _WIN32 DWORD win_thread_id = GetCurrentThreadId(); HANDLE handle = win_thread_map[win_thread_id]; CloseHandle(handle); size_t ret = win_thread_map.erase(win_thread_id); ut_a(ret == 1); mutex_exit(&thread_mutex); ExitThread(0); #else mutex_exit(&thread_mutex); if (detach) { pthread_detach(pthread_self()); } pthread_exit(NULL); #endif } /*****************************************************************//** Advises the os to give up remainder of the thread's time slice. */ void os_thread_yield(void) /*=================*/ { #if defined(_WIN32) SwitchToThread(); #else sched_yield(); #endif } #endif /* !UNIV_HOTBACKUP */ /*****************************************************************//** The thread sleeps at least the time given in microseconds. */ void os_thread_sleep( /*============*/ ulint tm) /*!< in: time in microseconds */ { #ifdef _WIN32 Sleep((DWORD) tm / 1000); #elif defined(HAVE_NANOSLEEP) struct timespec t; t.tv_sec = tm / 1000000; t.tv_nsec = (tm % 1000000) * 1000; ::nanosleep(&t, NULL); #else struct timeval t; t.tv_sec = tm / 1000000; t.tv_usec = tm % 1000000; select(0, NULL, NULL, NULL, &t); #endif /* _WIN32 */ } /*****************************************************************//** Check if there are threads active. @return true if the thread count > 0. */ bool os_thread_active() /*==============*/ { mutex_enter(&thread_mutex); bool active = (os_thread_count > 0); /* All the threads have exited or are just exiting; NOTE that the threads may not have completed their exit yet. Should we use pthread_join() to make sure they have exited? If we did, we would have to remove the pthread_detach() from os_thread_exit(). Now we just sleep 0.1 seconds and hope that is enough! */ mutex_exit(&thread_mutex); return(active); } /** Initializes OS thread management data structures. */ void os_thread_init() /*============*/ { mutex_create(LATCH_ID_THREAD_MUTEX, &thread_mutex); } /** Frees OS thread management data structures. */ void os_thread_free() /*============*/ { if (os_thread_count != 0) { ib::warn() << "Some (" << os_thread_count << ") threads are" " still active"; } mutex_destroy(&thread_mutex); }