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>
|
||||
|
||||
* configure.in: Complain about lack of w32api directory.
|
||||
|
|
|
@ -42,7 +42,7 @@ extern "C"
|
|||
#define PTHREAD_CANCEL_ENABLE 0
|
||||
#define PTHREAD_CANCEL_DEFERRED 0
|
||||
#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 */
|
||||
#define PTHREAD_COND_INITIALIZER (void *)21
|
||||
#define PTHREAD_CREATE_DETACHED 1
|
||||
|
|
|
@ -140,7 +140,7 @@ pthread_attr_getstackaddr (const pthread_attr_t * attr, void **stackaddr)
|
|||
void
|
||||
pthread_exit (void *value_ptr)
|
||||
{
|
||||
return __pthread_exit (value_ptr);
|
||||
return pthread::self()->exit (value_ptr);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -428,25 +428,25 @@ pthread_cancel (pthread_t thread)
|
|||
int
|
||||
pthread_setcancelstate (int state, int *oldstate)
|
||||
{
|
||||
return __pthread_setcancelstate (state, oldstate);
|
||||
return pthread::self()->setcancelstate (state, oldstate);
|
||||
}
|
||||
|
||||
int
|
||||
pthread_setcanceltype (int type, int *oldtype)
|
||||
{
|
||||
return __pthread_setcanceltype (type, oldtype);
|
||||
return pthread::self()->setcanceltype (type, oldtype);
|
||||
}
|
||||
|
||||
void
|
||||
pthread_testcancel (void)
|
||||
{
|
||||
__pthread_testcancel ();
|
||||
pthread::self()->testcancel ();
|
||||
}
|
||||
|
||||
void
|
||||
_pthread_cleanup_push (__pthread_cleanup_handler *handler)
|
||||
{
|
||||
pthread::self()->push_cleanup_handler(handler);
|
||||
pthread::self()->push_cleanup_handler (handler);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -355,7 +355,8 @@ pthread::self ()
|
|||
|
||||
/* member methods */
|
||||
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)
|
||||
CloseHandle (win32_obj_id);
|
||||
if (cancel_event)
|
||||
CloseHandle (cancel_event);
|
||||
}
|
||||
|
||||
|
||||
|
@ -394,6 +397,15 @@ pthread::create (void *(*func) (void *), pthread_attr *newattr,
|
|||
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,
|
||||
(LPTHREAD_START_ROUTINE) thread_init_wrapper,
|
||||
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
|
||||
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 ?
|
||||
api_fatal ("Attempt to execute a cleanup handler across threads");
|
||||
|
||||
mutex.Lock ();
|
||||
|
||||
if (cleanup_stack != NULL)
|
||||
{
|
||||
__pthread_cleanup_handler *handler = cleanup_stack;
|
||||
|
@ -441,6 +753,8 @@ pthread::pop_cleanup_handler (int const execute)
|
|||
(*handler->function) (handler->arg);
|
||||
cleanup_stack = handler->next;
|
||||
}
|
||||
|
||||
mutex.UnLock ();
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -967,11 +1281,11 @@ pthread::thread_init_wrapper (void *_arg)
|
|||
/*the OS doesn't check this for <= 64 Tls entries (pre win2k) */
|
||||
TlsSetValue (MT_INTERFACE->thread_self_dwTlsIndex, thread);
|
||||
|
||||
thread->mutex.Lock();
|
||||
thread->mutex.Lock ();
|
||||
// if thread is detached force cleanup on exit
|
||||
if (thread->attr.joinable == PTHREAD_CREATE_DETACHED && thread->joiner == NULL)
|
||||
thread->joiner = pthread::self ();
|
||||
thread->mutex.UnLock();
|
||||
thread->mutex.UnLock ();
|
||||
|
||||
#ifdef _CYG_THREAD_FAILSAFE
|
||||
if (_REENT == _impure_ptr)
|
||||
|
@ -984,7 +1298,7 @@ pthread::thread_init_wrapper (void *_arg)
|
|||
// call the user's thread
|
||||
void *ret = thread->function (thread->arg);
|
||||
|
||||
__pthread_exit (ret);
|
||||
thread->exit (ret);
|
||||
|
||||
#if 0
|
||||
// ??? 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;
|
||||
}
|
||||
|
||||
/*Cancelability states */
|
||||
|
||||
|
||||
/*Perform the actual cancel */
|
||||
void
|
||||
__pthread_cleanup (pthread_t thread)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
__pthread_cancel (pthread_t thread)
|
||||
{
|
||||
if (verifyable_object_isvalid (&thread, PTHREAD_MAGIC) != VALID_OBJECT)
|
||||
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;
|
||||
/*
|
||||
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*/
|
||||
return thread->cancel ();
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -1556,32 +1632,6 @@ __pthread_attr_destroy (pthread_attr_t *attr)
|
|||
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
|
||||
__pthread_join (pthread_t *thread, void **return_val)
|
||||
{
|
||||
|
|
|
@ -266,6 +266,7 @@ public:
|
|||
void *return_ptr;
|
||||
bool suspended;
|
||||
int cancelstate, canceltype;
|
||||
HANDLE cancel_event;
|
||||
pthread_t joiner;
|
||||
// int joinable;
|
||||
|
||||
|
@ -287,6 +288,19 @@ public:
|
|||
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 pop_cleanup_handler (int const execute);
|
||||
|
||||
|
@ -298,7 +312,6 @@ private:
|
|||
__pthread_cleanup_handler *cleanup_stack;
|
||||
pthread_mutex mutex;
|
||||
|
||||
friend void __pthread_exit (void *value_ptr);
|
||||
friend int __pthread_join (pthread_t * thread, void **return_val);
|
||||
friend int __pthread_detach (pthread_t * thread);
|
||||
|
||||
|
@ -406,8 +419,10 @@ void __pthread_atforkprepare(void);
|
|||
void __pthread_atforkparent(void);
|
||||
void __pthread_atforkchild(void);
|
||||
|
||||
/* Cancellation */
|
||||
int __pthread_cancel (pthread_t thread);
|
||||
|
||||
/* Thread Exit */
|
||||
void __pthread_exit (void *value_ptr);
|
||||
int __pthread_join (pthread_t * thread, void **return_val);
|
||||
int __pthread_detach (pthread_t * thread);
|
||||
|
||||
|
@ -504,10 +519,6 @@ int __pthread_setschedparam (pthread_t thread, int policy,
|
|||
const struct sched_param *param);
|
||||
|
||||
/* 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 */
|
||||
int __sem_init (sem_t * sem, int pshared, unsigned int value);
|
||||
|
|
Loading…
Reference in New Issue