RU/2: Форум. Общение пользователей и разработчиков OS/2 (eCS). : Multithreading (XII)


Список сообщений | Написать новое | Ответить на сообщение | Домой Поиск:
Предыдущее сообщение | Следующее сообщение
From : ???
To : All
Subj : Multithreading (XII)

The OS/2 APIs DosWaitThread, DosEnterCritSec, and DosExitCritSec

1. DosWaitThread()

It has two basic modes of operation. This function allows a thread to wait or check
for completion of another thread.
Places the current thread into a wait state until another thread in the
current process has ended. It then returns the thread identifier of the ending
thread. It can wait for a specific thread, by specifying the thread's ID, or it can wait
for any thread termiantion in the process, by spcifying 0 for the tread ID.


Syntax:

#define INCL_DOSPROCESS
#include <os2.h>

PTID ptid; /* Address of the thread identification. */
ULONG option; /* An indicator that specifies whether to return if no thread has ended. */
APIRET ulrc; /* Return Code. */

ulrc = DosWaitThread(ptid, option);

Prototype:

APIRET DosWaitThread(PTID ptid, Ulong option);


Parameters:

ptid (PTID) - in/out - Address of the thread identification.


Input - The address of the ThreadID of the thread of interest. If ptid
is 0, the current thread waits until the next thread in the
process has ended. If ptid is nonzero, the current thread waits
until the indicated thread has ended.

Output - The ThreadID of the ended thread is returned in this field.

option (ULONG) - input
An indicator that specifies whether to return if no thread has ended.

The values of this field are shown in the following list:

0 - DCWW_WAIT
The current thread waits until a thread ends. If a thread has
already ended, the call returns immediately with the ptid.

1 - DCWW_NOWAIT
The current thread does not wait if no threads have ended.

ulrc (APIRET) - returns : Return Code.

DosWaitThread returns one of the following values:

0 NO_ERROR
95 ERROR_INTERRUPT
294 ERROR_THREAD_NOT_TERMINATED
309 ERROR_INVALID_THREADID

Remarks:

DosWaitThread is used to wait for termination of threads within a process. It
is usually used so that thread resources (for example, the stack) can be
recovered when a thread ends.

DosWaitThread waits on any thread within the current process, or on a specific thread within the process, based on the ptid parameter's contents. option allows the caller the option of waiting until a thread ends, or getting immediate return and status.

If no thread has ended and the DCWW_NOWAIT option is specified, the ptid field is preserved.

If DosWaitThread is called with the input ptid set to the current thread (the
thread attempts to wait on its own termination), the ERROR_INVALID_THREADID error
code is returned.

ERROR_INVALID_THREADID is also returned if a caller attempts to wait on the termination
of the thread with a ptid of 1.

Example:

This example creates a new thread within a process, sleeps for 1 second,
suspends the thread for 5 seconds, and then waits for the thread to
terminate.

Compile this example with MULTITHREAD LIBRARIES. If you are using C/2,
use the /Gm+ switch.

#define INCL_DOSPROCESS /* Process and thread values */
#define INCL_DOSERRORS /* DOS error values */
#include <os2.h>
#include <stdio.h>

void _System CntThreadProc(ULONG LoopMax); /* Count Thread */

int main(VOID) {


TID tidCntThread = 0; /* ID returned for newly created thread */
PFNTHREAD pfnCntThread = &CntThreadProc; /* Address of thread program */
ULONG ulThreadParm = 100; /* Parameter to thread routine */
APIRET rc = NO_ERROR; /* Return code */

rc = DosCreateThread(&tidCntThread, /* Thread ID (returned by function) */
pfnCntThread, /* Address of thread program */
ulThreadParm, /* Parameter passed to ThreadProc */
CREATE_READY | /* Thread is ready when created */
STACK_SPARSE, /* Do not pre-commit stack pages */
8192L); /* Stack size, rounded to page bdy */

if (rc != NO_ERROR) {

printf("DosCreateThread error: return code = %u\n", rc);
return 1;
}

rc = DosSleep (1000); /* Sleep for a second to allow thread to run a bit */
rc = DosSuspendThread (tidCntThread);

if (rc != NO_ERROR) {

printf("DosSuspendThread error: return code = %u\n", rc);
return 1;
}

rc = DosSleep (5000); /* Sleep 5 seconds before resuming the thread */

rc = DosResumeThread (tidCntThread);

if (rc != NO_ERROR) {

printf("DosResumeThread error: return code = %u\n", rc);
return 1;
}

rc = DosWaitThread (&tidCntThread, DCWW_WAIT);

if (rc != NO_ERROR) {
printf ("DosWaitThread error : return code = %u\n", rc);
}

printf ("Thread has completed!\n");

return NO_ERROR;
}

void _System CntThreadProc(ULONG LoopMax ) /* Count thread */
{
ULONG i = 0; /* Loop index */

for (i=0;i < LoopMax;i++ ) {
printf ("%d\n", i);
}

return;
}


2. DosEnterCritSec()

The DosEnterCritSec() function disables all thread rescheduling for the current process.

Syntax:

#define INCL_DOSPROCESS
#include <os2.h>

APIRET ulrc; /* Return Code. */

ulrc = DosEnterCritSec();

Prototype:

APIRET DosEnterCritSec(void);


Parameters:

ulrc (APIRET) - returns: Return Code.

DosEnterCritSec returns one of the following values:

0 NO_ERROR
309 ERROR_INVALID_THREADID
484 ERROR_CRITSEC_OVERFLOW

Remarks:

DosEnterCritSec causes all other threads in the process to block themselves
and give up their time slice.

After a DosEnterCritSec request is made, no functions should be called that depend on another thread to do processing until DosExitCritSec has completed.

!! Great care should be taken when using compiler runtime functions and other OS/2 functions after a DosEnterCritSec request has been made, since the underlying processing of the called function may require processing by another thread and thus cause a
deadlock. !!

A thread can also execute code without having to give up time slices to other threads in
its process if it requests a priority class that is higher than those of the other threads. A
thread's priority is examined with DosGetInfoBlocks, and changed with DosSetPriority.

A count is maintained of the number of times DosEnterCritSec is issued without a corresponding DosExitCritSec. The count is incremented by DosEnterCritSec and decremented by DosExitCritSec.

Normal thread dispatching is not restored until the count is zero. The outstanding
DosEnterCritSec count is maintained in a word. If an overflow occurs, the count is set to
the maximum value, no operation is performed, and the request returns with ERROR_CRITSEC_OVERFLOW.

If a signal occurs, thread 1 begins execution to process the signal even though another thread in the process has a DosEnterCritSec active. Thread 1 of a process is its initial
thread of execution, not a thread created with DosCreateThread.

Any processing done by thread 1 to satisfy the signal must not include accessing the
critical resource intended to be protected by DosEnterCritSec.

There is one exception to the exclusivity of critical sections. If a signal occurs, thread 1
will be allowed to execute its exception handling code even if another thread in the
same process is in a critical section. For this reason, execption handling code must be
carefully written to avoid performing any operations that might interfere with a thread
in a critical section.

Note: This function is very powerful and must be used with caution!

It should be used only in a most cooperative environment where the state of all threads in known. While in the critical section, do not call other compiler runtime or OS/2 functions that could start another thread that it would depend on running before being able to
return.

DosQueryThreadContext can be used to obtain the context of other threads in the process
once they have been blocked by DosEnterCritSec.

Calls to DosEnterCritSec() can be nested. Thus, if three calls to DosEnterCritSec() are
issued, three calls to DosExitSec() must be issued to reenable scheduling.


ERROR_INVALID_THREADID is returned when an invalid attempt is made to enter a critical section of code in a signal handler or exception handler.

ERROR_INVALID_THREADID is also returned when a dynamic link library (DLL) routine incorrectly issues DosEnterCritSec.

Example:


/* This example shows how a thread enters and exits a critical section of code. */

#define INCL_DOSPROCESS /* Process values */
#define INCL_DOSERRORS /* Error values */
#include <os2.h>
#include <stdio.h>

int main(VOID)

{

APIRET rc = NO_ERROR; /* Return code */

rc = DosEnterCritSec();

if (rc != NO_ERROR) {

printf("DosEnterCritSec error: return code = %u\n",rc);
return 1;
}

/***********************************************/
/* Add critical section code here. While this */
/* code is running, all other threads are */
/* stopped. CALL NO LIBRARY OR OS/2 FUNCTIONS */
/* HERE UNLESS YOU KNOW THEY DO NOT REQUIRE */
/* ACTION BY ANOTHER THREAD IN THE PROCESS. */
/***********************************************/

rc = DosExitCritSec();

if (rc != NO_ERROR) {

printf("DosExitCritSec error: return code = %u\n",rc);
return 1;
}

return NO_ERROR;
}


3. DosExitCritSec()

Syntax:

Restores normal thread dispatching for the current process.

#define INCL_DOSPROCESS
#include <os2.h>

APIRET ulrc; /* Return Code. */

ulrc = DosExitCritSec();

Prototype:

APIRET DosExitCritSec(void);

Parameters:

ulrc (APIRET) - returns : Return Code.

DosExitCritSec returns one of the following values:

0 NO_ERROR
309 ERROR_INVALID_THREADID
485 ERROR_CRITSEC_UNDERFLOW

Remarks:

DosExitCritSec is used following DosEnterCritSec to restore normal thread
switching to the threads of a process.

A count is maintained of the number of times DosEnterCritSec is issued
without a corresponding DosExitCritSec. The count is incremented by
DosEnterCritSec, and decremented by DosExitCritSec. Normal thread
dispatching is not restored until the count is zero.

If multiple DosEnterCritSec() calls have been issued, then the same number of
DosExitCritSec() calls are required before scheduling actually will be enabled.

The outstanding count is maintained in a word. If an underflow occurs (the
count is decremented below zero), the count is set to zero, no operation is
performed, and the request returns with ERROR_CRITSEC_UNDERFLOW.

ERROR_INVALID_THREADID is returned when an invalid attempt is made to
exit a critical section of code in a signal handler or exception handler.

ERROR_INVALID_THREADID is also returned when a dynamic link library (DLL)
routine incorrectly issues DosExitCritSec.


Example:

See the example concerning DosEnterCritSec() above.

















Mon 26 Jan 2004 16:50 Mozilla/4.61 [en] (OS/2; U)




Programmed by Dmitri Maximovich, Dmitry I. Platonoff, Eugen Kuleshov.
25.09.99 (c) 1999, RU/2. All rights reserved.
Rewritten by Dmitry Ban. All rights ignored.