⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pthread.c

📁 GNUnet是一个安全的点对点网络框架
💻 C
字号:
/*     This file is part of GNUnet.     (C) 2001, 2002, 2003, 2004, 2006 Christian Grothoff (and other contributing authors)     GNUnet is free software; you can redistribute it and/or modify     it under the terms of the GNU General Public License as published     by the Free Software Foundation; either version 2, or (at your     option) any later version.     GNUnet 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 for more details.     You should have received a copy of the GNU General Public License     along with GNUnet; see the file COPYING.  If not, write to the     Free Software Foundation, Inc., 59 Temple Place - Suite 330,     Boston, MA 02111-1307, USA.*//** * @file util/threads/pthread.c * @brief implementation of pthread start/join/sleep */#include "platform.h"#include "gnunet_util_threads.h"#include "gnunet_util_error.h"#include "gnunet_util_string.h"#if SOLARIS || GNUNET_freeBSD || OSX#include <semaphore.h>#endif#if SOMEBSD# include <pthread_np.h># include <sys/file.h>#endif#if LINUX# include <sys/sem.h>#endif#ifdef _MSC_VER#include <pthread.h>#endiftypedef struct GNUNET_ThreadHandle{  pthread_t pt;} PThread;/** * Returns GNUNET_YES if pt is the handle for THIS thread. */intGNUNET_thread_test_self (PThread * handle){  if (handle == NULL)    return GNUNET_NO;#if HAVE_PTHREAD_EQUAL  if (pthread_equal (pthread_self (), handle->pt))#else#if HAVE_NEW_PTHREAD_T  if (handle->pt->p == pthread_self ().p)#else  if (handle->pt == pthread_self ())#endif#endif    return GNUNET_YES;  else    return GNUNET_NO;}/** * Get the handle for THIS thread. */PThread *GNUNET_thread_get_self (){  PThread *ret;  ret = GNUNET_malloc (sizeof (PThread));  ret->pt = pthread_self ();  return ret;}/** * Release handle for a thread. */voidGNUNET_thread_release_self (PThread * handle){  GNUNET_free (handle);}/** * Create a thread. Use this method instead of pthread_create since * BSD may only give a 1k stack otherwise. * * @param handle handle to the pthread (for detaching, join) * @param main the main method of the thread * @param arg the argument to main * @param stackSize the size of the stack of the thread in bytes. *        Note that if the stack overflows, some OSes (seen under BSD) *        will just segfault and gdb will give a messed-up stacktrace. * @return see pthread_create */PThread *GNUNET_thread_create (GNUNET_ThreadMainFunction main, void *arg,                      unsigned int stackSize){  PThread *handle;#ifndef LINUX  pthread_attr_t stack_size_custom_attr;#endif  int ret;  handle = GNUNET_malloc (sizeof (PThread));#ifdef MINGW  memset (handle, 0, sizeof (PThread));#endif#ifndef LINUX  pthread_attr_init (&stack_size_custom_attr);  pthread_attr_setstacksize (&stack_size_custom_attr, stackSize);#endif  ret = pthread_create (&handle->pt,#ifndef LINUX                        &stack_size_custom_attr,#else                        NULL,#endif                        main, arg);  if (ret != 0)    {      GNUNET_free (handle);      return NULL;    }  return handle;}voidGNUNET_thread_join_at_file_line_ (PThread * handle,                                  void **ret, const char *file,                                  unsigned int line){  GNUNET_CronTime start;  GNUNET_CronTime end;  int k;  GNUNET_GE_ASSERT (NULL, handle != NULL);  GNUNET_GE_ASSERT (NULL, GNUNET_NO == GNUNET_thread_test_self (handle));  start = GNUNET_get_time ();  k = pthread_join (handle->pt, ret);  end = GNUNET_get_time ();  if ((end - start > GNUNET_REALTIME_LIMIT) && (GNUNET_REALTIME_LIMIT != 0))    {      GNUNET_GE_LOG (NULL,                     GNUNET_GE_DEVELOPER | GNUNET_GE_WARNING |                     GNUNET_GE_IMMEDIATE,                     _("Real-time delay violation (%llu ms) at %s:%u\n"),                     end - start, file, line);    }  GNUNET_free (handle);  switch (k)    {    case 0:      return;    case ESRCH:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_FATAL | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_IMMEDIATE,                     _("`%s' failed with error code %s: %s\n"),                     "pthread_join", "ESRCH", STRERROR (errno));      break;    case EINVAL:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_FATAL | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_IMMEDIATE,                     _("`%s' failed with error code %s: %s\n"),                     "pthread_join", "EINVAL", STRERROR (errno));    case EDEADLK:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_FATAL | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_IMMEDIATE,                     _("`%s' failed with error code %s: %s\n"),                     "pthread_join", "EDEADLK", STRERROR (errno));    default:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_FATAL | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_IMMEDIATE,                     _("`%s' failed with error code %d: %s\n"),                     "pthread_join", k, STRERROR (errno));    }  GNUNET_GE_ASSERT (NULL, 0);}#ifdef WINDOWS/** * @brief Called if a sleeping thread is interrupted */static void CALLBACK__PTHREAD_SIGNALED (DWORD sig){}#elsestatic voidsigalrmHandler (int sig){}#endif/** * Sleep for the specified time interval.  Use GNUNET_thread_stop_sleep to * wake the thread up early.  Caller is responsible to check that the * sleep was long enough. */voidGNUNET_thread_sleep (unsigned long long delay){#if LINUX || SOLARIS || SOMEBSD || OSX  struct timespec req;  struct timespec rem;#elif WINDOWS#else  int ret;  struct timeval timeout;#endif  /* actual sleep */#if LINUX || SOLARIS || SOMEBSD || OSX  req.tv_sec = delay / 1000;    /* ms -> seconds */  req.tv_nsec = (delay - req.tv_sec * 1000) * 1000 * 1000;      /* ms -> ns */  rem.tv_sec = 0;  rem.tv_nsec = 0;  if ((0 != nanosleep (&req, &rem)) && (errno != EINTR))    GNUNET_GE_LOG_STRERROR (NULL,                            GNUNET_GE_WARNING | GNUNET_GE_USER |                            GNUNET_GE_BULK, "nanosleep");#elif WINDOWS  SleepEx (delay, TRUE);#else  /* fall back to select */  timeout.tv_sec = delay / CRON_UNIT_TO_SECONDS;  timeout.tv_usec    = (delay - timeout.tv_sec * CRON_UNIT_TO_SECONDS) * MICROSEC_TO_CRON_UNIT;  ret = SELECT (0, NULL, NULL, NULL, &timeout);  if ((ret == -1) && (errno != EINTR))    GNUNET_GE_LOG_STRERROR (NULL,                            GNUNET_GE_WARNING | GNUNET_GE_USER |                            GNUNET_GE_BULK, "select");#endif}voidGNUNET_thread_stop_sleep (PThread * handle){  int ret;  if (handle == NULL)    return;#ifdef WINDOWS  ret = QueueUserAPC ((PAPCFUNC) __PTHREAD_SIGNALED,                      pthread_getw32threadhandle_np (handle->pt),                      0) != 0 ? 0 : EINVAL;#else  ret = pthread_kill (handle->pt, SIGALRM);#endif  switch (ret)    {    case 0:      break;                    /* ok */    case EINVAL:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_BULK,                     _("`%s' failed with error code %s: %s\n"),                     "pthread_kill", "EINVAL", STRERROR (ret));      break;    case ESRCH:      /* ignore, thread might have already exited by chance */      break;    default:      GNUNET_GE_LOG (NULL,                     GNUNET_GE_ERROR | GNUNET_GE_USER | GNUNET_GE_DEVELOPER |                     GNUNET_GE_BULK,                     _("`%s' failed with error code %d: %s\n"),                     "pthread_kill", ret, STRERROR (ret));      break;    }}#ifndef MINGWstatic struct sigaction sig;static struct sigaction old;#endif/** * Initialize the signal handlers, etc. */void __attribute__ ((constructor)) GNUNET_pthread_handlers_ltdl_init (){  /* make sure SIGALRM does not kill us */#ifndef MINGW  memset (&sig, 0, sizeof (struct sigaction));  memset (&old, 0, sizeof (struct sigaction));  sig.sa_flags = SA_NODEFER;  sig.sa_handler = &sigalrmHandler;  if (0 != sigaction (SIGALRM, &sig, &old))    GNUNET_GE_LOG_STRERROR (NULL,                            GNUNET_GE_WARNING | GNUNET_GE_ADMIN |                            GNUNET_GE_BULK, "sigaction");#else  InitWinEnv (NULL);#endif}void __attribute__ ((destructor)) GNUNET_pthread_handlers_ltdl_fini (){#ifndef MINGW  if (0 != sigaction (SIGALRM, &old, &sig))    GNUNET_GE_LOG_STRERROR (NULL,                            GNUNET_GE_WARNING | GNUNET_GE_ADMIN |                            GNUNET_GE_BULK, "sigaction");#else  ShutdownWinEnv ();#endif}/* end of pthread.c */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -