2002-06-25 Thomas Pfaff <tpfaff@gmx.net>
* include/pthread.h (PTHREAD_CANCELED): Defined a reasonable value. * pthread.cc (pthread_exit): Call method instead of function. (pthread_setcancelstate): Ditto. (pthread_setcanceltype): Ditto. (pthread_testcancel): Ditto. * thread.h (pthread::cancel_event): New member. (__pthread_cancel_self): New prototype. (pthread::exit): New Method. (pthread::cancel): Ditto. (pthread::testcancel): Ditto. (pthread::cancel_self): Ditto. (pthread::static_cancel_self): Ditto. (pthread::setcancelstate): Ditto. (pthread::setcanceltype): Ditto. (__pthread_cancel): Give c++ linkage. (__pthread_exit): Remove. (__pthread_setcancelstate): Ditto. (__pthread_setcanceltype): Ditto. (__pthread_testcancel): Ditto. * thread.cc (pthread::pthread): Inititialize cancel_event. (pthread::~pthread): Close cancel_event if needed. (pthread::create): Create cancel_event. (pthread::exit): New method. Replacement for __pthread_exit. (pthread::cancel): New method. (pthread::testcancel): Ditto. (pthread::static_cancel_self); New static method. (pthread::setcancelstate): New method. Replacement for __pthread_setcancelstate. (pthread::setcanceltype): New method. Replacement for __pthread_setcanceltype. (pthread::pop_cleanup_handler): Added lock for async cancel safe cancellation. (pthread::thread_init_wrapper): Change __pthread_exit to thread->exit(). (__pthread_cancel): Call method thread->cancel(). (__pthread_exit): Remove. (__pthread_setcancelstate): Ditto. (__pthread_setcanceltype): Ditto. (__pthread_testcancel): Ditto.
This commit is contained in:
parent
875beea460
commit
d288c1c78c
|
@ -1,3 +1,46 @@
|
||||||
|
2002-06-25 Thomas Pfaff <tpfaff@gmx.net>
|
||||||
|
|
||||||
|
* include/pthread.h (PTHREAD_CANCELED): Defined a reasonable
|
||||||
|
value.
|
||||||
|
* pthread.cc (pthread_exit): Call method instead of function.
|
||||||
|
(pthread_setcancelstate): Ditto.
|
||||||
|
(pthread_setcanceltype): Ditto.
|
||||||
|
(pthread_testcancel): Ditto.
|
||||||
|
* thread.h (pthread::cancel_event): New member.
|
||||||
|
(__pthread_cancel_self): New prototype.
|
||||||
|
(pthread::exit): New Method.
|
||||||
|
(pthread::cancel): Ditto.
|
||||||
|
(pthread::testcancel): Ditto.
|
||||||
|
(pthread::cancel_self): Ditto.
|
||||||
|
(pthread::static_cancel_self): Ditto.
|
||||||
|
(pthread::setcancelstate): Ditto.
|
||||||
|
(pthread::setcanceltype): Ditto.
|
||||||
|
(__pthread_cancel): Give c++ linkage.
|
||||||
|
(__pthread_exit): Remove.
|
||||||
|
(__pthread_setcancelstate): Ditto.
|
||||||
|
(__pthread_setcanceltype): Ditto.
|
||||||
|
(__pthread_testcancel): Ditto.
|
||||||
|
* thread.cc (pthread::pthread): Inititialize cancel_event.
|
||||||
|
(pthread::~pthread): Close cancel_event if needed.
|
||||||
|
(pthread::create): Create cancel_event.
|
||||||
|
(pthread::exit): New method. Replacement for __pthread_exit.
|
||||||
|
(pthread::cancel): New method.
|
||||||
|
(pthread::testcancel): Ditto.
|
||||||
|
(pthread::static_cancel_self); New static method.
|
||||||
|
(pthread::setcancelstate): New method. Replacement for
|
||||||
|
__pthread_setcancelstate.
|
||||||
|
(pthread::setcanceltype): New method. Replacement for
|
||||||
|
__pthread_setcanceltype.
|
||||||
|
(pthread::pop_cleanup_handler): Added lock for async cancel safe
|
||||||
|
cancellation.
|
||||||
|
(pthread::thread_init_wrapper): Change __pthread_exit to
|
||||||
|
thread->exit().
|
||||||
|
(__pthread_cancel): Call method thread->cancel().
|
||||||
|
(__pthread_exit): Remove.
|
||||||
|
(__pthread_setcancelstate): Ditto.
|
||||||
|
(__pthread_setcanceltype): Ditto.
|
||||||
|
(__pthread_testcancel): Ditto.
|
||||||
|
|
||||||
2002-06-02 Christopher Faylor <cgf@redhat.com>
|
2002-06-02 Christopher Faylor <cgf@redhat.com>
|
||||||
|
|
||||||
* configure.in: Complain about lack of w32api directory.
|
* configure.in: Complain about lack of w32api directory.
|
||||||
|
|
|
@ -42,7 +42,7 @@ extern "C"
|
||||||
#define PTHREAD_CANCEL_ENABLE 0
|
#define PTHREAD_CANCEL_ENABLE 0
|
||||||
#define PTHREAD_CANCEL_DEFERRED 0
|
#define PTHREAD_CANCEL_DEFERRED 0
|
||||||
#define PTHREAD_CANCEL_DISABLE 1
|
#define PTHREAD_CANCEL_DISABLE 1
|
||||||
#define PTHREAD_CANCELED
|
#define PTHREAD_CANCELED ((void *)-1)
|
||||||
/* this should be a value that can never be a valid address */
|
/* this should be a value that can never be a valid address */
|
||||||
#define PTHREAD_COND_INITIALIZER (void *)21
|
#define PTHREAD_COND_INITIALIZER (void *)21
|
||||||
#define PTHREAD_CREATE_DETACHED 1
|
#define PTHREAD_CREATE_DETACHED 1
|
||||||
|
|
|
@ -140,7 +140,7 @@ pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
|
||||||
void
|
void
|
||||||
pthread_exit (void *value_ptr)
|
pthread_exit (void *value_ptr)
|
||||||
{
|
{
|
||||||
return __pthread_exit (value_ptr);
|
return pthread::self()->exit (value_ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -428,25 +428,25 @@ pthread_cancel (pthread_t thread)
|
||||||
int
|
int
|
||||||
pthread_setcancelstate (int state, int *oldstate)
|
pthread_setcancelstate (int state, int *oldstate)
|
||||||
{
|
{
|
||||||
return __pthread_setcancelstate (state, oldstate);
|
return pthread::self()->setcancelstate (state, oldstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
pthread_setcanceltype (int type, int *oldtype)
|
pthread_setcanceltype (int type, int *oldtype)
|
||||||
{
|
{
|
||||||
return __pthread_setcanceltype (type, oldtype);
|
return pthread::self()->setcanceltype (type, oldtype);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread_testcancel (void)
|
pthread_testcancel (void)
|
||||||
{
|
{
|
||||||
__pthread_testcancel ();
|
pthread::self()->testcancel ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_pthread_cleanup_push (__pthread_cleanup_handler *handler)
|
_pthread_cleanup_push (__pthread_cleanup_handler *handler)
|
||||||
{
|
{
|
||||||
pthread::self()->push_cleanup_handler(handler);
|
pthread::self()->push_cleanup_handler (handler);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
|
@ -355,7 +355,8 @@ pthread::self ()
|
||||||
|
|
||||||
/* member methods */
|
/* member methods */
|
||||||
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
|
pthread::pthread ():verifyable_object (PTHREAD_MAGIC), win32_obj_id (0),
|
||||||
cancelstate (0), canceltype (0), joiner (NULL), cleanup_stack(NULL)
|
cancelstate (0), canceltype (0), cancel_event(0),
|
||||||
|
joiner (NULL), cleanup_stack(NULL)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -363,6 +364,8 @@ pthread::~pthread ()
|
||||||
{
|
{
|
||||||
if (win32_obj_id)
|
if (win32_obj_id)
|
||||||
CloseHandle (win32_obj_id);
|
CloseHandle (win32_obj_id);
|
||||||
|
if (cancel_event)
|
||||||
|
CloseHandle (cancel_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -394,6 +397,15 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cancel_event = ::CreateEvent (NULL,TRUE,FALSE,NULL);
|
||||||
|
if (!cancel_event)
|
||||||
|
{
|
||||||
|
system_printf ("couldn't create cancel event, this %p LastError %d", this, GetLastError () );
|
||||||
|
/*we need the event for correct behaviour */
|
||||||
|
magic = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
|
win32_obj_id = ::CreateThread (&sec_none_nih, attr.stacksize,
|
||||||
(LPTHREAD_START_ROUTINE) thread_init_wrapper,
|
(LPTHREAD_START_ROUTINE) thread_init_wrapper,
|
||||||
this, CREATE_SUSPENDED, &thread_id);
|
this, CREATE_SUSPENDED, &thread_id);
|
||||||
|
@ -416,6 +428,304 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread::exit (void *value_ptr)
|
||||||
|
{
|
||||||
|
class pthread *thread = this;
|
||||||
|
|
||||||
|
// run cleanup handlers
|
||||||
|
pop_all_cleanup_handlers ();
|
||||||
|
|
||||||
|
MT_INTERFACE->destructors.IterateNull ();
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread::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 or
|
||||||
|
opengroup specs.
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread::testcancel (void)
|
||||||
|
{
|
||||||
|
if (cancelstate == PTHREAD_CANCEL_DISABLE)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if( WAIT_OBJECT_0 == WaitForSingleObject (cancel_event, 0 ) )
|
||||||
|
cancel_self ();
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
pthread::static_cancel_self (void)
|
||||||
|
{
|
||||||
|
pthread::self()->cancel_self ();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread::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;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
pthread::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;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
|
pthread::push_cleanup_handler (__pthread_cleanup_handler *handler)
|
||||||
{
|
{
|
||||||
|
@ -433,6 +743,8 @@ pthread::pop_cleanup_handler (int const execute)
|
||||||
// TODO: send a signal or something to the thread ?
|
// TODO: send a signal or something to the thread ?
|
||||||
api_fatal ("Attempt to execute a cleanup handler across threads");
|
api_fatal ("Attempt to execute a cleanup handler across threads");
|
||||||
|
|
||||||
|
mutex.Lock ();
|
||||||
|
|
||||||
if (cleanup_stack != NULL)
|
if (cleanup_stack != NULL)
|
||||||
{
|
{
|
||||||
__pthread_cleanup_handler *handler = cleanup_stack;
|
__pthread_cleanup_handler *handler = cleanup_stack;
|
||||||
|
@ -441,6 +753,8 @@ pthread::pop_cleanup_handler (int const execute)
|
||||||
(*handler->function) (handler->arg);
|
(*handler->function) (handler->arg);
|
||||||
cleanup_stack = handler->next;
|
cleanup_stack = handler->next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mutex.UnLock ();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -967,11 +1281,11 @@ pthread::thread_init_wrapper (void *_arg)
|
||||||
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
|
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
|
||||||
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread);
|
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread);
|
||||||
|
|
||||||
thread->mutex.Lock();
|
thread->mutex.Lock ();
|
||||||
// if thread is detached force cleanup on exit
|
// if thread is detached force cleanup on exit
|
||||||
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
||||||
thread->joiner = pthread::self ();
|
thread->joiner = pthread::self ();
|
||||||
thread->mutex.UnLock();
|
thread->mutex.UnLock ();
|
||||||
|
|
||||||
#ifdef _CYG_THREAD_FAILSAFE
|
#ifdef _CYG_THREAD_FAILSAFE
|
||||||
if (_REENT == _impure_ptr)
|
if (_REENT == _impure_ptr)
|
||||||
|
@ -984,7 +1298,7 @@ pthread::thread_init_wrapper (void *_arg)
|
||||||
// call the user's thread
|
// call the user's thread
|
||||||
void *ret = thread->function (thread->arg);
|
void *ret = thread->function (thread->arg);
|
||||||
|
|
||||||
__pthread_exit (ret);
|
thread->exit (ret);
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
// ??? This code only runs if the thread exits by returning.
|
// ??? This code only runs if the thread exits by returning.
|
||||||
|
@ -1038,251 +1352,13 @@ __pthread_once (pthread_once_t *once_control, void (*init_routine) (void))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*Cancelability states */
|
|
||||||
|
|
||||||
|
|
||||||
/*Perform the actual cancel */
|
|
||||||
void
|
|
||||||
__pthread_cleanup (pthread_t thread)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int
|
int
|
||||||
__pthread_cancel (pthread_t thread)
|
__pthread_cancel (pthread_t thread)
|
||||||
{
|
{
|
||||||
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
|
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
|
||||||
return ESRCH;
|
return ESRCH;
|
||||||
if (thread->cancelstate == PTHREAD_CANCEL_ENABLE)
|
|
||||||
{
|
|
||||||
#if 0
|
|
||||||
/*once all the functions call testcancel (), we will do this */
|
|
||||||
if (thread->canceltype == PTHREAD_CANCEL_DEFERRED)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
/*possible FIXME: this function is meant to return asynchronously
|
|
||||||
*from the cancellation routine actually firing. So we may need some sort
|
|
||||||
*of signal to be sent that is immediately recieved and acted on.
|
|
||||||
*/
|
|
||||||
__pthread_cleanup (thread);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
/* return 0;
|
|
||||||
*/
|
|
||||||
|
|
||||||
return ESRCH;
|
return thread->cancel ();
|
||||||
/*
|
|
||||||
we return ESRCH until all the required functions call testcancel ();
|
|
||||||
this will give applications predictable behaviour.
|
|
||||||
|
|
||||||
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 or
|
|
||||||
opengroup specs.
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/*no races in these three functions: they are all current-thread-only */
|
|
||||||
int
|
|
||||||
__pthread_setcancelstate (int state, int *oldstate)
|
|
||||||
{
|
|
||||||
class pthread *thread = pthread::self ();
|
|
||||||
if (state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE)
|
|
||||||
return EINVAL;
|
|
||||||
*oldstate = thread->cancelstate;
|
|
||||||
thread->cancelstate = state;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
|
||||||
__pthread_setcanceltype (int type, int *oldtype)
|
|
||||||
{
|
|
||||||
class pthread *thread = pthread::self ();
|
|
||||||
if (type != PTHREAD_CANCEL_DEFERRED && type != PTHREAD_CANCEL_ASYNCHRONOUS)
|
|
||||||
return EINVAL;
|
|
||||||
*oldtype = thread->canceltype;
|
|
||||||
thread->canceltype = type;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*deferred cancellation request handler */
|
|
||||||
void
|
|
||||||
__pthread_testcancel (void)
|
|
||||||
{
|
|
||||||
class pthread *thread = pthread::self ();
|
|
||||||
if (thread->cancelstate == PTHREAD_CANCEL_DISABLE)
|
|
||||||
return;
|
|
||||||
/*check the cancellation event object here - not neededuntil pthread_cancel actually
|
|
||||||
*does something*/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -1556,32 +1632,6 @@ __pthread_attr_destroy (pthread_attr_t *attr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
__pthread_exit (void *value_ptr)
|
|
||||||
{
|
|
||||||
pthread * thread = pthread::self ();
|
|
||||||
|
|
||||||
// run cleanup handlers
|
|
||||||
thread->pop_all_cleanup_handlers ();
|
|
||||||
|
|
||||||
MT_INTERFACE->destructors.IterateNull ();
|
|
||||||
|
|
||||||
thread->mutex.Lock();
|
|
||||||
// cleanup if thread is in detached state and not joined
|
|
||||||
if( __pthread_equal(&thread->joiner, &thread ) )
|
|
||||||
delete thread;
|
|
||||||
else
|
|
||||||
{
|
|
||||||
thread->return_ptr = value_ptr;
|
|
||||||
thread->mutex.UnLock();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (InterlockedDecrement (&MT_INTERFACE->threadcount) == 0)
|
|
||||||
exit (0);
|
|
||||||
else
|
|
||||||
ExitThread (0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int
|
int
|
||||||
__pthread_join (pthread_t *thread, void **return_val)
|
__pthread_join (pthread_t *thread, void **return_val)
|
||||||
{
|
{
|
||||||
|
|
|
@ -266,6 +266,7 @@ public:
|
||||||
void *return_ptr;
|
void *return_ptr;
|
||||||
bool suspended;
|
bool suspended;
|
||||||
int cancelstate, canceltype;
|
int cancelstate, canceltype;
|
||||||
|
HANDLE cancel_event;
|
||||||
pthread_t joiner;
|
pthread_t joiner;
|
||||||
// int joinable;
|
// int joinable;
|
||||||
|
|
||||||
|
@ -287,6 +288,19 @@ public:
|
||||||
pthread ();
|
pthread ();
|
||||||
~pthread ();
|
~pthread ();
|
||||||
|
|
||||||
|
void exit (void *value_ptr);
|
||||||
|
|
||||||
|
int cancel ();
|
||||||
|
void testcancel ();
|
||||||
|
void cancel_self ()
|
||||||
|
{
|
||||||
|
exit (PTHREAD_CANCELED);
|
||||||
|
}
|
||||||
|
static void static_cancel_self ();
|
||||||
|
|
||||||
|
int setcancelstate (int state, int *oldstate);
|
||||||
|
int setcanceltype (int type, int *oldtype);
|
||||||
|
|
||||||
void push_cleanup_handler (__pthread_cleanup_handler *handler);
|
void push_cleanup_handler (__pthread_cleanup_handler *handler);
|
||||||
void pop_cleanup_handler (int const execute);
|
void pop_cleanup_handler (int const execute);
|
||||||
|
|
||||||
|
@ -298,7 +312,6 @@ private:
|
||||||
__pthread_cleanup_handler *cleanup_stack;
|
__pthread_cleanup_handler *cleanup_stack;
|
||||||
pthread_mutex mutex;
|
pthread_mutex mutex;
|
||||||
|
|
||||||
friend void __pthread_exit (void *value_ptr);
|
|
||||||
friend int __pthread_join (pthread_t * thread, void **return_val);
|
friend int __pthread_join (pthread_t * thread, void **return_val);
|
||||||
friend int __pthread_detach (pthread_t * thread);
|
friend int __pthread_detach (pthread_t * thread);
|
||||||
|
|
||||||
|
@ -406,8 +419,10 @@ void __pthread_atforkprepare(void);
|
||||||
void __pthread_atforkparent(void);
|
void __pthread_atforkparent(void);
|
||||||
void __pthread_atforkchild(void);
|
void __pthread_atforkchild(void);
|
||||||
|
|
||||||
|
/* Cancellation */
|
||||||
|
int __pthread_cancel (pthread_t thread);
|
||||||
|
|
||||||
/* Thread Exit */
|
/* Thread Exit */
|
||||||
void __pthread_exit (void *value_ptr);
|
|
||||||
int __pthread_join (pthread_t * thread, void **return_val);
|
int __pthread_join (pthread_t * thread, void **return_val);
|
||||||
int __pthread_detach (pthread_t * thread);
|
int __pthread_detach (pthread_t * thread);
|
||||||
|
|
||||||
|
@ -504,10 +519,6 @@ int __pthread_setschedparam (pthread_t thread, int policy,
|
||||||
const struct sched_param *param);
|
const struct sched_param *param);
|
||||||
|
|
||||||
/* cancelability states */
|
/* cancelability states */
|
||||||
int __pthread_cancel (pthread_t thread);
|
|
||||||
int __pthread_setcancelstate (int state, int *oldstate);
|
|
||||||
int __pthread_setcanceltype (int type, int *oldtype);
|
|
||||||
void __pthread_testcancel (void);
|
|
||||||
|
|
||||||
/* Semaphores */
|
/* Semaphores */
|
||||||
int __sem_init (sem_t * sem, int pshared, unsigned int value);
|
int __sem_init (sem_t * sem, int pshared, unsigned int value);
|
||||||
|
|
Loading…
Reference in New Issue