コード例 #1
0
ファイル: kaidemo2.c プロジェクト: komh/kai
int main( int argc, char *argv[])
{
    int             key;
    ULONG           ulMode;
    const char     *modeName[] = {"DART", "UNIAUD"};
    KAICAPS         kaic;
    TID             tid1, tid2, tid3;

    ulMode = ( argc < 2 ) ? KAIM_AUTO : atoi( argv[ 1 ]);
    if( kaiInit( ulMode ))
    {
        fprintf( stderr, "Failed to init kai\n");

        return 0;
    }

    kaiCaps( &kaic );

    printf("Mode = %s, Available channels = %ld, PDD Name = %s\n",
           modeName[ kaic.ulMode - 1 ], kaic.ulMaxChannels, kaic.szPDDName );

    printf("Press ESC to quit\n");

    m_fQuit    = FALSE;
    m_nThreads = 0;

    tid1 = play("demo1.wav");
    tid2 = play("demo2.wav");
    tid3 = play("demo3.wav");

    while( !m_fQuit && m_nThreads )
    {
        key = read_key();

        if( key == 27 )     /* ESC */
            m_fQuit = TRUE;

        DosSleep( 1 );
    }

    DosWaitThread( &tid1, DCWW_WAIT );
    DosWaitThread( &tid2, DCWW_WAIT );
    DosWaitThread( &tid3, DCWW_WAIT );

    kaiDone();

    return 0;
}
コード例 #2
0
ファイル: specific.c プロジェクト: etix/vlc
/**
 * Cleans up after system_Init() and system_Configure().
 */
void system_End(void)
{
    if( tidIPCFirst == _gettid())
    {
        HPIPE hpipe;
        ULONG ulAction;
        ULONG cbActual;
        ULONG rc;

        do
        {
            rc = DosOpen( VLC_IPC_PIPE, &hpipe, &ulAction, 0, 0,
                          OPEN_ACTION_OPEN_IF_EXISTS,
                          OPEN_ACCESS_READWRITE | OPEN_SHARE_DENYREADWRITE |
                          OPEN_FLAGS_FAIL_ON_ERROR,
                          NULL );

            if( rc == ERROR_PIPE_BUSY )
                DosWaitNPipe( VLC_IPC_PIPE, -1 );
            else if( rc )
                DosSleep( 1 );
        } while( rc );

        /* Ask for IPCHelper to quit */
        ULONG ulCmd = IPC_CMD_QUIT;
        DosWrite( hpipe, &ulCmd, sizeof( ulCmd ), &cbActual );

        DosClose( hpipe );

        TID tid = tidIPCHelper;
        DosWaitThread( &tid, DCWW_WAIT );
    }
}
コード例 #3
0
void omni_thread::join(void** status)
{
    mutex.lock();

    if ((_state != STATE_RUNNING) && (_state != STATE_TERMINATED)) {
        mutex.unlock();
        throw omni_thread_invalid();
    }

    mutex.unlock();

    if (this == self())
        throw omni_thread_invalid();

    if (detached)
        throw omni_thread_invalid();

    DB(cerr << "omni_thread::join: doing DosWaitThread\n");

    APIRET rc = DosWaitThread( &handle , DCWW_WAIT );
    if ( rc != 0 )
        throw omni_thread_fatal(rc);

    DB(cerr << "omni_thread::join: DosWaitThread succeeded\n");

    if (status)
      *status = return_val;

    delete this;
}
コード例 #4
0
/*--------------------------------------------------
 * Wait the thread
 *-------------------------------------------------*/
PMThread& PMThread::join()
{
  if( run_id != -1 )
    DosWaitThread( &run_id, DCWW_WAIT );

  return *this;
}
コード例 #5
0
/****************************************************************\
 * Routine to signal consumer to release resource.              *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:     SignalUserEvent(pfAutoMode)                       *
 *                                                              *
 *  Purpose:  Posts user event semaphore to signal thread to    *
 *            release resource.  Also posts event to stop       *
 *            Auto mode if *pfAutoMode is true.                 *
 *                                                              *
 *  Usage:    Called in file usercmd.c when the user selects    *
 *            Event from the semaphore menu.                    *
 *                                                              *
 *  Method:   Turns off Auto mode, if present by posting auto   *
 *            semaphore.  User event is then posted.            *
 *                                                              *
 *  Returns:                                                    *
 *                                                              *
\****************************************************************/
VOID SignalUserEvent(PULONG pfAutoMode)
{
  ULONG rc;

                          /* If sample is in auto mode turn auto mode off. */
  if (*pfAutoMode)
  {
      rc = DosPostEventSem(hevStopAuto);
      if (rc)
      {
         SemError("DosPostEventSem Stop Auto",rc);
      }
                       /* Wait for auto mode thread to die, so we don't
                          end up with multiple copies of it later.    */

      rc = DosWaitThread(&tidAutoThread,0L);
      if (rc)
      {
         SemError("DosWaitThread",rc);
      }
      *pfAutoMode = FALSE;
      DosCloseEventSem (hevStopAuto);
  }

  /* If Auto mode haas already posted the event this is OK
     so we will not check error codes here. */

  DosPostEventSem(aSquares[rand() % MAXRESOURCES].hev);
  return;
}
コード例 #6
0
int main(void)
{
    APIRET apiret;
    TID tid;
    HEV hev;
    int i;

    /* test thread1 */
    printf(__FILE__ " main function invoked\n");
    printf("Test named event semaphores\n");

    apiret = DosCreateEventSem("\\SEM32\\TEST3SEM", &hev, DC_SEM_SHARED, FALSE);
    printf("DosCreateEventSem function returned %d\n", (int)apiret);

    /* post to thread 1 */
    printf("Starting thread with DosCreateThread\n");
    apiret = DosCreateThread(&tid, thread1, (ULONG)hev, 0, 8092);

    for (i = 0; i < 4; i++) {
        apiret = DosPostEventSem(hev);
        printf("Function DosPostEventSem returned %d\n", (int)apiret);
        DosSleep(1500); /* 1.5 seconds */
    }

    apiret = DosWaitThread(&tid, DCWW_WAIT);
    printf("Function DosWaitThread returned %d\n", (int)apiret);

    /* post to thread 2 */
    printf("Starting thread with DosCreateThread\n");
    apiret = DosCreateThread(&tid, thread2, (ULONG)hev, 0, 8092);

    for (i = 0; i < 4; i++) {
        apiret = DosPostEventSem(hev);
        printf("Function DosPostEventSem returned %d\n", (int)apiret);
        DosSleep(1500); /* 1.5 seconds */
    }

    apiret = DosWaitThread(&tid, DCWW_WAIT);
    printf("Function DosWaitThread returned %d\n", (int)apiret);
    printf("The last DosWaitEventSem should have returned 640\n");

    apiret = DosCloseEventSem(hev);
    printf("Function DosCloseEventSem returned %d\n", (int)apiret);

    return 0;
}
コード例 #7
0
/****************************************************************\
 * Routine to really stop semaphore example.                    *
 *--------------------------------------------------------------*
 *                                                              *
 *  Name:     StopSemaphore( PVOID pvArg )                      *
 *                                                              *
 *  Purpose:  Waits for threads to complete,                    *
 *            Sends message to message thread to indicate this  *
 *            has occurred, and exits.                          *
 *                                                              *
 *  Usage:    Exec'd from BeginStop when user selects Stop from *
 *            Semaphore menu.                                   *
 *                                                              *
 *  Method:   Turns off Auto mode, if present by posting auto   *
 *            semaphore.  Then stop event is posted.  Waits     *
 *            for threads to die.                               *
 *  Returns:                                                    *
 *                                                              *
\****************************************************************/
VOID StopSemaphore( PVOID pvArg )
{
   ULONG rc,usCount, i;
   PULONG pfAutoMode = (PULONG)pvArg;

   if (*pfAutoMode)
   {
      rc = DosWaitThread(&tidAutoThread,0L);
      if (rc && (rc != ERROR_INVALID_THREADID))
      {
         SemError("DosWaitThread",rc);
      }
      *pfAutoMode = FALSE;
   }
   /* Wait for usConsumer threads to die.  Order of death not important. */

   for (usCount = 0; usCount < usConsumerThreadsCreated; usCount++)
   {
      rc = DosWaitThread(&thrConsumers[usCount].tid,0L);

      /* rc is ERROR_INVALID_THREADID the thread is already dead.*\
      \* This is OK and not a error.                             */

      if (rc && (rc != ERROR_INVALID_THREADID))
      {
         SemError("DosWaitThread",rc);
      }
   }
                /* Threads dead so we don't need semaphores any more.  */
   DosCloseEventSem(hevStopAuto);
   DosCloseEventSem(hevStop);
   DosCloseMutexSem(hmtxOwnResource);
   for (i = 0; i < MAXRESOURCES; i++)
   {
      DosCloseEventSem(aSquares[i].hev);
   }
   DosCloseMuxWaitSem (hmuxResource);
   WinPostMsg (hwndMain, WM_COMMAND, (MPARAM)IDM_STOPFINISHED, (MPARAM)NULL);
   DosExit (EXIT_THREAD, 0);
   return;
}
コード例 #8
0
ファイル: copyonwrite-test.c プロジェクト: komh/os2codes
int main( void )
{
    TID tid;

    tid = _beginthread( worker, NULL, 1024 * 1024, NULL );

    DosWaitThread( &tid, DCWW_WAIT );

    worker( NULL );

    return 0;
}
コード例 #9
0
ファイル: thread.c プロジェクト: Tilka/vlc
void vlc_timer_destroy (vlc_timer_t timer)
{
    if (timer->htimer != NULLHANDLE)
        DosStopTimer (timer->htimer);

    timer->quit = true;
    DosPostEventSem (timer->hev);
    DosWaitThread (&timer->tid, DCWW_WAIT);
    DosCloseEventSem (timer->hev);

    free (timer);
}
コード例 #10
0
SSMODULEDECLSPEC int SSMODULECALL SSModule_StopSaving(void)
{
  // This is called when we have to stop saving.
#ifdef DEBUG_LOGGING
  AddLog("[SSModule_StopSaving] : Enter!\n");
#endif
  if (!bRunning)
  {
#ifdef DEBUG_LOGGING
    AddLog("[SSModule_StopSaving] : Not running, Leaving.\n");
#endif
    return SSMODULE_ERROR_NOTRUNNING;
  }

#ifdef DEBUG_LOGGING
  AddLog("[SSModule_StopSaving] : Closing saver window\n");
#endif

  // Notify saver thread to stop!
  if (bOnlyPreviewMode)
  {
    // In preview mode, which means that there is no window created, but the
    // window was subclassed. So we cannot close the window, but we have to
    // post the WM_QUIT message into the thread's message queue to notify it
    // that this is the end of its job.
    WinPostQueueMsg(hmqSaverThreadMsgQueue, WM_QUIT, (MPARAM) NULL, (MPARAM) NULL);
  }
  else
  {
    // Close saver window
    WinPostMsg(hwndSaverWindow, WM_QUIT, (MPARAM) NULL, (MPARAM) NULL);
  }

#ifdef DEBUG_LOGGING
  AddLog("[SSModule_StopSaving] : Waiting for thread to die\n");
#endif

  // Wait for the thread to stop
  DosWaitThread(&tidSaverThread, DCWW_WAIT);

#ifdef DEBUG_LOGGING
  AddLog("[SSModule_StopSaving] : Screen saver stopped.\n");
#endif

  // Ok, screensaver stopped.
  bRunning = FALSE;
  free(CfgDlgInit.pchText);
  CfgDlgInit.pchText = NULL;

  return SSMODULE_NOERROR;
}
// ------------------------------------------------------------------------------------------------------------
int main( int argc, char **argv )
{
  HMQ           hmq;
  QMSG          qmsg;
  ULONG         ulWork;
  SWP           swp;
  LONG          cx;

  // initialize globals struct to defaults
  memset( &globals, 0, sizeof( globals ));
  strcpy( globals.szRexxFileName, "DRAW.CMD" );
  // parameter is a REXX filename
  if( argc > 1 ) {
    strcpy( globals.szRexxFileName, argv[ 1 ] );
  }
  // PM application init
  globals.hab = WinInitialize( 0 );
  hmq = WinCreateMsgQueue( globals.hab, 0);
  // create a frame window with listbox to display REXX diagnostic output
  ulWork = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_ICON | FCF_TASKLIST;
  globals.hwndOutputFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWork, WC_LISTBOX, OUTPUTCAPTION, LS_NOADJUSTPOS,
                                               (HMODULE)0, ID_RXDRAW, &globals.hwndOutputListbox );
  assert( globals.hwndOutputFrame   );
  assert( globals.hwndOutputListbox );
  // create a frame window to display REXX graphical output
  WinRegisterClass( globals.hab, CLASSNAME, (PFNWP)ClientWinProc, CS_SIZEREDRAW, 0 );
  ulWork = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER | FCF_MINMAX | FCF_MENU | FCF_ICON | FCF_TASKLIST;
  globals.hwndFrame = WinCreateStdWindow( HWND_DESKTOP, 0, &ulWork, CLASSNAME, CAPTION, 0,
                                         (HMODULE)0, ID_RXDRAW, &globals.hwndClient );
  assert( globals.hwndFrame  );
  assert( globals.hwndClient );
  // tile the two windows using shell's preferred placement for one
  WinQueryTaskSizePos( globals.hab, 0, &swp );
  cx = (swp.cx * 2) / 3;
  ulWork = SWP_SIZE | SWP_MOVE | SWP_ZORDER | SWP_SHOW | SWP_ACTIVATE | SWP_RESTORE;
  WinSetWindowPos( globals.hwndOutputFrame, HWND_TOP, swp.x+cx, swp.y, swp.cx-cx, swp.cy, ulWork );
  WinSetWindowPos( globals.hwndFrame, HWND_TOP, swp.x, swp.y, cx, swp.cy, ulWork );
  // message loop
  while( WinGetMsg( globals.hab, &qmsg, 0, 0, 0 ))   WinDispatchMsg( globals.hab, &qmsg );
  if( !globals.fCloseMsgSent ) {
    // got a WM_QUIT without WM_CLOSE; must be shutdown or Close from Window List
    WinPostMsg( globals.hwndObject, WM_QUIT, 0, 0 );
  }
  // clean up
  WinDestroyWindow( globals.hwndFrame );
  WinDestroyWindow( globals.hwndOutputFrame );
  WinDestroyMsgQueue( hmq );
  WinTerminate( globals.hab );
  DosWaitThread( &globals.tidObject, DCWW_WAIT );
  return 0;
}
コード例 #12
0
void TThreads::suspend() {
   shutDownFlag=1;
   TID localTID=mouseThreadID;
   if (localTID != 0xFFFF) DosWaitThread(&localTID,DCWW_WAIT);
   //  cerr << " MouseThread has ended\n";
   ULONG count;
   assert(! DosQueryEventSem(TThreads::hevKeyboard2,&count));
   if (!count)
      assert(! DosPostEventSem(TThreads::hevKeyboard2));  // Make sure the thread is running.
   localTID=keyboardThreadID;
   DosWaitThread(&localTID,DCWW_WAIT);
   //  cerr << " KeyboardThread has ended\n";

   assert(!DosCloseMutexSem(hmtxMouse1));
   assert(!DosCloseEventSem(hevKeyboard2));
   assert(!DosCloseEventSem(hevKeyboard1));
   assert(!DosCloseEventSem(hevMouse2));
   assert(!DosCloseEventSem(hevMouse1));
   assert(!DosCloseMuxWaitSem(hmuxMaster));

   if (tiled->mouseHandle != 0xFFFF) MouClose(tiled->mouseHandle);   // This doesn't work, the mouseThread uses the handle.
   assert(! DosFreeMem(tiled));  // Better not, dito
}
コード例 #13
0
ファイル: kva.c プロジェクト: fabsther/vlc-mort
/*****************************************************************************
 * Close: destroy KVA video thread output method
 *****************************************************************************
 * Terminate an output method created by Open
 *****************************************************************************/
static void Close ( vlc_object_t *object )
{
    vout_display_t * vd = (vout_display_t *)object;
    vout_display_sys_t * sys = vd->sys;

    WinPostQueueMsg( sys->hmq, WM_QUIT, 0, 0 );

    DosWaitThread( &sys->tid, DCWW_WAIT );

    if( sys->pool )
        picture_pool_Delete( sys->pool );

    DosCloseEventSem( sys->ack_event );

    free( sys );
}
コード例 #14
0
ファイル: silcos2thread.c プロジェクト: FabrizioFabbe/runtime
SilcBool silc_thread_wait(SilcThread thread, void **exit_value)
{
#ifdef SILC_THREADS

  if (DosWaitThread((unsigned long)thread, DCWW_WAIT) !=
      ERROR_INVALID_THREADID) {
    if (exit_value)
      *exit_value = NULL;
    return TRUE;
  }

  return FALSE;
#else
  return FALSE;
#endif
}
コード例 #15
0
/*******************************************************************************
    Timeout waiting for a thread to terminate. Alarms if unsucessful.
*******************************************************************************/
BOOL TimeoutDlgThread(PTID pTid, ULONG ulNtimeslices)
    {
        APIRET  rc;
        do  {
                rc = DosWaitThread(pTid, DCWW_NOWAIT);
                if(rc == ERROR_THREAD_NOT_TERMINATED)
                    {
                        DosSleep(1);
                        ulNtimeslices--;
                    }
                else if(rc == NO_ERROR) return(TRUE);
                else return(FALSE);
            }   while(ulNtimeslices);
        if(!ulNtimeslices) WinAlarm(HWND_DESKTOP, WA_ERROR);
        return(FALSE);
    }
コード例 #16
0
/**
 * free what has been allocated by avcodec_thread_init().
 * must be called after decoding has finished, especially do not call while avcodec_thread_execute() is running
 */
void avcodec_thread_free(AVCodecContext *s){
    ThreadContext *c= s->thread_opaque;
    int i;

    for(i=0; i<s->thread_count; i++){

        c[i].func= NULL;
        DosPostEventSem(c[i].work_sem);
        //        ReleaseSemaphore(c[i].work_sem, 1, 0);
        DosWaitThread((PTID)&c[i].thread,DCWW_WAIT);
//        WaitForSingleObject(c[i].thread, INFINITE);
        if(c[i].work_sem) DosCloseEventSem(c[i].work_sem);//CloseHandle(c[i].work_sem);
        if(c[i].done_sem) DosCloseEventSem(c[i].done_sem);//CloseHandle(c[i].done_sem);
    }

    av_freep(&s->thread_opaque);
}
コード例 #17
0
SSMODULEDECLSPEC int SSMODULECALL SSModule_StartSaving(HWND hwndParent, char *pchHomeDirectory, int bPreviewMode)
{
  // This is called when we should start the saving.
  // Return error if already running, start the saver thread otherwise!

  if (bRunning)
    return SSMODULE_ERROR_ALREADYRUNNING;

  readConfig(pchHomeDirectory);

  iSaverThreadState = STATE_UNKNOWN;
  bOnlyPreviewMode = bPreviewMode;
  tidSaverThread = _beginthread(fnSaverThread,
                                0,
                                1024*1024,
                                (void *) hwndParent);

  if (tidSaverThread == 0)
  {
#ifdef DEBUG_LOGGING
    AddLog("[SSModule_StartSaving] : Error creating screensaver thread!\n");
#endif
    // Error creating screensaver thread!
    return SSMODULE_ERROR_INTERNALERROR;
  }

  // Wait for saver thread to start up!
  while (iSaverThreadState==STATE_UNKNOWN) DosSleep(32);
  if (iSaverThreadState!=STATE_RUNNING)
  {
#ifdef DEBUG_LOGGING
    AddLog("[SSModule_StartSaving] : Something went wrong in screensaver thread!\n");
#endif

    // Something wrong in saver thread!
    DosWaitThread(&tidSaverThread, DCWW_WAIT);
    return SSMODULE_ERROR_INTERNALERROR;
  }

  // Fine, screen saver started and running!
  bRunning = TRUE;
  return SSMODULE_NOERROR;
}
コード例 #18
0
ファイル: sh6bench.c プロジェクト: cksystemsgroup/libscm
/* wait for all benchmark threads to terminate */
void WaitForThreads(ThreadID tids[], unsigned tidCnt)
{
#ifdef __OS2__
	while (tidCnt--)
		DosWaitThread(&tids[tidCnt], DCWW_WAIT);

#elif defined(WIN32)
	WaitForMultipleObjects(tidCnt, tids, TRUE, INFINITE);

#elif defined(__sun)
	int prio;
	thr_getprio(thr_self(), &prio);
	thr_setprio(thr_self(), max(0, prio-1));
	while (tidCnt--)
		thr_join(0, NULL, NULL);

#elif defined(_POSIX_THREADS) || defined(_POSIX_REENTRANT_FUNCTIONS)
	while (tidCnt--)
		pthread_join(tids[tidCnt], NULL);

#endif
}
コード例 #19
0
ファイル: con_os2.cpp プロジェクト: AaronDP/efte_adbshell
int GUI::ClosePipe(int id) {
  if ((id < 0) || (id > MAX_PIPES)) return -1;

  if (Pipes[id].used == 0) return -1;

  if (Pipes[id].reading == 1) {
    Pipes[id].DoTerm = 1;
    DosPostEventSem(Pipes[id].ResumeRead);
    DosWaitThread(&Pipes[id].tid, DCWW_WAIT);
  }
  free(Pipes[id].buffer);
  free(Pipes[id].Command);
  DosCloseEventSem(Pipes[id].NewData);
  DosCloseEventSem(Pipes[id].ResumeRead);
  DosCloseMutexSem(Pipes[id].Access);

  //    fprintf(stderr, "Pipe Close: %d\n", id);
  Pipes[id].used = 0;

  // ConContinue();
  return Pipes[id].RetCode;
}
コード例 #20
0
int bd_rix(void) {

 void BuildFieldListRix(FIELDDESCTYPE fieldList[]);

#pragma pack(1)

 ACCESSPACK AP;
 DOSFILEPACK DFP;
 CREATEDATAPACK CDP;
 CREATEINDEXPACK CIP;
 HANDLEPACK HP;
 OPENPACK OP;
 QUERYSETPACK QSP;
 STATINDEXPACK SIP;   // for separate thread reindex percentage done

 struct EmpRecType {
  CHAR tag;              // record tag, init to SPACE, * means deleted
  CHAR empID[9];         // SSN (not 0T string)
  CHAR empLN[16];        // last name
  CHAR empFN[16];        // first name
  CHAR empHire[8];       // "YYYYMMDD" (not 0T string)
  CHAR empDept[6];       // department assigned
 }; // 56 bytes
 struct EmpRecType EmpRec;

#pragma pack()   // no more Bullet-accessed data structures follow

 time_t startTime, endTime;
 int display = 0;          // display results or not flag
 int thread = 1;           // dispatch reindex in a thread flag
 int lastNameVar;          // used to construct on-the-fly data record...
 int lastFourVar;          // ...that is unique

 LONG rez;                 // return value from Bullet

 CHAR nameIX3[] = ".\\$bd_rix.ix3"; // name of index file created
 ULONG indexID=0;                // handle of index file
 CHAR keyExpression[128];        // key expression string buffer (159 max)
 CHAR keyBuffer[68];             // buffer used to store/receive key values

 CHAR nameData[] = ".\\$bd_rix.dbf";// name of data file created
 ULONG dataID=0;                 // handle of data file
 FIELDDESCTYPE fieldList[5];     // 5 fields used in data record

 LONG i;                 // counter
 CHAR tmpStr[128];       // misc stuff, non-Bullet related
 CHAR putStr[128];
 ULONG tmpU;

 SIP.func = 0; // init+ref it for DOSX32 compile

 // set field descriptor info for DBF data file created later

 memset(fieldList,0,sizeof(fieldList));  // init unused bytes to 0 (required)
 BuildFieldListRix(fieldList);


 // Use 300K for workspace in reindex module (min is 48K, max is whatever you want)
 // Note: larger is not necessarily faster; it depends on the data order
 #define NEW_XBUFF_SIZE (300*1024)

 QSP.func = SET_SYSVARS_XB;
 QSP.item = REINDEX_BUFFER_SIZE;
 QSP.itemValue = NEW_XBUFF_SIZE;
 rez = BULLET(&QSP);
 if (rez) {
    sprintf(putStr,"Failed SET_SYSVARS_XB #%d (reindex buffer size) call.  Err: %d\n",QSP.item,rez);
    PutMsg(putStr);
    goto Abend;
 }

 tmpU = QSP.itemValue;              // 0=default, or 144KB total buffer space
 if (tmpU == 0) tmpU = (144*1024);
 sprintf(putStr,"Bullet reindex tmp buffer was %d KB, now %d KB\n", tmpU/1024,
                                                                     NEW_XBUFF_SIZE/1024);
 PutMsg(putStr);

 // Delete previous files from any previous run (disregard any error return)

 DFP.func = DELETE_FILE_DOS;
 DFP.filenamePtr = nameData;
 rez = BULLET(&DFP);
 DFP.filenamePtr = nameIX3;
 rez = BULLET(&DFP);


 // Create the data file, a standard DBF (ID=3) as defined in fieldList above.

 CDP.func = CREATE_DATA_XB;
 CDP.filenamePtr = nameData;
 CDP.noFields = 5;
 CDP.fieldListPtr = fieldList;
 CDP.fileID = 0x03;
 rez = BULLET(&CDP);
 if (rez) {
    sprintf(putStr,"Failed data file create.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }


 // Open the data file (required before creating an index file for it)

 OP.func = OPEN_DATA_XB;
 OP.filenamePtr = nameData;
 OP.asMode = READWRITE | DENYNONE;
 rez = BULLET(&OP);
 if (rez) {
    sprintf(putStr,"Failed data file open.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }
 dataID = OP.handle;


 // Create an index file for the data file opened above.
 // This example uses a multi-part key composed of parts of last name and SSN.

 strcpy(keyExpression,"SUBSTR(LNAME,1,4)+SUBSTR(SSN,6,4)");

 CIP.func = CREATE_INDEX_XB;
 CIP.filenamePtr = nameIX3;
 CIP.keyExpPtr = keyExpression;
 CIP.xbLink = dataID;            // the handle of the data file
 CIP.sortFunction = NLS_SORT | SORT_SET;  // sort by NLS (SORT_SET defined in PLATFORM.H)
 CIP.codePage = CODEPAGE;        // code page to use, or 0 for system default
 CIP.countryCode = CTRYCODE;     // country code...
 CIP.collatePtr = collateTable;  // (see #define INT2165xxNS above)
 CIP.nodeSize = 512;             // 512-byte node size (or 1024, 2048 bytes)
 rez = BULLET(&CIP);
 if (rez) {
    sprintf(putStr,"Failed index file create.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }


 // Open the index file (what we just created above).
 // As with the index-create, the index-open requires the handle of the data
 // file which this index file indexes.

 OP.func = OPEN_INDEX_XB;
 OP.filenamePtr = nameIX3;
 OP.asMode = READWRITE | DENYNONE;
 OP.xbLink = dataID;
 rez = BULLET(&OP);
 if (rez) {
    sprintf(putStr,"Failed index file open.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }
 indexID = OP.handle;


 PutMsg("Display all data accessed (slower results)? (y/N) ");
 GetMsg(tmpStr);
 if (*tmpStr=='y') display = 1;

#if PLATFORM == ON_OS2 || PLATFORM == ON_WIN32 && FOR_WINDOWS == 0
  PutMsg("  Dispatch REINDEX_XB in a separate thread? (Y/n) ");
  GetMsg(tmpStr);
  if (*tmpStr=='n') thread = 0;
#else
  thread = 0;
#endif

 PutMsg("  How many records do you want for this test run? ");
 GetMsg(tmpStr);
 recs2add = atol(tmpStr);

 if (recs2add < 1) recs2add = 1;         // would you rather end the test?
 if (recs2add > 9999999) recs2add = 1;   // why wait around for 10M?


 // Add the data records, which are created here, on-the-fly, varying enough
 // to make unique records.

 lastFourVar = 1;                        // 0001 start (as used in strncpy() below)
 lastNameVar = 0;                        // 0000 start

 EmpRec.tag = ' ';                       // set to not-deleted
 strncpy(EmpRec.empID,"465990001",9);    // only changing last 4 in test
 strcpy(EmpRec.empLN,"0000LastNameNum"); // only changing first 4 in test
 strcpy(EmpRec.empFN,"YourFirstName");   // everyone has this first name!
 strncpy(EmpRec.empHire,"19950527",8);   // YYYYMMDD DBF form, no \0 on date
 strcpy(EmpRec.empDept,"MIS");           // everyone works for MIS!

 sprintf(putStr,"    Adding %d records...  ",recs2add);
 PutMsg(putStr);

 time(&startTime);

 AP.func = ADD_RECORD_XB;
 AP.handle = dataID;
 AP.recPtr = &EmpRec;
 for (i = 1; i <= recs2add; i++) {

    sprintf(tmpStr,"%4.4i",lastFourVar++);
    strncpy(EmpRec.empID+5,tmpStr,4);            // update last 4 of empID
    rez = BULLET(&AP);                           // AP. already setup
    if (rez) {
       sprintf(putStr,"Failed while adding record %d.  Err: %d\n",i,rez);
       PutMsg(putStr);
       goto Abend;
    }
    if (lastFourVar > 9999) {                    // changes every 10,000 adds
       lastFourVar = 0;                          // where name takes carry ...
       sprintf(tmpStr,"%4.4i",++lastNameVar);
       strncpy(EmpRec.empLN,tmpStr,4);           // update first 4 of empLN
    }

#if FOR_WINDOWS == 1                   // deal with message queue every now and then
    if (i % Q_ADD == 0) DoWinThing(0); // 0=no waiting around
#endif

 }
 time(&endTime);
 sprintf(putStr,"took %u secs.\n",(endTime - startTime));
 PutMsg(putStr);


 // Reindex

 sprintf(putStr,"Reindexing %d records...  \r",recs2add);
 PutMsg(putStr);

 time(&startTime);

 AP.func = REINDEX_XB;           // this is all there is to reindexing even...
 AP.handle = indexID;            // ...million-record databases
 AP.keyPtr = keyBuffer;          // if dup key error...(see manual for details)
 AP.nextPtr = NULL;              // just this one index file

 if (thread) {

#if PLATFORM == ON_DOSX32

    PutMsg(" Threads are not supported on this OS\n");
    goto Abend;

#elif PLATFORM == ON_OS2

    rez = DosCreateThread(&tidRix,
                          (PFNTHREAD) &ThreadRix,
                          (ULONG) &AP,
                          CREATE_READY | STACK_SPARSE,
                          32768);  // min is 8K stack
    if (rez) {
       sprintf(putStr,"Could not start reindex thread.  Err: %d\n",rez);
       PutMsg(putStr);
       goto Abend;
    }

    DosSleep(32);  // wait a bit to let reindex code set progress to non-zero

    // could also use a callback routine to put out a reindex % number

    SIP.func = STAT_INDEX_XB;
    SIP.handle = indexID;
    rez = BULLET(&SIP);
    while (rez==0) {
       DosSleep(100);
       sprintf(putStr,"Reindexing %d records... %3.3u%%\r",recs2add,SIP.progress);
       PutMsg(putStr);
       rez = BULLET(&SIP);
       if (SIP.progress==0) {
          sprintf(putStr,"Reindexing %d records...  ",recs2add);
          PutMsg(putStr);
          break;
       }
    }
    if (rez) {
       sprintf(putStr,"Failed progress check.  Err: %d\n",rez);
       PutMsg(putStr);
    } // continue

    // Can actually get here _before_ the reindex thread fully exits, but
    // won't get here until SIP.progress is back to 0.

    time(&endTime);

    // It's likely that the thread has exited completely by now, but if
    // it was blocked after setting SIP.progress to 0 (hung up in the cache,
    // etc.), then it's possible to get here well before Bullet has exited.
    // Since calling Bullet while Bullet is busy (for most routines) results
    // in a rc=640 being returned (mutex timeout), just call this to wait
    // for the thread to exit completely.  Note that this has only been seen
    // under Win95 (done, but blocked), but this little routine won't hurt.
    // Ignore any error, which there will be if the thread has indeed exited.
    // Another option is to use a non-0 mutex-timeout value, via SET_SYSVARS_XB.

    rez = DosWaitThread(&tidRix,DCWW_WAIT);
    // ignore error (such as "invalid thread ID")

    DosSleep(1); // allow the reindex thread to exit BULLET() (and set rez)

    rez = rezRix;           // get return code set by ThreadRix()
    if (rez) {              // rez is already AP.stat
       sprintf(putStr,"Failed reindex.  Err: %d\n",rez);
       PutMsg(putStr);
       goto Abend;
    }
    sprintf(putStr,"took %u secs.\n",(endTime - startTime));
    PutMsg(putStr);

#elif PLATFORM == ON_WIN32

    hRix = CreateThread(NULL,
                        32768,               // 8KB min.
                        (LPTHREAD_START_ROUTINE) &ThreadRix,
                        (PACCESSPACK) &AP,
                        0,                   // immediate start
                        &tidRix);


    if (hRix==0) {
       rez = GetLastError();
       sprintf(putStr,"Could not start reindex thread.  Err: %d\n",rez);
       PutMsg(putStr);
       goto Abend;
    }

    Sleep(32);   // wait a bit to let reindex code set progress to non-zero

    SIP.func = STAT_INDEX_XB;
    SIP.handle = indexID;
    rez = BULLET(&SIP);
    while (rez==0) {
       Sleep(100);
       sprintf(putStr,"Reindexing %d records... %3.3u%%\r",recs2add,SIP.progress);
       PutMsg(putStr);
       rez = BULLET(&SIP);
       if (SIP.progress==0) {
          sprintf(putStr,"Reindexing %d records...  ",recs2add);
          PutMsg(putStr);
          break;
       }
    }
    if (rez) {
       sprintf(putStr,"Failed progress check.  Err: %d\n",rez);
       PutMsg(putStr);
    } // continue


    // Can actually get here _before_ the reindex thread fully exits, but
    // won't get here until SIP.progress is back to 0.

    time(&endTime);

    // It's likely that the thread has exited completely by now, but if
    // it was blocked after setting SIP.progress to 0 (hung up in the cache,
    // etc.), then it's possible to get here well before Bullet has exited.
    // Since calling Bullet while Bullet is busy (for most routines) results
    // in a rc=640 being returned (mutex timeout), just call this to wait
    // for the thread to exit completely.  Note that this has only been seen
    // under Win95 (done, but blocked), but this little routine won't hurt.
    // Ignore any error, which there will be if the thread has indeed exited.
    // Another option is to use a non-0 mutex-timeout value, via SET_SYSVARS_XB.
    // Error code 640 is documented in BULLET_2.H.

    rez = WaitForSingleObject(hRix,10*1000); // 10 secs plenty of flush time
    // ignore error

    Sleep(32);   // allow the reindex thread to exit BULLET() (and set rez)
                 // why 32ms?  Only because OS/2 min std resolution is 32ms

    rez = rezRix;       // get return code set by ThreadRix()
    if (rez) {              // rez is already AP.stat
       sprintf(putStr,"Failed reindex.  Err: %d\n",rez);
       PutMsg(putStr);
       goto Abend;
    }
    sprintf(putStr,"took %u secs.\n",(endTime - startTime));
    PutMsg(putStr);

#endif

 }
 else {

    // no separate thread, so use callback (especially useful for DOSX32 and Win32s)

    QSP.func = SET_SYSVARS_XB;
    QSP.item = CALLBACK_PTR;
    QSP.itemValue = (ULONG) &CallbackRix;
    rez = BULLET(&QSP);
    if (rez) {
       sprintf(putStr,"Failed SET_SYSVARS_XB #%d (callback address) call.  Err: %d\n",QSP.item,rez);
       PutMsg(putStr);
       goto Abend;
    }

    // now make actual REINDEX_XB call, set up above

    rez = BULLET(&AP);       // rez=0 if okay, or =1 if pack failed with ecode in AP.stat
    if (rez) {
       rez = AP.stat;
       sprintf(putStr,"Failed reindex.  Err: %d\n",rez);
       PutMsg(putStr);
       goto Abend;
    }
    time(&endTime);
    sprintf(putStr,"Reindexing %d records...  took %u secs.\n",recs2add,(endTime - startTime));
    PutMsg(putStr);

    // turn off callback

    QSP.func = SET_SYSVARS_XB;
    QSP.item = CALLBACK_PTR;
    QSP.itemValue = 0;
    rez = BULLET(&QSP);
    if (rez) {
       sprintf(putStr,"Failed SET_SYSVARS_XB #%d (callback clear) call.  Err: %d\n",QSP.item,rez);
       PutMsg(putStr);
       goto Abend;
    }

 }


 // Get key data

 memset(keyBuffer,0,sizeof(keyBuffer));
 sprintf(putStr," Accessing %d keys...     ",recs2add);
 PutMsg(putStr);
 if (display) PutMsg("\n");
 time(&startTime);
 AP.func = FIRST_KEY_XB;
 AP.handle = indexID;
 AP.keyPtr = keyBuffer;
 rez = BULLET(&AP);
 i=0;
 while (rez==0) {
    if (display) {
       sprintf(putStr,"%s  %9.9lu\r", keyBuffer, AP.recNo);
       PutMsg(putStr);
    }
    i++;
    AP.func = NEXT_KEY_XB;
    rez = BULLET(&AP);

#if FOR_WINDOWS == 1                   // deal with message queue every now and then
    if (i % Q_KEY == 0) DoWinThing(0); // 0=no waiting around
#endif

 }
 time(&endTime);
 if (display) PutMsg("\n...");

 // expected rez is EXB_END_OF_FILE

 if (rez == EXB_END_OF_FILE) rez=0;
 if (rez) {
    sprintf(putStr,"Failed KEY access.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }
 sprintf(putStr,"took %u secs. for %d keys\n",(endTime - startTime),i);
 PutMsg(putStr);


 // Get key and record data

 sprintf(putStr," Accessing %d keys+recs...",recs2add);
 PutMsg(putStr);
 if (display) PutMsg("\n");
 time(&startTime);

 AP.func = GET_FIRST_XB;
 AP.handle = indexID;
 AP.keyPtr = keyBuffer;
 AP.recPtr = &EmpRec;
 rez = BULLET(&AP);
 i=0;
 while (rez==0) {
    if (display) {
       sprintf(putStr,"%s  %9.9lu   %s\r", keyBuffer, AP.recNo, &EmpRec); // partial show
       PutMsg(putStr);
    }
    i++;
    AP.func = GET_NEXT_XB;
    rez = BULLET(&AP);

#if FOR_WINDOWS == 1                   // deal with message queue every now and then
    if (i % Q_GET == 0) DoWinThing(0); // 0=no waiting around
#endif

 }
 time(&endTime);
 if (display) PutMsg("\n...");

 // expected rez is EXB_END_OF_FILE

 if (rez == EXB_END_OF_FILE) rez=0;
 if (rez) {
    sprintf(putStr,"Failed GET access.  Err: %d\n",rez);
    PutMsg(putStr);
    goto Abend;
 }
 sprintf(putStr,"took %u secs. for %d keys & records\n",(endTime - startTime),i);
 PutMsg(putStr);


 // Fatal errors above come straight to here
Abend:

 // Close files

 if (indexID) {
    HP.func = CLOSE_INDEX_XB;
    HP.handle = indexID;
    rez = BULLET(&HP);
    if (rez) {
       sprintf(putStr,"Failed index file close.  Err: %d\n",rez);
       PutMsg(putStr);
    }
 }

 // Unlikely the above could fail, considering how far it has gotten so far!
 // But logic says that we want to continue closing other open files...

 if (dataID) {
    HP.func = CLOSE_DATA_XB;
    HP.handle = dataID;
    rez = BULLET(&HP);
    if (rez) {
       sprintf(putStr,"Failed data file close.  Err: %d\n",rez);
       PutMsg(putStr);
    }
 }
 return rez;  // module exit
}
コード例 #21
0
ファイル: mpmt_os2_child.c プロジェクト: Alivx/apache2nginx
void ap_mpm_child_main(apr_pool_t *pconf)
{
    ap_listen_rec *lr = NULL;
    int requests_this_child = 0;
    int rv = 0;
    unsigned long ulTimes;
    int my_pid = getpid();
    ULONG rc, c;
    HQUEUE workq;
    apr_pollset_t *pollset;
    int num_listeners;
    TID server_maint_tid;
    void *sb_mem;

    /* Stop Ctrl-C/Ctrl-Break signals going to child processes */
    DosSetSignalExceptionFocus(0, &ulTimes);
    set_signals();

    /* Create pool for child */
    apr_pool_create(&pchild, pconf);

    ap_run_child_init(pchild, ap_server_conf);

    /* Create an event semaphore used to trigger other threads to shutdown */
    rc = DosCreateEventSem(NULL, &shutdown_event, 0, FALSE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create shutdown semaphore, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Gain access to the scoreboard. */
    rc = DosGetNamedSharedMem(&sb_mem, ap_scoreboard_fname,
                              PAG_READ|PAG_WRITE);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "scoreboard not readable in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_calc_scoreboard_size();
    ap_init_scoreboard(sb_mem);

    /* Gain access to the accpet mutex */
    rc = DosOpenMutexSem(NULL, &ap_mpm_accept_mutex);

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "accept mutex couldn't be accessed in child, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Find our pid in the scoreboard so we know what slot our parent allocated us */
    for (child_slot = 0; ap_scoreboard_image->parent[child_slot].pid != my_pid && child_slot < HARD_SERVER_LIMIT; child_slot++);

    if (child_slot == HARD_SERVER_LIMIT) {
        ap_log_error(APLOG_MARK, APLOG_ERR, 0, ap_server_conf,
                     "child pid not found in scoreboard, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    ap_my_generation = ap_scoreboard_image->parent[child_slot].generation;
    memset(ap_scoreboard_image->servers[child_slot], 0, sizeof(worker_score) * HARD_THREAD_LIMIT);

    /* Set up an OS/2 queue for passing connections & termination requests
     * to worker threads
     */
    rc = DosCreateQueue(&workq, QUE_FIFO, apr_psprintf(pchild, "/queues/httpd/work.%d", my_pid));

    if (rc) {
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_FROM_OS_ERROR(rc), ap_server_conf,
                     "unable to create work queue, exiting");
        clean_child_exit(APEXIT_CHILDFATAL);
    }

    /* Create initial pool of worker threads */
    for (c = 0; c < ap_min_spare_threads; c++) {
//        ap_scoreboard_image->servers[child_slot][c].tid = _beginthread(worker_main, NULL, 128*1024, (void *)c);
    }

    /* Start maintenance thread */
    server_maint_tid = _beginthread(server_maintenance, NULL, 32768, NULL);

    /* Set up poll */
    for (num_listeners = 0, lr = ap_listeners; lr; lr = lr->next) {
        num_listeners++;
    }

    apr_pollset_create(&pollset, num_listeners, pchild, 0);

    for (lr = ap_listeners; lr != NULL; lr = lr->next) {
        apr_pollfd_t pfd = { 0 };

        pfd.desc_type = APR_POLL_SOCKET;
        pfd.desc.s = lr->sd;
        pfd.reqevents = APR_POLLIN;
        pfd.client_data = lr;
        apr_pollset_add(pollset, &pfd);
    }

    /* Main connection accept loop */
    do {
        apr_pool_t *pconn;
        worker_args_t *worker_args;
        int last_poll_idx = 0;

        apr_pool_create(&pconn, pchild);
        worker_args = apr_palloc(pconn, sizeof(worker_args_t));
        worker_args->pconn = pconn;

        if (num_listeners == 1) {
            rv = apr_socket_accept(&worker_args->conn_sd, ap_listeners->sd, pconn);
        } else {
            const apr_pollfd_t *poll_results;
            apr_int32_t num_poll_results;

            rc = DosRequestMutexSem(ap_mpm_accept_mutex, SEM_INDEFINITE_WAIT);

            if (shutdown_pending) {
                DosReleaseMutexSem(ap_mpm_accept_mutex);
                break;
            }

            rv = APR_FROM_OS_ERROR(rc);

            if (rv == APR_SUCCESS) {
                rv = apr_pollset_poll(pollset, -1, &num_poll_results, &poll_results);
                DosReleaseMutexSem(ap_mpm_accept_mutex);
            }

            if (rv == APR_SUCCESS) {
                if (last_poll_idx >= num_listeners) {
                    last_poll_idx = 0;
                }

                lr = poll_results[last_poll_idx++].client_data;
                rv = apr_socket_accept(&worker_args->conn_sd, lr->sd, pconn);
                last_poll_idx++;
            }
        }

        if (rv != APR_SUCCESS) {
            if (!APR_STATUS_IS_EINTR(rv)) {
                ap_log_error(APLOG_MARK, APLOG_ERR, rv, ap_server_conf,
                             "apr_socket_accept");
                clean_child_exit(APEXIT_CHILDFATAL);
            }
        } else {
            DosWriteQueue(workq, WORKTYPE_CONN, sizeof(worker_args_t), worker_args, 0);
            requests_this_child++;
        }

        if (ap_max_requests_per_child != 0 && requests_this_child >= ap_max_requests_per_child)
            break;
    } while (!shutdown_pending && ap_my_generation == ap_scoreboard_image->global->running_generation);

    ap_scoreboard_image->parent[child_slot].quiescing = 1;
    DosPostEventSem(shutdown_event);
    DosWaitThread(&server_maint_tid, DCWW_WAIT);

    if (is_graceful) {
        char someleft;

        /* tell our worker threads to exit */
        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosWriteQueue(workq, WORKTYPE_EXIT, 0, NULL, 0);
            }
        }

        do {
            someleft = 0;

            for (c=0; c<HARD_THREAD_LIMIT; c++) {
                if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                    someleft = 1;
                    DosSleep(1000);
                    break;
                }
            }
        } while (someleft);
    } else {
        DosPurgeQueue(workq);

        for (c=0; c<HARD_THREAD_LIMIT; c++) {
            if (ap_scoreboard_image->servers[child_slot][c].status != SERVER_DEAD) {
                DosKillThread(ap_scoreboard_image->servers[child_slot][c].tid);
            }
        }
    }

    apr_pool_destroy(pchild);
}
コード例 #22
0
ファイル: uthread_join.c プロジェクト: OS2World/LIB-PTHREADS
int
pthread_join(pthread_t pthread, void **thread_return)
{
	int             rval = 0;
	int             status = 0;
	TID		tid;
	pthread_t	pthread1;

	PTHREAD_INIT;

	/* Block signals: */
	_thread_kern_sig_block(&status);

	/* Point to the first thread in the list: */
	pthread1 = _thread_link_list;

	/* Search for the thread to join to: */
	while (pthread1 != NULL && pthread1 != pthread) {
		/* Point to the next thread: */
		pthread1 = pthread1->nxt;
	}

	if (pthread1 == NULL) {
		/* Point to the first thread in the dead thread list: */
		pthread1 = _thread_dead;

		/* Search for the thread to join to: */
		while (pthread1 != NULL && pthread1 != pthread) {
			/* Point to the next thread: */
			pthread1 = pthread1->nxt;
		}
	}

	if (pthread1 == NULL) {
		/* Return an error: */
		errno = ESRCH;
		rval = -1;

	/* Check if this thread has been detached: */
	} else if ((pthread->attr.flags & PTHREAD_DETACHED) != 0) {
		/* Return an error: */
		errno = ESRCH;
		rval = -1;
	}
	/* Check if the thread is not dead: */
	else if (pthread->state != PS_DEAD) {
		/* Add the running thread to the join queue: */
		/* _thread_queue_enq(&(pthread->join_queue), _thread_run); */
		_thread_kern_sig_unblock(status);

		/* Schedule the next thread: */
		/* _thread_kern_sched_state(PS_JOIN, __FILE__, __LINE__); */
		PTHREAD_NEW_STATE(_thread_run, PS_JOIN);
		tid = (pthread)->threadid;
		DosWaitThread(&tid, DCWW_WAIT);
		PTHREAD_NEW_STATE(_thread_run, PS_RUNNING);

		/* Block signals again: */
		_thread_kern_sig_block(&status);

		/* Check if the thread is not detached: */
		if ((pthread->attr.flags & PTHREAD_DETACHED) == 0) {
			/* Check if the return value is required: */
			if (thread_return) {
				/* Return the thread's return value: */
				*thread_return = pthread->ret;
			}
		} else {
			/* Return an error: */
			errno = ESRCH;
			rval = -1;
		}
	} else {
		/* Check if the return value is required: */
		if (thread_return != NULL) {
			/* Return the thread's return value: */
			*thread_return = pthread->ret;
		}
	}

	/* Unblock signals: */
	_thread_kern_sig_unblock(status);

	/* Return the completion status: */
	return (rval);
}
コード例 #23
0
void fnSaverThread(void *p)
{
  HWND hwndOldFocus;
  HWND hwndParent = (HWND) p;
  HWND hwndOldSysModal;
  HAB hab;
  QMSG msg;
  ULONG ulStyle;

  // Set our thread to slightly more than regular to be able
  // to update the screen fine.
  DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, +5, 0);

  hab = WinInitialize(0);
  hmqSaverThreadMsgQueue = WinCreateMsgQueue(hab, 0);

  if (bOnlyPreviewMode)
  {
    PFNWP pfnOldWindowProc;
    // We should run in preview mode, so the hwndParent we have is not the
    // desktop, but a special window we have to subclass.
    pfnOldWindowProc = WinSubclassWindow(hwndParent,
                                         (PFNWP) fnSaverWindowProc);

    // Initialize window proc (simulate WM_CREATE)
    WinSendMsg(hwndParent, WM_SUBCLASS_INIT, (MPARAM) NULL, (MPARAM) NULL);
    // Also make sure that the window will be redrawn with this new
    // window proc.
    WinInvalidateRect(hwndParent, NULL, FALSE);

    iSaverThreadState = STATE_RUNNING;

#ifdef DEBUG_LOGGING
    AddLog("[fnSaverThread] : Starting Cairo drawing thread\n");
#endif
    // Start Cairo drawing thread
    tidCairoDrawThread = _beginthread(CairoDrawThread,
                                      0,
                                      1024*1024,
                                      (void *) hwndParent);

#ifdef DEBUG_LOGGING
    AddLog("[fnSaverThread] : Entering message loop (Preview)\n");
#endif

    // Process messages until WM_QUIT!
    while (WinGetMsg(hab, &msg, 0, 0, 0))
      WinDispatchMsg(hab, &msg);

#ifdef DEBUG_LOGGING
    AddLog("[fnSaverThread] : Leaved message loop (Preview)\n");
#endif

#ifdef DEBUG_LOGGING
    AddLog("[fnSaverThread] : Stopping Cairo drawing thread\n");
#endif
    bShutdownDrawing = 1;
    DosWaitThread(&tidCairoDrawThread, DCWW_WAIT);


    // Uinitialize window proc (simulate WM_DESTROY)
    WinSendMsg(hwndParent, WM_SUBCLASS_UNINIT, (MPARAM) NULL, (MPARAM) NULL);

    // Undo subclassing
    WinSubclassWindow(hwndParent,
                      pfnOldWindowProc);
    // Also make sure that the window will be redrawn with the old
    // window proc.
    WinInvalidateRect(hwndParent, NULL, FALSE);

    iSaverThreadState = STATE_STOPPED_OK;
  } else
  {
    // We should run in normal mode, so create a new window, topmost, and everything else...
    WinRegisterClass(hab, (PSZ) pchSaverWindowClassName,
                     (PFNWP) fnSaverWindowProc,
                     CS_SIZEREDRAW | CS_CLIPCHILDREN | CS_CLIPSIBLINGS, 0);

    hwndOldFocus = WinQueryFocus(HWND_DESKTOP);

    // Create the saver output window so that it will be the child of
    // the given parent window.
    // Make window 'Always on top' because we'll be in real screensaver mode!
    ulStyle = WS_VISIBLE | WS_TOPMOST;
    hwndSaverWindow = WinCreateWindow(HWND_DESKTOP, pchSaverWindowClassName, "Screen saver",
                                      ulStyle,
                                      0, 0,
                                      (int) WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN),
                                      (int) WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN),
                                      HWND_DESKTOP,
                                      HWND_TOP,
                                      0x9fff, // Some ID....
                                      NULL, NULL);
    if (!hwndSaverWindow)
    {
#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : Could not create window!\n");
#endif
      // Yikes, could not create window!
      iSaverThreadState = STATE_STOPPED_ERROR;
    } else
    {
      // Cool, window created!

      // Make sure nobody will be able to switch away of it!
      // We do this by making the window system-modal, and giving it the focus!
      hwndOldSysModal = WinQuerySysModalWindow(HWND_DESKTOP);
      WinSetSysModalWindow(HWND_DESKTOP, hwndSaverWindow);
      WinSetFocus(HWND_DESKTOP, hwndSaverWindow);

      iSaverThreadState = STATE_RUNNING;

#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : Starting Cairo drawing thread\n");
#endif
      // Start Cairo drawing thread
      tidCairoDrawThread = _beginthread(CairoDrawThread,
                                        0,
                                        1024*1024,
                                        (void *) hwndSaverWindow);

#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : Entering message loop (Real)\n");
#endif
      // Process messages until WM_QUIT!
      while (WinGetMsg(hab, &msg, 0, 0, 0))
        WinDispatchMsg(hab, &msg);
#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : Leaved message loop (Real)\n");
#endif

#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : Stopping Cairo drawing thread\n");
#endif
      bShutdownDrawing = 1;
      DosWaitThread(&tidCairoDrawThread, DCWW_WAIT);

      // Undo system modalling
      WinSetSysModalWindow(HWND_DESKTOP, hwndOldSysModal);

      // Window closed, so destroy every resource we created!
      WinDestroyWindow(hwndSaverWindow);

      // Restore focus to old window
      WinSetFocus(HWND_DESKTOP, hwndOldFocus);

#ifdef DEBUG_LOGGING
      AddLog("[fnSaverThread] : STATE_STOPPED_OK\n");
#endif

      iSaverThreadState = STATE_STOPPED_OK;
    }
  }

  WinDestroyMsgQueue(hmqSaverThreadMsgQueue);
  WinTerminate(hab);

  _endthread();
}
/**************************************************************************
 *
 *  Name       : main(argc, argv)
 *
 *  Description: Initializes the application, gets and dispatches messages
 *               for the client window on thread 1 and terminates the
 *               application when a WM_QUIT message is received.  It then
 *               saves the configuration in os2.ini, destroys all OS/2
 *               PM resources, and terminates.
 *
 *               The following routine is the Presentation Manager program
 *               main body. The main body of a PM program is concerned with
 *               associating the application with the Presentation Manager
 *               system, creating its message queue, registering and displaying
 *               its main window, servicing its message queue during the time
 *               that the application is active, and disassociating the
 *               application from PM when the user is finished with the
 *               it. The remaining parts of this source module that are
 *               concerned with the Presentation Manager are the application's
 *               window procedures (main window procedure, child window
 *               procedures, and dialog window procedures) that process the
 *               messages associated with the application's various windows.
 *
 *  Concepts   : - obtains anchor block handle and creates message
 *                   queue
 *               - creates the main frame window which creates the
 *                   main client window
 *               - polls the message queue via Get/Dispatch Msg loop
 *               - upon exiting the loop, exits
 *
 *  API's      :  WinInitialize
 *                WinCreateMsgQueue
 *                WinRegisterClass
 *                WinLoadString
 *                WinCreateHelpInstance
 *                WinMessageBox
 *                WinCreateStdWindow
 *                WinQueryWindowULong
 *                WinAssociateHelpInstance
 *                WinAddSwitchEntry
 *                WinGetMsg
 *                WinDispatchMsg
 *                WinRemoveSwitchEntry
 *                WinDestroyHelpInstance
 *                WinDestroyWindow
 *                WinDestroyMsgQueue
 *                WinTerminate
 *
 *  Parameters :  [none]
 *
 *  Return     :  Always returns zero.  The ANSI standard requires that
 *                main be declared as an INT.
 *
 *************************************************************************/
INT main(INT argc, CHAR **argv)
{
                                        /* Define variables by type     */
   BOOL       bOK;                      /* Boolean used for return code */
   HAB        hab;                      /* PM anchor block handle       */
   HMQ        hmq;                      /* Message queue handle         */
   QMSG       qmsg;                     /* Message from message queue   */
   ULONG      ulCtlData;                /* Standard window create flags */
   HWND       hwndFrame;                /* Frame window handle          */
   HWND       hwndClient;               /* Client area window handle    */
   HWND       hwndHelp;                 /* Help window handle           */
   PMAIN_PARM pmp;                      /* Main parameters structure    */
   SWCNTRL    swctl;                    /* Struct to add to window list */
   HSWITCH    hsw;                      /* Window list handle ret'd     */
   HELPINIT   hmi;                      /* Struct for help creation     */
   CHAR       szWork[ LEN_WORKSTRING ]; /* General use string work area */
   PSZ        pszTitle;                 /* Pointer to program title     */


   /* normal PM application startup */
   hab = WinInitialize( 0 );
   hmq = WinCreateMsgQueue( hab, 0 );

   /*
    * Register a class for my client window's behavior.
    * This class has enough extra window words to hold a pointer.
    */
   bOK = WinRegisterClass(
                     hab,
                     CLASSNAME,
                     WinProc,
                     CS_SIZEREDRAW,
                     sizeof( PMAIN_PARM ));
   /*
    * Ensure WinRegisterClass worked ok; if not, present a message box.
    * ( See pmassert.h. )
    */
   pmassert( hab, bOK );


   /* Load program title and allocate a local copy. Use it in help creation. */
   WinLoadString( hab, (HMODULE)NULLHANDLE,
                  PROGRAM_TITLE, LEN_WORKSTRING, szWork );
   pszTitle = strdup( szWork );

   /* Create help. */
   memset( &hmi, 0, sizeof( hmi ));
   hmi.cb                 = sizeof( HELPINIT );
   hmi.phtHelpTable       = (HELPTABLE *)(0xffff0000 | ID_PRTSAMP);
   hmi.pszHelpWindowTitle = pszTitle;
   hmi.pszHelpLibraryName = HELP_FILE;
   hwndHelp = WinCreateHelpInstance( hab, &hmi );
   if( ! hwndHelp )
   {
      WinLoadString(hab, (HMODULE)NULLHANDLE,
                    ERRMSG_NO_HELP, LEN_WORKSTRING, szWork);
      WinMessageBox( HWND_DESKTOP,
                     HWND_DESKTOP,
                     szWork,
                     pszTitle,
                     (USHORT)0,
                     MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
   }

   /* done with local copy of title text */
   free( pszTitle );


   /* flags to control creation of window; use on call to WinCreateStdWindow */
   ulCtlData = FCF_SYSMENU | FCF_TITLEBAR | FCF_SIZEBORDER
                           | FCF_MINMAX | FCF_MENU | FCF_ACCELTABLE
                           | FCF_HORZSCROLL | FCF_VERTSCROLL;

   hwndFrame = WinCreateStdWindow( HWND_DESKTOP,
                                   WS_VISIBLE | FS_ICON | FS_SHELLPOSITION,
                                   &ulCtlData,
                                   CLASSNAME,
                                   NULL,    /* title text set in prtcreat.c */
                                   0,       /* client style                 */
                                   (HMODULE)NULLHANDLE,  /* resources in exe */
                                   ID_PRTSAMP,
                                   &hwndClient  );

   pmassert( hab, hwndFrame );
   pmassert( hab, hwndClient );

   /* create.c placed pointer to main params in client's window words; get it */
   pmp = (PMAIN_PARM) WinQueryWindowULong( hwndClient, QWL_USER );
   /* store help instance handle in main parameter block */
   pmp->hwndHelp  = hwndHelp;

   bOK = WinAssociateHelpInstance( hwndHelp, hwndFrame );
   pmassert( hab, bOK );

   /* Add program to task list. */
   memset( &swctl, 0, sizeof( SWCNTRL ));
   strcpy( swctl.szSwtitle, pmp->pszTitle );
   swctl.hwnd          = hwndFrame;
   swctl.uchVisibility = SWL_VISIBLE;
   swctl.fbJump        = SWL_JUMPABLE;
   hsw = WinAddSwitchEntry( &swctl );

   /* first parameter could be a filename, so store for later use */
   if (argc > 1)
   {
      argv++;
      strcpy( pmp->szArgFilename, *argv);
   }

   /* message loop */
   while( WinGetMsg( hab, &qmsg, (HWND)NULLHANDLE, 0, 0 ))
   {
     WinDispatchMsg( hab, &qmsg );
   }

   /* clean up */
   WinRemoveSwitchEntry( hsw );
   WinDestroyHelpInstance( hwndHelp );
   WinDestroyWindow( hwndFrame );
   WinDestroyMsgQueue( hmq );
   WinTerminate( hab );

   DosWaitThread( &pmp->tidObjectThread, DCWW_WAIT );
   return 0;
}  /* End of main() */
コード例 #25
0
/*
	SAVER_PROC
	This is the entry point into the saver module that is called by
	the ScreenSaver program.
	There should be no reason to alter the code.
	Depending on the requested function, the following tasks
	are performed:
	* set the name of the INI file to store and query settings
	* call the configuration dialog of the saver module
	* copy the name of the saver module into the supplied buffer
	* tell if the saver module is enabled
	* set the "enabled" state of the saver module
	* start the saver
	* stop the saver
	Note that before any processing is done, module configuration data is
	loaded from the INI-files.
*/
void	EXPENTRY SAVER_PROC(int function, HAB _hab, HWND hwndOwner, char *appname, void *buffer)
{
	hab = _hab;
	application_name = appname;
	hwndApplication = hwndOwner;
	// load all configuration data from INI-file
        if(function != FUNCTION_SETINIFILENAME)
	    load_configuration_data();
	switch(function){
	case FUNCTION_SETINIFILENAME:
		if(buffer != NULL)
			strcpy(ini_filename, (char *)buffer);
		else
			strcpy(ini_filename, "");
		return;
	case FUNCTION_CONFIGURE:
		// call the configuration dialog
		WinDlgBox(HWND_DESKTOP, hwndOwner, ConfigureDlgProc,
		  hmodDLL, IDD_CONFIGURE, application_name);
		return;
	case FUNCTION_STARTSAVER:
		// start the saver
		// get "low priority" state from supplied buffer (BOOL *)
		low_priority = *((BOOL *)buffer);
		// query size of screen
		screenSizeX = WinQuerySysValue(HWND_DESKTOP, SV_CXSCREEN);
		screenSizeY = WinQuerySysValue(HWND_DESKTOP, SV_CYSCREEN);
		// register window class for the saver window
		WinRegisterClass(hab, (PSZ)modulename,
		  (PFNWP)SaverWindowProc, 0, 0);
		// create the saver window
		hwndSaver = WinCreateWindow(HWND_DESKTOP, (PSZ)modulename,
		  (PSZ)NULL, WS_VISIBLE, 0, 0, screenSizeX, screenSizeY,
		  HWND_DESKTOP, HWND_TOP, 0, NULL, NULL);
		return;
	case FUNCTION_STOPSAVER:
		// stop the saver
		if(low_priority){
			stop_priority_thread = TRUE;
			DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 0, tidPriority);
			DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, 0, tidDraw);
			DosWaitThread(&tidPriority, DCWW_WAIT);
//			  DosKillThread(tidPriority);	***** kills thread 1 under OS/2 2.11
		}
		// tell drawing-thread to stop
		stop_draw_thread = TRUE;
		if(DosWaitThread(&tidDraw, DCWW_NOWAIT) == ERROR_THREAD_NOT_TERMINATED){
			// if priority of drawing-thread was set to idle time
			// priority, set it back to normal value
			DosSetPriority(PRTYS_THREAD, PRTYC_REGULAR, PRTYD_MAXIMUM, tidDraw);
			// wait until drawing-thread has ended
			DosWaitThread(&tidDraw, DCWW_WAIT);
		}

		if(hwndSaver != NULLHANDLE){
			// move saver window to front
			WinSetWindowPos(hwndSaver, HWND_TOP,
			  0, 0, 0, 0, SWP_ZORDER);
			// destroy saver window
			WinDestroyWindow(hwndSaver);
			hwndSaver = NULLHANDLE;
		}
		return;
	case FUNCTION_QUERYNAME:
		// copy module name to supplied buffer (CHAR *)
		strcpy(buffer, modulename);
		return;
	case FUNCTION_QUERYENABLED:
		// copy "enabled" state to supplied buffer (BOOL *)
		*((BOOL *)buffer) = configuration_data.enabled;
		return;
	case FUNCTION_SETENABLED:
		// get new "enabled" state from supplied buffer (BOOL *)
		configuration_data.enabled = *((BOOL *)buffer);
		write_profile_data();
		return;
	}

	// illegal function request
	WinAlarm(HWND_DESKTOP, WA_ERROR);
	return;
}
コード例 #26
0
ファイル: SDL_systhread.c プロジェクト: Bananattack/verge3
void
SDL_SYS_WaitThread(SDL_Thread * thread)
{
    TID tid = thread->handle;
    DosWaitThread(&tid, DCWW_WAIT);
}
コード例 #27
0
ファイル: MISCFUNC.C プロジェクト: OS2World/LIB-REXX-RXASYNC
APIRET MsgBox(
          PSZ    pszTitle,
          CHAR   chIcon,
          CHAR   chButtons,
          CHAR   chHelp,
          USHORT usNumber,
          PSZ    pszText )
{
   USHORT  usReply;
   MYMSG   msgMyMsg;
   PMYMSG  pMsg;

   pMsg = &msgMyMsg;

   /* Set message struct with parameters */

   pMsg->tidMyMsg   = NULLHANDLE;
   pMsg->habMyMsg   = NULLHANDLE;
   pMsg->hmqMyMsg   = NULLHANDLE;
   pMsg->hwndMyMsg  = NULLHANDLE;

   if ( pszTitle == NULL ) {
      strcpy( pMsg->szTitle, MSG_DEFAULT_TITLE );
   } else {
      strncpy( pMsg->szTitle, pszTitle, MSG_TITLE_LEN );
      (pMsg->szTitle)[MSG_TITLE_LEN] = EOSTR_CH;
   }

   pMsg->chIcon    = chIcon;
   pMsg->chButtons = chButtons;
   pMsg->chHelp    = chHelp;
   pMsg->usNumber  = usNumber;

   if ( pszText == NULL ) {
      strcpy( pMsg->szText, EMPTY_STR );
   } else {
      strcpy( pMsg->szText, pszText );
   }

   pMsg->usReply = MSG_RESPONSE_IGNORE;

   // if msgno not zero then build msg string from msgno
   // using msgtext for parameters (linefeed delimited),
   // any excess parameters are to be ignored, any
   // missing parameters need to be replaced with '<?>'

   pMsg->usNumber = 0;                  /* no help just yet */

   pMsg->tidMyMsg = _beginthread( MsgBoxThread, NULL, MSG_STACK_SIZE, (PVOID) pMsg );

   if ( pMsg->tidMyMsg == -1 ) {
      DosBeep(750,500);
   } else {
      DosWaitThread( &(pMsg->tidMyMsg), DCWW_WAIT );
   }

   usReply = pMsg->usReply; /* now we can extract the reply */

   return( usReply );

} /* end MsgBox() */
コード例 #28
0
ファイル: grop.c プロジェクト: OS2World/LIB-SDL-2014
VOID gropFree(PGROPDATA pGrop)
{
  ULONG      ulRC;
  HMQ        hmq;
  TID        tid;

  ulRC = DosRequestMutexSem( pGrop->hmtxData, 4000 );
  if ( ulRC != NO_ERROR )
    debug( "DosRequestMutexSem(), rc = %u", ulRC );

  hmq = pGrop->hmq;
  tid = pGrop->tid;
  // Tune off all callback functions.
  memset( &pGrop->stCallback, 0, sizeof(GROPCALLBACK) );
  DosReleaseMutexSem( pGrop->hmtxData );

  if ( ( hmq == NULLHANDLE ) || !WinPostQueueMsg( hmq, WM_QUIT, 0, 0 ) )
  {
    debug( "Hm... have not a thread?..." );
    if ( pGrop->fFullscreen )
      _setMode( pGrop, pGrop->ulModeIdx, FALSE );

    if ( tid != ((TID)(-1)) )
    {
      debug( "WTF?! %p %d", pGrop, tid );
      DosKillThread( tid );
    }
  }
  else if ( DosWaitThread( &tid, DCWW_NOWAIT ) != NO_ERROR )
  {
    debug( "Wait thread semaphore" );
    ulRC = DosWaitEventSem( pGrop->hevReady, 4000 );
    if ( ulRC != NO_ERROR )
    {
      PVIDEOMODE pMode = &pGrop->stModes.pList[pGrop->stModes.ulDesktopMode];

      debug( "DosWaitEventSem(), rc = %u. Kill thread...", ulRC );
      DosKillThread( tid );

      if ( pGrop->hwndDT != NULLHANDLE )
      {
        debug( "Return to the desktop..." );
        pGrop->pVideoSys->fnSetMode( pGrop->pVSData, pMode, FALSE,
                                     pGrop->hwndDT, pGrop->hdcDT );
      }
    }
    else
    {
      debug( "Wait thread" );
      DosWaitThread( &tid, DCWW_WAIT );
    }
  }
  else
    debug( "Thread already terminated." );

  // Remove GROP object from the list.
  ulRC = DosRequestMutexSem( hmtxGropList, SEM_INDEFINITE_WAIT );
  if ( ulRC != NO_ERROR )
    debug( "DosRequestMutexSem(), rc = %u", ulRC );
  lnkseqRemove( &lsGropList, pGrop );
  DosReleaseMutexSem( hmtxGropList );

  DosCloseEventSem( pGrop->hevReady );
  debugFree( pGrop );
  debug( "Success." );
}
コード例 #29
0
ファイル: thread_os2.cpp プロジェクト: Ayutac/OpenTTD
	/* virtual */ void Join()
	{
		DosWaitThread(&this->thread, DCWW_WAIT);
		this->thread = 0;
	}
コード例 #30
0
ファイル: attach.c プロジェクト: Andrel322/gecko-dev
int main(int argc, char **argv)
{
#ifdef _PR_PTHREADS
    int rv;
    pthread_t threadID;
    pthread_attr_t attr;
#elif defined(SOLARIS)
    int rv;
    thread_t threadID;
#elif defined(WIN32)
    DWORD rv;
    unsigned threadID;
    HANDLE hThread;
#elif defined(IRIX)
    int rv;
    int threadID;
#elif defined(OS2)
    int rv;
    TID threadID;
#elif defined(XP_BEOS)
	thread_id threadID;
	int32 threadRV;
	status_t waitRV;
#endif

	/* The command line argument: -d is used to determine if the test is being run
	in debug mode. The regress tool requires only one line output:PASS or FAIL.
	All of the printfs associated with this test has been handled with a if (debug_mode)
	test.
	Usage: test_name [-d] [-c n]
	*/
	PLOptStatus os;
	PLOptState *opt = PL_CreateOptState(argc, argv, "dc:");
	while (PL_OPT_EOL != (os = PL_GetNextOpt(opt)))
    {
		if (PL_OPT_BAD == os) continue;
        switch (opt->option)
        {
        case 'd':  /* debug mode */
			debug_mode = 1;
            break;
        case 'c':  /* loop count */
			count = atoi(opt->value);
            break;
         default:
            break;
        }
    }
	PL_DestroyOptState(opt);

#if defined(WIN16)
    printf("attach: This test is not valid for Win16\n");
    goto exit_now;
#endif

	if(0 == count) count = DEFAULT_COUNT;	

    /*
     * To force the implicit initialization of nspr20
     */
    PR_SetError(0, 0);
    PR_STDIO_INIT();

    /*
     * Platform-specific code to create a native thread.  The native
     * thread will repeatedly call PR_AttachThread and PR_DetachThread.
     * The primordial thread waits for this new thread to finish.
     */

#ifdef _PR_PTHREADS

    rv = _PT_PTHREAD_ATTR_INIT(&attr);
    if (debug_mode) PR_ASSERT(0 == rv);
	else if (0 != rv) {
		failed_already=1;
		goto exit_now;
	}
	
#ifndef _PR_DCETHREADS
    rv = pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
    if (debug_mode) PR_ASSERT(0 == rv);
	else if (0 != rv) {
		failed_already=1;
		goto exit_now;
	}
#endif  /* !_PR_DCETHREADS */
    rv = _PT_PTHREAD_CREATE(&threadID, attr, threadStartFunc, NULL);
    if (rv != 0) {
			fprintf(stderr, "thread creation failed: error code %d\n", rv);
			failed_already=1;
			goto exit_now;
	}
	else {
		if (debug_mode)
			printf ("thread creation succeeded \n");

	}
    rv = _PT_PTHREAD_ATTR_DESTROY(&attr);
    if (debug_mode) PR_ASSERT(0 == rv);
	else if (0 != rv) {
		failed_already=1;
		goto exit_now;
	}
    rv = pthread_join(threadID, NULL);
    if (debug_mode) PR_ASSERT(0 == rv);
	else if (0 != rv) {
		failed_already=1;
		goto exit_now;
	}

#elif defined(SOLARIS)

    rv = thr_create(NULL, 0, threadStartFunc, NULL, 0, &threadID);
    if (rv != 0) {
	if(!debug_mode) {
		failed_already=1;
		goto exit_now;
	} else	
		fprintf(stderr, "thread creation failed: error code %d\n", rv);
    }
    rv = thr_join(threadID, NULL, NULL);
    if (debug_mode) PR_ASSERT(0 == rv);
	else if (0 != rv)
	{
		failed_already=1;
		goto exit_now;
	}


#elif defined(WIN32)

    hThread = (HANDLE) _beginthreadex(NULL, 0, threadStartFunc, NULL,
            STACK_SIZE_PARAM_IS_A_RESERVATION, &threadID);
    if (hThread == 0) {
        fprintf(stderr, "thread creation failed: error code %d\n",
                GetLastError());
		failed_already=1;
		goto exit_now;
    }
    rv = WaitForSingleObject(hThread, INFINITE);
    if (debug_mode)PR_ASSERT(rv != WAIT_FAILED);
	else if (rv == WAIT_FAILED) {
		failed_already=1;
		goto exit_now;
	}

#elif defined(IRIX)

    threadID = sproc(threadStartFunc, PR_SALL, NULL);
    if (threadID == -1) {

			fprintf(stderr, "thread creation failed: error code %d\n",
					errno);
			failed_already=1;
			goto exit_now;
	
	}
	else {
		if (debug_mode) 
			printf ("thread creation succeeded \n");
		sleep(3);
		goto exit_now;
	}
    rv = waitpid(threadID, NULL, 0);
    if (debug_mode) PR_ASSERT(rv != -1);
	else  if (rv != -1) {
		failed_already=1;
		goto exit_now;
	}

#elif defined(OS2)

    threadID = (TID) _beginthread((void *)threadStartFunc, NULL,
            32768, NULL); 
    if (threadID == -1) {
        fprintf(stderr, "thread creation failed: error code %d\n", errno);
        failed_already=1;
        goto exit_now;
    }
    rv = DosWaitThread(&threadID, DCWW_WAIT);
    if (debug_mode) {
        PR_ASSERT(rv == NO_ERROR);
    } else if (rv != NO_ERROR) {
        failed_already=1;
        goto exit_now;
    }

#elif defined(XP_BEOS)
	
	threadID = spawn_thread(threadStartFunc, NULL, B_NORMAL_PRIORITY, NULL);
	if (threadID <= B_ERROR) {
		fprintf(stderr, "thread creation failed: error code %08lx\n", threadID);
		failed_already = 1;
		goto exit_now;
	}
	if (resume_thread(threadID) != B_OK) {
		fprintf(stderr, "failed starting thread: error code %08lx\n", threadID);
		failed_already = 1;
		goto exit_now;
	}

	waitRV = wait_for_thread(threadID, &threadRV);
	if (debug_mode)
		PR_ASSERT(waitRV == B_OK);
	else if (waitRV != B_OK) {
		failed_already = 1;
		goto exit_now;
	}
	
#else
	if (!debug_mode)
		failed_already=1;
	else	
		printf("The attach test does not apply to this platform because\n"
	    "either this platform does not have native threads or the\n"
	    "test needs to be written for this platform.\n");
	goto exit_now;
#endif

exit_now:
   if(failed_already)	
		return 1;
	else
		return 0;
}