From 22df4f5c42b3ac110f78fceed8d248900ea5419f Mon Sep 17 00:00:00 2001 From: rpj Date: Sat, 26 Mar 2011 00:19:09 +0000 Subject: New interface (not part of robust mutexes) --- ChangeLog | 9 +++ GNUmakefile | 2 + Makefile | 2 + global.c | 5 ++ implement.h | 2 + nonportable.c | 1 + pthread.h | 1 + pthread_getsequence_np.c | 47 +++++++++++++++ pthread_mutex_consistent.c | 17 +++++- ptw32_new.c | 1 + tests/Bmakefile | 13 +++-- tests/ChangeLog | 4 ++ tests/GNUmakefile | 15 ++--- tests/Makefile | 15 ++--- tests/Wmakefile | 13 +++-- tests/sequence1.c | 142 +++++++++++++++++++++++++++++++++++++++++++++ 16 files changed, 260 insertions(+), 29 deletions(-) create mode 100755 pthread_getsequence_np.c create mode 100755 tests/sequence1.c diff --git a/ChangeLog b/ChangeLog index 7ea66ae..d143ea2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2011-03-26 Ross Johnson + + * pthread_getsequence_np.c: New non-POSIX interface for compatibility + with some other implementations; returns a 64 bit sequence number + that is unique to each thread in the process. + * pthread.h (pthread_getsequence_np): Added. + * global.c: Add global sequence counter for above. + * implement.h: Likewise. + 2011-03-25 Ross Johnson * (cancelLock): Convert to an MCS lock and rename to stateLock. diff --git a/GNUmakefile b/GNUmakefile index 40fd538..3491efd 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -194,6 +194,7 @@ SMALL_STATIC_OBJS = \ pthread_mutexattr_setkind_np.o \ pthread_mutexattr_getkind_np.o \ pthread_getw32threadhandle_np.o \ + pthread_getsequence_np.o \ pthread_delay_np.o \ pthread_num_processors_np.o \ pthread_win32_attach_detach_np.o \ @@ -353,6 +354,7 @@ NONPORTABLE_SRCS = \ pthread_mutexattr_setkind_np.c \ pthread_mutexattr_getkind_np.c \ pthread_getw32threadhandle_np.c \ + pthread_getsequence_np.c \ pthread_delay_np.c \ pthread_num_processors_np.c \ pthread_win32_attach_detach_np.c \ diff --git a/Makefile b/Makefile index 23ef981..f7c6dc3 100644 --- a/Makefile +++ b/Makefile @@ -140,6 +140,7 @@ SMALL_STATIC_OBJS = \ pthread_mutexattr_setkind_np.obj \ pthread_mutexattr_getkind_np.obj \ pthread_getw32threadhandle_np.obj \ + pthread_getsequence_np.obj \ pthread_delay_np.obj \ pthread_num_processors_np.obj \ pthread_win32_attach_detach_np.obj \ @@ -295,6 +296,7 @@ NONPORTABLE_SRCS = \ pthread_mutexattr_setkind_np.c \ pthread_mutexattr_getkind_np.c \ pthread_getw32threadhandle_np.c \ + pthread_getsequence_np.c \ pthread_delay_np.c \ pthread_num_processors_np.c \ pthread_win32_attach_detach_np.c \ diff --git a/global.c b/global.c index be6d027..874b71b 100644 --- a/global.c +++ b/global.c @@ -52,6 +52,11 @@ int ptw32_concurrency = 0; /* What features have been auto-detected */ int ptw32_features = 0; +/* + * Global [process wide] thread sequence Number + */ +unsigned long long ptw32_threadSeqNumber = 0; + /* * Function pointer to QueueUserAPCEx if it exists, otherwise * it will be set at runtime to a substitute routine which cannot unblock diff --git a/implement.h b/implement.h index b4c80b3..8a27fae 100644 --- a/implement.h +++ b/implement.h @@ -561,6 +561,8 @@ extern pthread_cond_t ptw32_cond_list_tail; extern int ptw32_mutex_default_kind; +extern unsigned long long ptw32_threadSeqNumber; + extern int ptw32_concurrency; extern int ptw32_features; diff --git a/nonportable.c b/nonportable.c index 6c2a990..82c558b 100644 --- a/nonportable.c +++ b/nonportable.c @@ -40,6 +40,7 @@ #include "pthread_mutexattr_setkind_np.c" #include "pthread_mutexattr_getkind_np.c" #include "pthread_getw32threadhandle_np.c" +#include "pthread_getsequence_np.c" #include "pthread_delay_np.c" #include "pthread_num_processors_np.c" #include "pthread_win32_attach_detach_np.c" diff --git a/pthread.h b/pthread.h index 0c0aeb8..a3506b6 100644 --- a/pthread.h +++ b/pthread.h @@ -1176,6 +1176,7 @@ PTW32_DLLPORT int PTW32_CDECL pthread_mutexattr_getkind_np(pthread_mutexattr_t * */ PTW32_DLLPORT int PTW32_CDECL pthread_delay_np (struct timespec * interval); PTW32_DLLPORT int PTW32_CDECL pthread_num_processors_np(void); +PTW32_DLLPORT unsigned long long PTW32_CDECL pthread_getsequence_np(pthread_t thread); /* * Useful if an application wants to statically link diff --git a/pthread_getsequence_np.c b/pthread_getsequence_np.c new file mode 100755 index 0000000..0e643e9 --- /dev/null +++ b/pthread_getsequence_np.c @@ -0,0 +1,47 @@ +/* + * pthread_getsequence_np.c + * + * Description: + * This translation unit implements non-portable thread functions. + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + */ + +#include "pthread.h" +#include "implement.h" + +/* + * + */ +unsigned long long +pthread_getsequence_np (pthread_t thread) +{ + return ((ptw32_thread_t*)thread.p)->seqNumber; +} diff --git a/pthread_mutex_consistent.c b/pthread_mutex_consistent.c index 5ceab0c..08572a5 100755 --- a/pthread_mutex_consistent.c +++ b/pthread_mutex_consistent.c @@ -83,7 +83,7 @@ ptw32_robust_mutex_inherit(pthread_mutex_t * mutex) switch (PTW32_INTERLOCKED_COMPARE_EXCHANGE( (LPLONG)&robust->stateInconsistent, (LONG)PTW32_ROBUST_INCONSISTENT, - -1L /* Terminating thread sets this */)) + -1L /* The terminating thread sets this */)) { case -1L: result = EOWNERDEAD; @@ -99,6 +99,18 @@ ptw32_robust_mutex_inherit(pthread_mutex_t * mutex) return result; } +/* + * The next two internal support functions depend on only being + * called by the thread that owns the robust mutex. This enables + * us to avoid additional locks. + * Any mutex currently in the thread's robust mutex list is held + * by the thread, again eliminating the need for locks. + * The forward/backward links allow the thread to unlock mutexes + * in any order, not necessarily the reverse locking order. + * This is all possible because it is an error if a thread that + * does not own the [robust] mutex attempts to unlock it. + */ + INLINE void ptw32_robust_mutex_add(pthread_mutex_t* mutex, pthread_t self) @@ -131,10 +143,9 @@ ptw32_robust_mutex_remove(pthread_mutex_t* mutex, ptw32_thread_t* otp) { ptw32_robust_node_t** list; pthread_mutex_t mx = *mutex; - ptw32_thread_t* tp = mx->ownerThread.p; ptw32_robust_node_t* robust = mx->robustNode; - list = &tp->robustMxList; + list = &(((ptw32_thread_t*)mx->ownerThread.p)->robustMxList); mx->ownerThread.p = otp; if (robust->next != NULL) { diff --git a/ptw32_new.c b/ptw32_new.c index 881c6ac..ac836ea 100644 --- a/ptw32_new.c +++ b/ptw32_new.c @@ -70,6 +70,7 @@ ptw32_new (void) } /* Set default state. */ + tp->seqNumber = ++ptw32_threadSeqNumber; tp->sched_priority = THREAD_PRIORITY_NORMAL; tp->detachState = PTHREAD_CREATE_JOINABLE; tp->cancelState = PTHREAD_CANCEL_ENABLE; diff --git a/tests/Bmakefile b/tests/Bmakefile index 263d127..bd8d7b7 100644 --- a/tests/Bmakefile +++ b/tests/Bmakefile @@ -85,7 +85,7 @@ PASSES= loadfree.pass \ mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass \ condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \ exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass \ - kill1.pass valid1.pass valid2.pass \ + sequence1.pass kill1.pass valid1.pass valid2.pass \ exit2.pass exit3.pass exit4.pass exit5.pass \ join0.pass join1.pass detach1.pass join2.pass join3.pass \ mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass \ @@ -311,11 +311,6 @@ mutex8.pass: mutex7.pass mutex8n.pass: mutex7n.pass mutex8e.pass: mutex7e.pass mutex8r.pass: mutex7r.pass -robust1.pass: mutex8r.pass -robust2.pass: mutex8r.pass -robust3.pass: robust2.pass -robust4.pass: robust3.pass -robust5.pass: robust4.pass once1.pass: create1.pass once2.pass: once1.pass once3.pass: once2.pass @@ -324,6 +319,11 @@ priority1.pass: join1.pass priority2.pass: priority1.pass barrier3.pass reuse1.pass: create2.pass reuse2.pass: reuse1.pass +robust1.pass: mutex8r.pass +robust2.pass: mutex8r.pass +robust3.pass: robust2.pass +robust4.pass: robust3.pass +robust5.pass: robust4.pass rwlock1.pass: condvar6.pass rwlock2.pass: rwlock1.pass rwlock3.pass: rwlock2.pass @@ -346,6 +346,7 @@ semaphore3.pass: semaphore2.pass semaphore4.pass: semaphore3.pass cancel1.pass semaphore4t.pass: semaphore4.pass semaphore5.pass: semaphore4.pass +sequence1.pass: reuse2.pass sizes.pass: spin1.pass: spin2.pass: spin1.pass diff --git a/tests/ChangeLog b/tests/ChangeLog index 8d7604f..47b8253 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +2011-03-26 Ross Johnson + + * sequence1.c: New test for new pthread_getsequence_np(). + 2011-03-24 Ross Johnson * mutex*.c: Include tests for robust mutexes wherever diff --git a/tests/GNUmakefile b/tests/GNUmakefile index 98342cc..9a46b2c 100644 --- a/tests/GNUmakefile +++ b/tests/GNUmakefile @@ -92,7 +92,7 @@ TESTS = \ semaphore1 semaphore2 semaphore3 \ condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 \ create1 create2 reuse1 reuse2 equal1 \ - kill1 valid1 valid2 \ + sequence1 kill1 valid1 valid2 \ exit2 exit3 exit4 exit5 \ join0 join1 detach1 join2 join3 \ mutex2 mutex2r mutex2e mutex3 mutex3r mutex3e \ @@ -131,7 +131,7 @@ STATICTESTS = \ semaphore1 semaphore2 semaphore3 \ condvar1 condvar1_1 condvar1_2 condvar2 condvar2_1 exit1 \ create1 create2 reuse1 reuse2 equal1 \ - kill1 valid1 valid2 \ + sequence1 kill1 valid1 valid2 \ exit2 exit3 exit4 exit5 \ join0 join1 detach1 join2 join3 \ mutex2 mutex2r mutex2e mutex3 mutex3r mutex3e \ @@ -329,11 +329,6 @@ mutex8.pass: mutex7.pass mutex8n.pass: mutex7n.pass mutex8e.pass: mutex7e.pass mutex8r.pass: mutex7r.pass -robust1.pass: mutex8r.pass -robust2.pass: mutex8r.pass -robust3.pass: robust2.pass -robust4.pass: robust3.pass -robust5.pass: robust4.pass once1.pass: create1.pass once2.pass: once1.pass once3.pass: once2.pass @@ -343,6 +338,11 @@ priority1.pass: join1.pass priority2.pass: priority1.pass barrier3.pass reuse1.pass: create2.pass reuse2.pass: reuse1.pass +robust1.pass: mutex8r.pass +robust2.pass: mutex8r.pass +robust3.pass: robust2.pass +robust4.pass: robust3.pass +robust5.pass: robust4.pass rwlock1.pass: condvar6.pass rwlock2.pass: rwlock1.pass rwlock3.pass: rwlock2.pass @@ -365,6 +365,7 @@ semaphore3.pass: semaphore2.pass semaphore4.pass: semaphore3.pass cancel1.pass semaphore4t.pass: semaphore4.pass semaphore5.pass: semaphore4.pass +sequence1.pass: reuse2.pass sizes.pass: spin1.pass: spin2.pass: spin1.pass diff --git a/tests/Makefile b/tests/Makefile index 5439ee1..4164e1e 100644 --- a/tests/Makefile +++ b/tests/Makefile @@ -89,7 +89,7 @@ PASSES= sizes.pass loadfree.pass \ mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass \ condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \ exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass \ - kill1.pass valid1.pass valid2.pass \ + sequence1.pass kill1.pass valid1.pass valid2.pass \ exit2.pass exit3.pass exit4.pass exit5.pass \ join0.pass join1.pass detach1.pass join2.pass join3.pass \ mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass \ @@ -135,7 +135,7 @@ STATICRESULTS = \ mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass \ condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass \ exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass \ - kill1.pass valid1.pass valid2.pass \ + sequence1.pass kill1.pass valid1.pass valid2.pass \ exit2.pass exit3.pass exit4.pass exit5.pass \ join0.pass join1.pass detach1.pass join2.pass join3.pass \ mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass \ @@ -400,11 +400,6 @@ mutex8.pass: mutex7.pass mutex8n.pass: mutex7n.pass mutex8e.pass: mutex7e.pass mutex8r.pass: mutex7r.pass -robust1.pass: mutex8r.pass -robust2.pass: mutex8r.pass -robust3.pass: robust2.pass -robust4.pass: robust3.pass -robust5.pass: robust4.pass once1.pass: create1.pass once2.pass: once1.pass once3.pass: once2.pass @@ -413,6 +408,11 @@ priority1.pass: join1.pass priority2.pass: priority1.pass barrier3.pass reuse1.pass: create2.pass reuse2.pass: reuse1.pass +robust1.pass: mutex8r.pass +robust2.pass: mutex8r.pass +robust3.pass: robust2.pass +robust4.pass: robust3.pass +robust5.pass: robust4.pass rwlock1.pass: condvar6.pass rwlock2.pass: rwlock1.pass rwlock3.pass: rwlock2.pass @@ -435,6 +435,7 @@ semaphore3.pass: semaphore2.pass semaphore4.pass: semaphore3.pass cancel1.pass semaphore4t.pass: semaphore4.pass semaphore5.pass: semaphore4.pass +sequence1.pass: reuse2.pass sizes.pass: spin1.pass: spin2.pass: spin1.pass diff --git a/tests/Wmakefile b/tests/Wmakefile index c7e97fb..0fcbd43 100644 --- a/tests/Wmakefile +++ b/tests/Wmakefile @@ -87,7 +87,7 @@ PASSES = sizes.pass loadfree.pass & mutex2r.pass mutex2e.pass mutex3r.pass mutex3e.pass & condvar1.pass condvar1_1.pass condvar1_2.pass condvar2.pass condvar2_1.pass & exit1.pass create1.pass create2.pass reuse1.pass reuse2.pass equal1.pass & - kill1.pass valid1.pass valid2.pass & + sequence1.pass kill1.pass valid1.pass valid2.pass & exit2.pass exit3.pass exit4 exit5 & join0.pass join1.pass detach1.pass join2.pass join3.pass & mutex4.pass mutex6.pass mutex6n.pass mutex6e.pass mutex6r.pass & @@ -309,11 +309,6 @@ mutex8.pass: mutex7.pass mutex8n.pass: mutex7n.pass mutex8e.pass: mutex7e.pass mutex8r.pass: mutex7r.pass -robust1.pass: mutex8r.pass -robust2.pass: mutex8r.pass -robust3.pass: robust2.pass -robust4.pass: robust3.pass -robust5.pass: robust4.pass once1.pass: create1.pass once2.pass: once1.pass once3.pass: once2.pass @@ -322,6 +317,11 @@ priority1.pass: join1.pass priority2.pass: priority1.pass barrier3.pass reuse1.pass: create2.pass reuse2.pass: reuse1.pass +robust1.pass: mutex8r.pass +robust2.pass: mutex8r.pass +robust3.pass: robust2.pass +robust4.pass: robust3.pass +robust5.pass: robust4.pass rwlock1.pass: condvar6.pass rwlock2.pass: rwlock1.pass rwlock3.pass: rwlock2.pass @@ -343,6 +343,7 @@ semaphore3.pass: semaphore2.pass semaphore4.pass: semaphore3.pass cancel1.pass semaphore4t.pass: semaphore4.pass semaphore5.pass: semaphore4.pass +sequence1.pass: reuse2.pass sizes.pass: spin1.pass: spin2.pass: spin1.pass diff --git a/tests/sequence1.c b/tests/sequence1.c new file mode 100755 index 0000000..d7c6e0b --- /dev/null +++ b/tests/sequence1.c @@ -0,0 +1,142 @@ +/* + * File: sequence1.c + * + * + * -------------------------------------------------------------------------- + * + * Pthreads-win32 - POSIX Threads Library for Win32 + * Copyright(C) 1998 John E. Bossom + * Copyright(C) 1999,2005 Pthreads-win32 contributors + * + * Contact Email: rpj@callisto.canberra.edu.au + * + * The current list of contributors is contained + * in the file CONTRIBUTORS included with the source + * code distribution. The list can also be seen at the + * following World Wide Web location: + * http://sources.redhat.com/pthreads-win32/contributors.html + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library in the file COPYING.LIB; + * if not, write to the Free Software Foundation, Inc., + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA + * + * -------------------------------------------------------------------------- + * + * Test Synopsis: + * - that unique thread sequence numbers are generated. + * - Analyse thread struct reuse. + * + * Test Method (Validation or Falsification): + * - + * + * Requirements Tested: + * - + * + * Features Tested: + * - + * + * Cases Tested: + * - + * + * Description: + * - + * + * Environment: + * - This test is implementation specific + * because it uses knowledge of internals that should be + * opaque to an application. + * + * Input: + * - None. + * + * Output: + * - File name, Line number, and failed expression on failure. + * - analysis output on success. + * + * Assumptions: + * - + * + * Pass Criteria: + * - unique sequence numbers are generated for every new thread. + * + * Fail Criteria: + * - + */ + +#include "test.h" + +/* + */ + +enum { + NUMTHREADS = 10000 +}; + + +static long done = 0; +/* + * seqmap should have 1 in every element except [0] + * Thread sequence numbers start at 1 and we will also + * include this main thread so we need NUMTHREADS+2 + * elements. + */ +static UINT64 seqmap[NUMTHREADS+2]; + +void * func(void * arg) +{ + sched_yield(); + seqmap[(int)pthread_getsequence_np(pthread_self())] = 1; + InterlockedIncrement(&done); + + return (void *) 0; +} + +int +main() +{ + pthread_t t[NUMTHREADS]; + pthread_attr_t attr; + int i; + + assert(pthread_attr_init(&attr) == 0); + assert(pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED) == 0); + + for (i = 0; i <= NUMTHREADS+2; i++) + { + seqmap[i] = 0; + } + + for (i = 0; i < NUMTHREADS; i++) + { + if (NUMTHREADS/2 == i) + { + /* Include this main thread, which will be an implicit pthread_t */ + seqmap[(int)pthread_getsequence_np(pthread_self())] = 1; + } + assert(pthread_create(&t[i], &attr, func, NULL) == 0); + } + + while (NUMTHREADS > InterlockedExchangeAdd((LPLONG)&done, 0L)) + Sleep(100); + + Sleep(100); + + assert(seqmap[0] == 0); + for (i = 1; i < NUMTHREADS+2; i++) + { + assert(seqmap[i] == 1); + } + + return 0; +} -- cgit v1.2.3