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

📄 thread.cc

📁 cygwin, 著名的在win32下模拟unix操作系统的东东
💻 CC
📖 第 1 页 / 共 4 页
字号:
/* thread.cc: Locking and threading module functions   Copyright 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.   Originally written by Marco Fuykschot <marco@ddi.nl>   Substantialy enhanced by Robert Collins <rbtcollins@hotmail.com>This file is part of Cygwin.This software is a copyrighted work licensed under the terms of theCygwin license.  Please consult the file "CYGWIN_LICENSE" fordetails. *//* Implementation overview and caveats:   Win32 puts some contraints on what can and cannot be implemented.  Where   possible we work around those contrainsts.  Where we cannot work around   the constraints we either pretend to be conformant, or return an error   code.   Some caveats: PROCESS_SHARED objects while they pretend to be process   shared, may not actually work.  Some test cases are needed to determine   win32's behaviour.  My suspicion is that the win32 handle needs to be   opened with different flags for proper operation.   R.Collins, April 2001.  */#ifdef HAVE_CONFIG_H# include "config.h"#endif#ifdef _MT_SAFE#include "winsup.h"#include <limits.h>#include <errno.h>#include "cygerrno.h"#include <assert.h>#include <stdlib.h>#include <syslog.h>#include "pinfo.h"#include "perprocess.h"#include "security.h"#include <semaphore.h>#include <stdio.h>#include <sys/timeb.h>extern int threadsafe;struct _reent *_reent_clib (){  struct __reent_t *_r =    (struct __reent_t *) MT_INTERFACE->reent_key.get ();#ifdef _CYG_THREAD_FAILSAFE  if (_r == 0)    system_printf ("local thread storage not inited");#endif  return _r->_clib;}struct _winsup_t *_reent_winsup (){  struct __reent_t *_r =    (struct __reent_t *) MT_INTERFACE->reent_key.get ();#ifdef _CYG_THREAD_FAILSAFE  if (_r == 0)    system_printf ("local thread storage not inited");#endif  return _r->_winsup;}inline LPCRITICAL_SECTIONResourceLocks::Lock (int _resid){#ifdef _CYG_THREAD_FAILSAFE  if (!inited)    system_printf ("lock called before initialization");  thread_printf    ("Get Resource lock %d ==> %p for %p , real : %d , threadid %d ", _resid,     &lock, user_data, myself->pid, GetCurrentThreadId ());#endif  return &lock;}voidSetResourceLock (int _res_id, int _mode, const char *_function){#ifdef _CYG_THREAD_FAILSAFE  thread_printf ("Set resource lock %d mode %d for %s start",		 _res_id, _mode, _function);#endif  EnterCriticalSection (user_data->resourcelocks->Lock (_res_id));#ifdef _CYG_THREAD_FAILSAFE  user_data->resourcelocks->owner = GetCurrentThreadId ();  user_data->resourcelocks->count++;#endif}voidReleaseResourceLock (int _res_id, int _mode, const char *_function){#ifdef _CYG_THREAD_FAILSAFE  thread_printf ("Release resource lock %d mode %d for %s done", _res_id,		 _mode, _function);  AssertResourceOwner (_res_id, _mode);  user_data->resourcelocks->count--;  if (user_data->resourcelocks->count == 0)    user_data->resourcelocks->owner = 0;#endif  LeaveCriticalSection (user_data->resourcelocks->Lock (_res_id));}#ifdef _CYG_THREAD_FAILSAFEvoidAssertResourceOwner (int _res_id, int _mode){  thread_printf    ("Assert Resource lock %d ==> for %p , real : %d , threadid %d count %d owner %d",     _res_id, user_data, myself->pid, GetCurrentThreadId (),     user_data->resourcelocks->count, user_data->resourcelocks->owner);  if (user_data && (user_data->resourcelocks->owner != GetCurrentThreadId ()))    system_printf ("assertion failed, not the resource owner");}#endifvoidResourceLocks::Init (){  InitializeCriticalSection (&lock);  inited = true;#ifdef _CYG_THREAD_FAILSAFE  owner = 0;  count = 0;#endif  thread_printf ("lock %p inited by %p , %d", &lock, user_data, myself->pid);}voidResourceLocks::Delete (){  if (inited)    {      thread_printf ("Close Resource Locks %p ", &lock);      DeleteCriticalSection (&lock);      inited = false;    }}voidMTinterface::Init (int forked){  reents._clib = _impure_ptr;  reents._winsup = &winsup_reent;  winsup_reent._process_logmask = LOG_UPTO (LOG_DEBUG);  if (!forked)    reent_key.set (&reents);  pthread_mutex::initMutex ();}voidMTinterface::fixup_before_fork (void){  pthread_key::fixup_before_fork ();}/* This function is called from a single threaded process */voidMTinterface::fixup_after_fork (void){  pthread_key::fixup_after_fork ();  pthread_mutex *mutex = mutexs;  debug_printf ("mutexs is %x",mutexs);  while (mutex)    {      mutex->fixup_after_fork ();      mutex = mutex->next;    }  pthread_cond *cond = conds;  debug_printf ("conds is %x",conds);  while (cond)    {      cond->fixup_after_fork ();      cond = cond->next;    }  semaphore *sem = semaphores;  debug_printf ("semaphores is %x",semaphores);  while (sem)    {      sem->fixup_after_fork ();      sem = sem->next;    }  pthread::initMainThread (true);  threadcount = 1;}/* pthread calls *//* static methods */voidpthread::initMainThread (bool do_init){  if (!do_init)    return;  pthread *thread = getTlsSelfPointer ();  if (!thread)    {      thread = new pthread ();      if (!thread)        api_fatal ("failed to create mainthread object");    }  thread->initCurrentThread ();}pthread *pthread::self (){  pthread *thread = getTlsSelfPointer ();  if (thread)    return thread;  return pthreadNull::getNullpthread ();}voidpthread::setTlsSelfPointer (pthread *thisThread){  MT_INTERFACE->thread_self_key.set (thisThread);}pthread *pthread::getTlsSelfPointer (){  return (pthread *) MT_INTERFACE->thread_self_key.get ();}/* member methods */pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),		    cancelstate (0), canceltype (0), cancel_event (0),		    joiner (NULL), cleanup_stack (NULL){}pthread::~pthread (){  if (win32_obj_id)    CloseHandle (win32_obj_id);  if (cancel_event)    CloseHandle (cancel_event);}voidpthread::setThreadIdtoCurrent (){  thread_id = GetCurrentThreadId ();}voidpthread::precreate (pthread_attr *newattr){  pthread_mutex *verifyable_mutex_obj = &mutex;  /* already running ? */  if (win32_obj_id)    return;  if (newattr)    {      attr.joinable = newattr->joinable;      attr.contentionscope = newattr->contentionscope;      attr.inheritsched = newattr->inheritsched;      attr.stacksize = newattr->stacksize;    }  if (!pthread_mutex::isGoodObject (&verifyable_mutex_obj))    {      thread_printf ("New thread object access mutex is not valid. this %p",		     this);      magic = 0;      return;    }  cancel_event = ::CreateEvent (&sec_none_nih, TRUE, FALSE, NULL);  if (!cancel_event)    {      system_printf ("couldn't create cancel event, this %p LastError %E", this);      /* we need the event for correct behaviour */      magic = 0;      return;    }}voidpthread::create (void *(*func) (void *), pthread_attr *newattr,		 void *threadarg){  precreate (newattr);  if (!magic)      return;   function = func;   arg = threadarg;  win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,				(LPTHREAD_START_ROUTINE) thread_init_wrapper,				this, CREATE_SUSPENDED, &thread_id);  if (!win32_obj_id)    {      thread_printf ("CreateThread failed: this %p LastError %E", this);      magic = 0;    }  else {      postcreate ();      ResumeThread (win32_obj_id);  }}voidpthread::postcreate (){    InterlockedIncrement (&MT_INTERFACE->threadcount);    /* FIXME: set the priority appropriately for system contention scope */    if (attr.inheritsched == PTHREAD_EXPLICIT_SCHED)      {	/* FIXME: set the scheduling settings for the new thread */	/* sched_thread_setparam (win32_obj_id, attr.schedparam); */      }}voidpthread::exit (void *value_ptr){  class pthread *thread = this;  // run cleanup handlers  pop_all_cleanup_handlers ();  pthread_key::runAllDestructors ();  mutex.Lock ();  // cleanup if thread is in detached state and not joined  if (__pthread_equal (&joiner, &thread))    delete this;  else    {      return_ptr = value_ptr;      mutex.UnLock ();    }  if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)    ::exit (0);  else    ExitThread (0);}intpthread::cancel (void){  class pthread *thread = this;  class pthread *self = pthread::self ();  mutex.Lock ();  if (canceltype == PTHREAD_CANCEL_DEFERRED ||      cancelstate == PTHREAD_CANCEL_DISABLE)    {      // cancel deferred      mutex.UnLock ();      SetEvent (cancel_event);      return 0;    }  else if (__pthread_equal (&thread, &self))    {      mutex.UnLock ();      cancel_self ();      return 0; // Never reached    }  // cancel asynchronous  SuspendThread (win32_obj_id);  if (WaitForSingleObject (win32_obj_id, 0) == WAIT_TIMEOUT)    {      CONTEXT context;      context.ContextFlags = CONTEXT_CONTROL;      GetThreadContext (win32_obj_id, &context);      context.Eip = (DWORD) pthread::static_cancel_self;      SetThreadContext (win32_obj_id, &context);    }  mutex.UnLock ();  ResumeThread (win32_obj_id);  return 0;/*  TODO: insert  pthread_testcancel into the required functions  the required function list is: *indicates done, X indicates not present in cygwin.aio_suspend ()*close ()*creat ()fcntl ()fsync ()getmsg ()getpmsg ()lockf ()mq_receive ()mq_send ()msgrcv ()msgsnd ()msync ()nanosleep ()open ()pause ()poll ()pread ()pthread_cond_timedwait ()pthread_cond_wait ()*pthread_join ()pthread_testcancel ()putmsg ()putpmsg ()pwrite ()read ()readv ()select ()sem_wait ()sigpause ()sigsuspend ()sigtimedwait ()sigwait ()sigwaitinfo ()*sleep ()system ()tcdrain ()*usleep ()wait ()wait3()waitid ()waitpid ()write ()writev ()the optional list is:catclose ()catgets ()catopen ()closedir ()closelog ()ctermid ()dbm_close ()dbm_delete ()dbm_fetch ()dbm_nextkey ()dbm_open ()dbm_store ()dlclose ()dlopen ()endgrent ()endpwent ()endutxent ()fclose ()fcntl ()fflush ()fgetc ()fgetpos ()fgets ()fgetwc ()fgetws ()fopen ()fprintf ()fputc ()fputs ()fputwc ()fputws ()fread ()freopen ()fscanf ()fseek ()fseeko ()fsetpos ()ftell ()ftello ()ftw ()fwprintf ()fwrite ()fwscanf ()getc ()getc_unlocked ()getchar ()getchar_unlocked ()getcwd ()getdate ()getgrent ()getgrgid ()getgrgid_r ()getgrnam ()getgrnam_r ()getlogin ()getlogin_r ()getpwent ()*getpwnam ()*getpwnam_r ()*getpwuid ()*getpwuid_r ()gets ()getutxent ()getutxid ()getutxline ()getw ()getwc ()getwchar ()getwd ()glob ()iconv_close ()iconv_open ()ioctl ()lseek ()mkstemp ()nftw ()opendir ()openlog ()pclose ()perror ()popen ()printf ()putc ()putc_unlocked ()putchar ()putchar_unlocked ()puts ()pututxline ()putw ()putwc ()putwchar ()readdir ()readdir_r ()remove ()rename ()rewind ()rewinddir ()scanf ()seekdir ()semop ()setgrent ()setpwent ()setutxent ()strerror ()syslog ()tmpfile ()tmpnam ()ttyname ()ttyname_r ()ungetc ()ungetwc ()unlink ()vfprintf ()vfwprintf ()vprintf ()vwprintf ()wprintf ()wscanf ()Note, that for fcntl (), for any value of the cmd argument.And we must not introduce cancellation points anywhere else that's part of the posix oropengroup specs. */}voidpthread::testcancel (void){  if (cancelstate == PTHREAD_CANCEL_DISABLE)    return;  if (WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0))    cancel_self ();}voidpthread::static_cancel_self (void){  pthread::self ()->cancel_self ();}intpthread::setcancelstate (int state, int *oldstate){  int result = 0;  mutex.Lock ();  if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)    result = EINVAL;  else    {      if (oldstate)	*oldstate = cancelstate;      cancelstate = state;    }  mutex.UnLock ();  return result;}intpthread::setcanceltype (int type, int *oldtype){  int result = 0;  mutex.Lock ();  if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)    result = EINVAL;  else    {      if (oldtype)	*oldtype = canceltype;      canceltype = type;    }  mutex.UnLock ();  return result;}voidpthread::push_cleanup_handler (__pthread_cleanup_handler *handler){  if (this != self ())    // TODO: do it?    api_fatal ("Attempt to push a cleanup handler across threads");  handler->next = cleanup_stack;  InterlockedExchangePointer (&cleanup_stack, handler);}voidpthread::pop_cleanup_handler (int const execute){  if (this != self ())    // TODO: send a signal or something to the thread ?    api_fatal ("Attempt to execute a cleanup handler across threads");  mutex.Lock ();

⌨️ 快捷键说明

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