22 */

23 if ((counter % 755) == 0) {

24 status = pthread_setcancelstate (

25 PTHREAD_CANCEL_DISABLE, &state);

26 if (status != 0)

27 err_abort (status, 'Disable cancel');

28 sleep (1);

29 status = pthread_setcancelstate (

30 state, &state);

31 if (status != 0)

32 err_abort (status, 'Restore cancel');

33 } else

34 if ((counter % 1000) == 0)

35 pthread_testcancel ();

36 }

37 }

38

39 int main (int argc, char *argv[])

40 {

41 pthread_t thread_id;

42 void *result;

43 int status;

44

45 status = pthread_create (

46 &thread_id, NULL, thread_routine, NULL);

47 if (status != 0)

48 err_abort (status, 'Create thread');

49 sleep (2);

50 status = pthread_cancel (thread_id);

51 if (status != 0)

52 err_abort (status, 'Cancel thread');

53

54 status = pthread_join (thread_id, &result);

55 if (status != 0)

56 err_abort (status, 'Join thread');

57 if (result == PTHREAD_CANCELED)

58 printf ('Thread canceled at iteration %d ', counter);

59 else

60 printf ('Thread was not canceled ');

61 return 0;

62 }

5.3.2 Asynchronous cancelability

Asynchronous cancellation is useful because the 'target thread' doesn't need to poll for cancellation requests by using cancellation points. That can be valuable for a thread that runs a tight compute-bound loop (for example, searching for a prime number factor) where the overhead of calling pthread_testcancel might be severe.

Avoid asynchronous cancellation! It is difficult to use correctly and is rarely useful.

The problem is that you're limited in what you can do with asynchronous cancellation enabled. You can't acquire any resources, for example, including locking a mutex. That's because the cleanup code would have no way to determine

whether the mutex had been locked. Asynchronous cancellation can occur at any hardware instruction. On some computers it may even be possible to interrupt some instructions in the middle. That makes it really difficult to determine what the canceled thread was doing.

For example, when you call malloc the system allocates some heap memory for you, stores a pointer to that memory somewhere (possibly in a hardware register), and then returns to your code, which probably moves the return value into some local storage for later use. There are lots of places that malloc might be interrupted by an asynchronous cancel, with varying effects. It might be interrupted before the memory was allocated. Or it might be interrupted after allocating storage but before it stored the address for return. Or it might even return to your code, but get interrupted before the return value could be copied to a local variable. In any of those cases the variable where your code expects to find a pointer to the allocated memory will be uninitialized. You can't tell whether the memory really was allocated yet. You can't free the memory, so that memory (if it was allocated to you) will remain allocated for the life of the program. That's a memory leak, which is not a desirable feature.

Or when you call pthread_mutex_lock, the system might be interrupted within a function call either before or after locking the mutex. Again, there's no way for your program to find out, because the interrupt may have occurred between any two instructions, even within the pthread_mutex_lock function, which might leave the mutex unusable. If the mutex is locked, the application will likely end up hanging because it will never be unlocked.

Call no code with asynchronous cancellation enabled unless you wrote it to be async-cancel safe — and even then, think twice!

You are not allowed to call any function that acquires resources while asynchronous cancellation is enabled. In fact, you should never call any function while asynchronous cancellation is enabled unless the function is documented as 'async-cancel safe.' The only functions required to be async safe by Pthreads are pthread_cancel, pthread_setcancelstate, and pthread_setcanceltype. (And there is no reason to call pthread_cancel with asynchronous cancelability enabled.) No other POSIX orANSI C functions need be async-cancel safe, and you should never call them with asynchronous cancelability enabled.

Pthreads suggests that all library functions should document whether or not they are async-cancel safe. However if the description of a function does not specifically say it is async-cancel safe you should always assume that it is not. The consequences of asynchronous cancellation in a function that is not async-cancel safe can be severe. And worse, the effects are sensitive to timing — so a function that appears to be async-cancel safe during experimentation may in fact cause all sorts of problems later when it ends up being canceled in a slightly different place.

The following program, cancel_async.c, shows the use of asynchronous cancellation in a compute-bound loop. Use of asynchronous cancellation makes this

loop 'more responsive' than the deferred cancellation loop in cancel.c. However, the program would become unreliable if any function calls were made within the loop, whereas the deferred cancellation version would continue to function correctly. In most cases, synchronous cancellation is preferable.

24-28 To keep the thread running awhile with something more interesting than an empty loop, cancel_async.c uses a simple matrix multiply nested loop. The matrixa and matrixb arrays are initialized with, respectively, their major or minor array index.

34-36 The cancellation type is changed to PTHREAD_CANCEL_ASYNCHRONOUS, allowing asynchronous cancellation within the matrix multiply loops.

39-44 The thread repeats the matrix multiply until canceled, on each iteration replacing the first source array (matrixa) with the result of the previous multiplication (matrixc).

66-74 Once again, on a Solaris system, set the thread concurrency level to 2, allowing the main thread and thread_routine to run concurrently on a uniprocessor. The program will hang without this step,

Добавить отзыв
ВСЕ ОТЗЫВЫ О КНИГЕ В ИЗБРАННОЕ

0

Вы можете отметить интересные вам фрагменты текста, которые будут доступны по уникальной ссылке в адресной строке браузера.

Отметить Добавить цитату