Back to index

lightning-sunbird  0.9+nobinonly
attach.c
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
00002 /* ***** BEGIN LICENSE BLOCK *****
00003  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00004  *
00005  * The contents of this file are subject to the Mozilla Public License Version
00006  * 1.1 (the "License"); you may not use this file except in compliance with
00007  * the License. You may obtain a copy of the License at
00008  * http://www.mozilla.org/MPL/
00009  *
00010  * Software distributed under the License is distributed on an "AS IS" basis,
00011  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00012  * for the specific language governing rights and limitations under the
00013  * License.
00014  *
00015  * The Original Code is the Netscape Portable Runtime (NSPR).
00016  *
00017  * The Initial Developer of the Original Code is
00018  * Netscape Communications Corporation.
00019  * Portions created by the Initial Developer are Copyright (C) 1998-2000
00020  * the Initial Developer. All Rights Reserved.
00021  *
00022  * Contributor(s):
00023  *
00024  * Alternatively, the contents of this file may be used under the terms of
00025  * either the GNU General Public License Version 2 or later (the "GPL"), or
00026  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00027  * in which case the provisions of the GPL or the LGPL are applicable instead
00028  * of those above. If you wish to allow use of your version of this file only
00029  * under the terms of either the GPL or the LGPL, and not to allow others to
00030  * use your version of this file under the terms of the MPL, indicate your
00031  * decision by deleting the provisions above and replace them with the notice
00032  * and other provisions required by the GPL or the LGPL. If you do not delete
00033  * the provisions above, a recipient may use your version of this file under
00034  * the terms of any one of the MPL, the GPL or the LGPL.
00035  *
00036  * ***** END LICENSE BLOCK ***** */
00037 
00038 /***********************************************************************
00039 **  1996 - Netscape Communications Corporation
00040 **
00041 ** Name: attach.c
00042 **
00043 ** Description: Platform-specific code to create a native thread. The native thread will
00044 **                            repeatedly call PR_AttachThread and PR_DetachThread. The
00045 **                            primordial thread waits for this new thread to finish.
00046 **
00047 ** Modification History:
00048 ** 13-May-97 AGarcia- Converted the test to accomodate the debug_mode flag.
00049 **              The debug mode will print all of the printfs associated with this test.
00050 **                    The regress mode will be the default mode. Since the regress tool limits
00051 **           the output to a one line status:PASS or FAIL,all of the printf statements
00052 **                    have been handled with an if (debug_mode) statement.
00053 ** 04-June-97 AGarcia removed the Test_Result function. Regress tool has been updated to
00054 **                   recognize the return code from tha main program.
00055 ** 12-June-97 Revert to return code 0 and 1.
00056 ***********************************************************************/
00057 
00058 /***********************************************************************
00059 ** Includes
00060 ***********************************************************************/
00061 
00062 /* Used to get the command line option */
00063 #include "nspr.h"
00064 #include "pprthred.h"
00065 #include "plgetopt.h"
00066 
00067 #include <stdio.h>
00068 
00069 #ifdef WIN32
00070 #include <windows.h>
00071 #include <process.h>
00072 #elif defined(_PR_PTHREADS)
00073 #include <pthread.h>
00074 #include "md/_pth.h"
00075 #elif defined(IRIX)
00076 #include <sys/types.h>
00077 #include <sys/prctl.h>
00078 #include <sys/wait.h>
00079 #include <errno.h>
00080 #elif defined(SOLARIS)
00081 #include <thread.h>
00082 #elif defined(OS2)
00083 #define INCL_DOS
00084 #define INCL_ERRORS
00085 #include <os2.h>
00086 #include <process.h>
00087 #elif defined(XP_BEOS)
00088 #include <kernel/OS.h>
00089 #endif
00090 
00091 #define DEFAULT_COUNT 1000
00092 PRIntn failed_already=0;
00093 PRIntn debug_mode;
00094 
00095 
00096 int count;
00097 
00098 
00099 static void 
00100 AttachDetach(void)
00101 {
00102     PRThread *me;
00103     PRInt32 index;
00104 
00105     for (index=0;index<count; index++) {
00106         me = PR_AttachThread(PR_USER_THREAD, 
00107                              PR_PRIORITY_NORMAL,
00108                              NULL);
00109  
00110         if (!me) {
00111             fprintf(stderr, "Error attaching thread %d: PR_AttachThread failed\n",
00112                   count);
00113               failed_already = 1;
00114               return;
00115         }
00116         PR_DetachThread();
00117     }
00118 }
00119 
00120 /************************************************************************/
00121 
00122 static void Measure(void (*func)(void), const char *msg)
00123 {
00124     PRIntervalTime start, stop;
00125     double d;
00126 
00127     start = PR_IntervalNow();
00128     (*func)();
00129     stop = PR_IntervalNow();
00130 
00131     d = (double)PR_IntervalToMicroseconds(stop - start);
00132        if (debug_mode)
00133     printf("%40s: %6.2f usec\n", msg, d / count);
00134 }
00135 
00136 #ifdef WIN32
00137 static unsigned __stdcall threadStartFunc(void *arg)
00138 #elif defined(IRIX) && !defined(_PR_PTHREADS)
00139 static void threadStartFunc(void *arg)
00140 #elif defined(XP_BEOS)
00141 static int32 threadStartFunc(void *arg)
00142 #else
00143 static void * threadStartFunc(void *arg)
00144 #endif
00145 {
00146 #ifdef _PR_DCETHREADS
00147     {
00148         int rv;
00149         pthread_t self = pthread_self();
00150         rv = pthread_detach(&self);
00151         if (debug_mode) PR_ASSERT(0 == rv);
00152               else if (0 != rv) failed_already=1;
00153     }
00154 #endif
00155 
00156     Measure(AttachDetach, "Attach/Detach");
00157 
00158 #ifndef IRIX
00159     return 0;
00160 #endif
00161 }
00162 
00163 int main(int argc, char **argv)
00164 {
00165 #ifdef _PR_PTHREADS
00166     int rv;
00167     pthread_t threadID;
00168     pthread_attr_t attr;
00169 #elif defined(SOLARIS)
00170     int rv;
00171     thread_t threadID;
00172 #elif defined(WIN32)
00173     DWORD rv;
00174     unsigned threadID;
00175     HANDLE hThread;
00176 #elif defined(IRIX)
00177     int rv;
00178     int threadID;
00179 #elif defined(OS2)
00180     int rv;
00181     TID threadID;
00182 #elif defined(XP_BEOS)
00183        thread_id threadID;
00184        int32 threadRV;
00185        status_t waitRV;
00186 #endif
00187 
00188        /* The command line argument: -d is used to determine if the test is being run
00189        in debug mode. The regress tool requires only one line output:PASS or FAIL.
00190        All of the printfs associated with this test has been handled with a if (debug_mode)
00191        test.
00192        Usage: test_name [-d] [-c n]
00193        */
00194        PLOptStatus os;
00195        PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
00196        while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
00197     {
00198               if (PL_OPT_BAD == os) continue;
00199         switch (opt->option)
00200         {
00201         case 'd':  /* debug mode */
00202                      debug_mode = 1;
00203             break;
00204         case 'c':  /* loop count */
00205                      count = atoi(opt->value);
00206             break;
00207          default:
00208             break;
00209         }
00210     }
00211        PL_DestroyOptState(opt);
00212 
00213 #if defined(WIN16)
00214     printf("attach: This test is not valid for Win16\n");
00215     goto exit_now;
00216 #endif
00217 
00218        if(0 == count) count = DEFAULT_COUNT;     
00219 
00220     /*
00221      * To force the implicit initialization of nspr20
00222      */
00223     PR_SetError(0, 0);
00224     PR_STDIO_INIT();
00225 
00226     /*
00227      * Platform-specific code to create a native thread.  The native
00228      * thread will repeatedly call PR_AttachThread and PR_DetachThread.
00229      * The primordial thread waits for this new thread to finish.
00230      */
00231 
00232 #ifdef _PR_PTHREADS
00233 
00234     rv = _PT_PTHREAD_ATTR_INIT(&attr);
00235     if (debug_mode) PR_ASSERT(0 == rv);
00236        else if (0 != rv) {
00237               failed_already=1;
00238               goto exit_now;
00239        }
00240        
00241 #ifndef _PR_DCETHREADS
00242     rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
00243     if (debug_mode) PR_ASSERT(0 == rv);
00244        else if (0 != rv) {
00245               failed_already=1;
00246               goto exit_now;
00247        }
00248 #endif  /* !_PR_DCETHREADS */
00249     rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL);
00250     if (rv != 0) {
00251                      fprintf(stderr, "thread creation failed: error code %d\n", rv);
00252                      failed_already=1;
00253                      goto exit_now;
00254        }
00255        else {
00256               if (debug_mode)
00257                      printf ("thread creation succeeded \n");
00258 
00259        }
00260     rv = _PT_PTHREAD_ATTR_DESTROY(&attr);
00261     if (debug_mode) PR_ASSERT(0 == rv);
00262        else if (0 != rv) {
00263               failed_already=1;
00264               goto exit_now;
00265        }
00266     rv = pthread_join(threadID, NULL);
00267     if (debug_mode) PR_ASSERT(0 == rv);
00268        else if (0 != rv) {
00269               failed_already=1;
00270               goto exit_now;
00271        }
00272 
00273 #elif defined(SOLARIS)
00274 
00275     rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID);
00276     if (rv != 0) {
00277        if(!debug_mode) {
00278               failed_already=1;
00279               goto exit_now;
00280        } else 
00281               fprintf(stderr, "thread creation failed: error code %d\n", rv);
00282     }
00283     rv = thr_join(threadID, NULL, NULL);
00284     if (debug_mode) PR_ASSERT(0 == rv);
00285        else if (0 != rv)
00286        {
00287               failed_already=1;
00288               goto exit_now;
00289        }
00290 
00291 
00292 #elif defined(WIN32)
00293 
00294     hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL,
00295             0, &threadID); 
00296     if (hThread == 0) {
00297         fprintf(stderr, "thread creation failed: error code %d\n",
00298                 GetLastError());
00299               failed_already=1;
00300               goto exit_now;
00301     }
00302     rv = WaitForSingleObject(hThread, INFINITE);
00303     if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
00304        else if (rv == WAIT_FAILED) {
00305               failed_already=1;
00306               goto exit_now;
00307        }
00308 
00309 #elif defined(IRIX)
00310 
00311     threadID = sproc(threadStartFunc, PR_SALL, NULL);
00312     if (threadID == -1) {
00313 
00314                      fprintf(stderr, "thread creation failed: error code %d\n",
00315                                    errno);
00316                      failed_already=1;
00317                      goto exit_now;
00318        
00319        }
00320        else {
00321               if (debug_mode) 
00322                      printf ("thread creation succeeded \n");
00323               sleep(3);
00324               goto exit_now;
00325        }
00326     rv = waitpid(threadID, NULL, 0);
00327     if (debug_mode) PR_ASSERT(rv != -1);
00328        else  if (rv != -1) {
00329               failed_already=1;
00330               goto exit_now;
00331        }
00332 
00333 #elif defined(OS2)
00334 
00335 # ifdef __EMX__
00336     threadID = (TID) _beginthread((void *)threadStartFunc, NULL,
00337             32768, NULL); 
00338 # else
00339     threadID = (TID) _beginthread((void(* _Optlink)(void*))threadStartFunc, NULL,
00340             32768, NULL); 
00341 # endif
00342     if (threadID == -1) {
00343         fprintf(stderr, "thread creation failed: error code %d\n", errno);
00344         failed_already=1;
00345         goto exit_now;
00346     }
00347     rv = DosWaitThread(&threadID, DCWW_WAIT);
00348     if (debug_mode) {
00349         PR_ASSERT(rv == NO_ERROR);
00350     } else if (rv != NO_ERROR) {
00351         failed_already=1;
00352         goto exit_now;
00353     }
00354 
00355 #elif defined(XP_BEOS)
00356        
00357        threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL);
00358        if (threadID <= B_ERROR) {
00359               fprintf(stderr, "thread creation failed: error code %08lx\n", threadID);
00360               failed_already = 1;
00361               goto exit_now;
00362        }
00363        if (resume_thread(threadID) != B_OK) {
00364               fprintf(stderr, "failed starting thread: error code %08lx\n", threadID);
00365               failed_already = 1;
00366               goto exit_now;
00367        }
00368 
00369        waitRV = wait_for_thread(threadID, &threadRV);
00370        if (debug_mode)
00371               PR_ASSERT(waitRV == B_OK);
00372        else if (waitRV != B_OK) {
00373               failed_already = 1;
00374               goto exit_now;
00375        }
00376        
00377 #else
00378        if (!debug_mode)
00379               failed_already=1;
00380        else   
00381               printf("The attach test does not apply to this platform because\n"
00382            "either this platform does not have native threads or the\n"
00383            "test needs to be written for this platform.\n");
00384        goto exit_now;
00385 #endif
00386 
00387 exit_now:
00388    if(failed_already)       
00389               return 1;
00390        else
00391               return 0;
00392 }