From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 983 invoked by alias); 7 Feb 2011 13:07:24 -0000 Received: (qmail 970 invoked by uid 22791); 7 Feb 2011 13:07:21 -0000 X-SWARE-Spam-Status: No, hits=1.8 required=5.0 tests=BAYES_50,SARE_MILLIONSOF,SPF_SOFTFAIL,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mtagate4.uk.ibm.com (HELO mtagate4.uk.ibm.com) (194.196.100.164) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Mon, 07 Feb 2011 13:07:14 +0000 Received: from d06nrmr1507.portsmouth.uk.ibm.com (d06nrmr1507.portsmouth.uk.ibm.com [9.149.38.233]) by mtagate4.uk.ibm.com (8.13.1/8.13.1) with ESMTP id p17D7Ar1027918 for ; Mon, 7 Feb 2011 13:07:10 GMT Received: from d06av12.portsmouth.uk.ibm.com (d06av12.portsmouth.uk.ibm.com [9.149.37.247]) by d06nrmr1507.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id p17D7DKC1749232 for ; Mon, 7 Feb 2011 13:07:13 GMT Received: from d06av12.portsmouth.uk.ibm.com (loopback [127.0.0.1]) by d06av12.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVout) with ESMTP id p17D7Ave016437 for ; Mon, 7 Feb 2011 06:07:10 -0700 Received: from d12ml072.megacenter.de.ibm.com (d12ml072.megacenter.de.ibm.com [9.149.166.115]) by d06av12.portsmouth.uk.ibm.com (8.14.4/8.13.1/NCO v10.0 AVin) with ESMTP id p17D79dR016434 for ; Mon, 7 Feb 2011 06:07:09 -0700 In-Reply-To: <4D4E6D82.2060607@homemail.com.au> Subject: Re: Compilation issue with pthreads-win32 To: Ross Johnson Cc: "pthreads-win32@sourceware.org" Message-ID: From: Alexander Terekhov Date: Mon, 07 Feb 2011 13:07:00 -0000 MIME-Version: 1.0 Content-type: text/plain; charset=US-ASCII X-IsSubscribed: yes Mailing-List: contact pthreads-win32-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: pthreads-win32-owner@sourceware.org X-SW-Source: 2011/txt/msg00006.txt.bz2 Ross Johnson wrote: > > Yes, you can role your own. There's an example of a usable compare > function here: > > http://sourceware.org/ml/pthreads-win32/2009/msg00023.html Raw bits of the pthread_t representation are not helpful because the same pthread_t value could have more than one representation (different values in raw bits). regards, alexander. Ross Johnson @sourceware.org on 06.02.2011 10:44:34 Sent by: pthreads-win32-owner@sourceware.org To: "pthreads-win32@sourceware.org" cc: Subject: Re: Compilation issue with pthreads-win32 Yes, you can role your own. There's an example of a usable compare function here: http://sourceware.org/ml/pthreads-win32/2009/msg00023.html But if you are comparing/sorting/hashing handles then, whatever you use to represent a thread, it will be much less problematic if it represents that thread and only that thread for the life of the process, i.e. even after the thread exits. On 6/02/2011 4:17 AM, Lubashev, Igor wrote: > Why is this an issue? > > If some code wants to have treads comperable/hashable, they can roll > their own class/struct that wraps pthread_t and provides whatever > functionality it wants. > > In fact, for the simple requirment of isNull, compare, and hash, just > use a (pthread_t *) for a thread handle! > > - Igor > > - Igor Lubashev > > -----Original Message----- > *From:* Alexander Terekhov [TEREKHOV@de.ibm.com] > *Received:* Saturday, 05 Feb 2011, 10:18am > *To:* Ross Johnson [Ross.Johnson@homemail.com.au] > *CC:* pthreads-win32@sourceware.org [pthreads-win32@sourceware.org] > *Subject:* Re: Compilation issue with pthreads-win32 > > Ross Johnson wrote: > [...] > > You are right that all Unixes (that I know of) define > > pthread_t as a scalar type and that pthread_win32 > > deviates from this convention by using a struct. The > > projects FAQ offers a history and explanation in > > Question 11, which I've quoted at the end. > > Mainframe UNIX > > http://en.wikipedia.org/wiki/Single_UNIX_Specification#z.2FOS > > also uses a struct. > > Unfortunately pthreads do not provide standard > > pthread_null/compare/hash > > interfaces, see > > http://tinyurl.com/buj9 > > but you might want to add _np() functions... > > regards, > alexander. > > > Ross Johnson @sourceware.org on 05.02.2011 > 09:51:35 > > Sent by: pthreads-win32-owner@sourceware.org > > > To: pthreads-win32@sourceware.org > cc: > Subject: Re: Compilation issue with pthreads-win32 > > > Hi Claude, > > Glad you found the library useful and thankyou for the feedback. > > You are right that all Unixes (that I know of) define pthread_t as a > scalar type and that pthread_win32 deviates from this convention by > using a struct. The projects FAQ offers a history and explanation in > Question 11, which I've quoted at the end. > > IIRC Solaris does not use a pointer but uses an int type that sequences > to provide a unique id for each new thread in a process. I have no idea > how Solaris maps this counting value to thread storage when needed nor > how it does it efficiently when the set of living threads becomes > sparse, but they do it. Linux and BSD use pointers which are not unique > if the thread exits and its memory has been allocated to a new > pthread_t, or any other type for that matter. I know from comments in > their code that the BSD developers have thought about this issue and the > possibility of changing away from a pointer type at some point. > > Having done so ourselves we no longer get questions about the many > complex problems that arise when using pointers. We have had a few > questions like yours to do with porting, all three of which have been > fairly easily solved AFAIK. I take the blame for the decision but I > thought it was better to provide application reliability, predictability > etc. for everyone and accept the occasional but fixable compiler breakage. > > But the crux of it is this: the POSIX (and now the SUSv3) standard > allows pthread_t to be scalar or non-scalar and in making it non-scalar > in pthreads-win we are not just taking advantage of a loophole in the > standard; the standard has deliberately not defined pthread_t so that > implementations can define it how they see fit. The notes within the > standard actually suggest defining pthread_t as a struct exactly as it > is defined here, to allow inclusion of a 'sequence' counter to render > the handle unique over time. > > But back to your code: > What would happen if you did not set SSD->id = 0, i.e. just leave it > unitialised? I'm curious because your code appears not to attempt a > comparison of the value with 0, e.g. "if (SSD->id == 0) ..." otherwise > you would see a compiler error attempting to compare a struct. > > If you can't avoid initialising a pthread_t variable, I would suggest > doing it by declaring a special pthread_t constant with the value you > want (0 in this case), e.g.: > > typedef union { > pthread_t t; > int filler[sizeof(pthread_t)/sizeof(int)]; > } init_t; > > const init_t u_init = {.filler = {0}}; # Relies on having a C99 > compliant compiler > > Then you can do this to initialise: > > SSD->id = u_init.t; > > Note that the initialisation of the array u_init.filler only sets the > first element to 0 explicitly and the remaining elements, if any, are > set to 0 by default. Since you don't really know how many elements there > are you should probably avoid trying to initialise more than one > element, i.e. don't do " = {.filler = {0 , 0}};". > > This method means you don't need to break the opacity of the pthread_t > and it should also be portable. > > Also for portability, you should only ever use the pthread_equal() > function to compare pthread_t types, e.g.: > > if (pthread_equal(SSD->id, u_init.t) { > ... > } > > And one more thing that I can mention. In pthreads-win32 you can call > pthread_kill(threadID, 0) to check if threadID is valid, i.e. refers to > a living thread. It will return ESRCH if invalid. However this is not > portable and therefore not safe but can sometimes be better than > nothing. It probably also works for Solaris and works here because we > can guarantee that threadID is a unique value within the process scope > and we can determine all of the previous values of living and dead > threadIDs. (This is not absolutely strictly true of course but is true > within the practical lifetimes of processes.) > > FAQ > === > Q 11 Why isn't pthread_t defined as a scalar (e.g. pointer or int) > like it is for other POSIX threads implementations? > ---- > > Originally pthread_t was defined as a pointer (to the opaque pthread_t_ > struct) and later it was changed to a struct containing the original > pointer plus a sequence counter. This is allowed under both the original > POSIX Threads Standard and the current Single Unix Specification. > > When pthread_t is a simple pointer to a struct some very difficult to > debug problems arise from the process of freeing and later allocing > thread structs because new pthread_t handles can acquire the identity of > previously detached threads. The change to a struct was made, along with > some changes to their internal managment, in order to guarantee (for > practical applications) that the pthread_t handle will be unique over the > life of the running process. > > Where application code attempts to compare one pthread_t against another > directly, a compiler error will be emitted because structs can't be > compared at that level. This should signal a potentially serious problem > in the code design, which would go undetected if pthread_t was a scalar. > > The POSIX Threading API provides a function named pthread_equal() to > compare pthread_t thread handles. > > Other pthreads implementations, such as Sun's, use an int as the handle > but do guarantee uniqueness within the process scope. Win32 scalar typed > thread handles also guarantee uniqueness in system scope. It wasn't clear > how well the internal management of these handles would scale as the > number of threads and the fragmentation of the sequence numbering > increased for applications where thousands or millions of threads are > created and detached over time. The current management of threads within > pthreads-win32 using structs for pthread_t, and reusing without ever > freeing them, reduces the management time overheads to a constant, which > could be important given that pthreads-win32 threads are built on top of > Win32 threads and will therefore include that management overhead on top > of their own. The cost is that the memory resources used for thread > handles will remain at the peak level until the process exits. > > While it may be inconvenient for developers to be forced away from making > assumptions about the internals of pthread_t, the advantage for the > future development of pthread-win32, as well as those applications that > use it and other pthread implementations, is that the library is free to > change pthread_t internals and management as better methods arise. > > > On 5/02/2011 1:35 AM, Claude LALYRE wrote: > > Hi Ross, > > > > I would like to thank a lot your pthreads-win32 team for the great > work they achieved. > > This week, I was in a situation of migrating UNIX source code to > Windows environment. > > And helpfully with your project phreads-win32 that task was easily > possible. > > > > But I encountered some compilation issues. And I have had to declare > some missing > > typedef and macros in my code, picked from cygwin header files. And > surprisingly > > it was enough for my code being able to compile. > > > > So as it was just a small issue, I thought I should give you my point > of view and > > the little declarations I made. I think that it should be easily > integrated in your > > source code. Just have a look at the posix.h attached file. > > > > Another point is concerning the declaration of your type "pthread_t". > In all UNIX > > platforms this is formerly a pointer, but in your Windows > implementation this > > is a struct object. The issue is that I was given a source file > containing a SSD > > object containing a field "id" of type pthread_t. > > > > struct SSD { > > pthread_t id; > > int dummy; > > } > > > > And somewhere else in the code they gave me, I have this > > SSD->id = 0; > > > > And that line of code was not accepted by cl.exe (Windows) compiler ! > > So I face the situation by adding this ugly fix > > > > #ifdef WIN32 > > SSD->id.p = 0 > > #else /* WIN32 */ > > SSD->id = 0; > > #endif /* WIN32 */ > > > > So I am sorry to tell you this about the most basic type of your > pthreads-win32 library, > > but it would have been great to keep the pthread_t type as a pointer > rather than a struct > > object. However, as I managed to fix this situation its a tiny issue, an > > enhancement suggestion rather than a bug... > > > > Thank a lot for all youy great job ! > > > > Claude. > > > > > > > > > > >