async.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. /***************************************************************************
  2. lib/async.c
  3. -------------------
  4. copyright : (C) 2002 by Frank Mori Hess
  5. email : fmhess@users.sourceforge.net
  6. ***************************************************************************/
  7. /***************************************************************************
  8. * *
  9. * This program is free software; you can redistribute it and/or modify *
  10. * it under the terms of the GNU General Public License as published by *
  11. * the Free Software Foundation; either version 2 of the License, or *
  12. * (at your option) any later version. *
  13. * *
  14. ***************************************************************************/
  15. #include "ib_internal.h"
  16. #include <sys/ioctl.h>
  17. #include <stdlib.h>
  18. #include <pthread.h>
  19. static void* do_aio( void *varg );
  20. struct gpib_aio_arg
  21. {
  22. int ud;
  23. ibConf_t *conf;
  24. int gpib_aio_type;
  25. };
  26. void init_async_op( struct async_operation *async )
  27. {
  28. pthread_mutex_init( &async->lock, NULL );
  29. pthread_mutex_init( &async->join_lock, NULL );
  30. pthread_cond_init(&async->condition, NULL);
  31. async->buffer = NULL;
  32. async->buffer_length = 0;
  33. async->iberr = 0;
  34. async->ibsta = 0;
  35. async->ibcntl = 0;
  36. async->in_progress = 0;
  37. async->abort = 0;
  38. }
  39. static void cleanup_aio( void *varg )
  40. {
  41. struct gpib_aio_arg arg = *((struct gpib_aio_arg*) varg);
  42. ibBoard_t *board = interfaceBoard(arg.conf);
  43. ibstatus( arg.conf, 0, 0, CMPL);
  44. int retval = unlock_board_mutex(board);
  45. assert(retval == 0);
  46. }
  47. int gpib_aio_launch( int ud, ibConf_t *conf, int gpib_aio_type,
  48. void *buffer, long cnt )
  49. {
  50. int retval;
  51. struct gpib_aio_arg *arg;
  52. pthread_attr_t attributes;
  53. arg = malloc( sizeof( *arg ) );
  54. if( arg == NULL )
  55. {
  56. setIberr( EDVR );
  57. setIbcnt( ENOMEM );
  58. return -1;
  59. }
  60. arg->ud = ud;
  61. arg->conf = conf;
  62. arg->gpib_aio_type = gpib_aio_type;
  63. pthread_mutex_lock( &conf->async.lock );
  64. if( conf->async.in_progress )
  65. {
  66. pthread_mutex_unlock( &conf->async.lock );
  67. setIberr( EOIP );
  68. return -1;
  69. }
  70. conf->async.ibsta = 0;
  71. conf->async.ibcntl = 0;
  72. conf->async.iberr = 0;
  73. conf->async.buffer = buffer;
  74. conf->async.buffer_length = cnt;
  75. conf->async.abort = 0;
  76. pthread_attr_init( &attributes );
  77. pthread_attr_setstacksize( &attributes, 0x10000 );
  78. retval = pthread_create( &conf->async.thread,
  79. &attributes, do_aio, arg );
  80. pthread_attr_destroy( &attributes );
  81. conf->async.in_progress = (retval == 0);
  82. pthread_cond_wait(&conf->async.condition, &conf->async.lock);
  83. pthread_mutex_unlock( &conf->async.lock );
  84. if( retval )
  85. {
  86. free( arg ); arg = NULL;
  87. setIberr( EDVR );
  88. setIbcnt( retval );
  89. return -1;
  90. }
  91. return 0;
  92. }
  93. static void* do_aio( void *varg )
  94. {
  95. size_t count;
  96. struct gpib_aio_arg arg;
  97. ibConf_t *conf;
  98. ibBoard_t *board;
  99. int retval;
  100. arg = *((struct gpib_aio_arg*) varg);
  101. free( varg ); varg = NULL;
  102. conf = arg.conf;
  103. board = interfaceBoard(conf);
  104. retval = lock_board_mutex(board);
  105. if(retval == 0)
  106. {
  107. ibstatus(conf, 0, CMPL, 0);
  108. }
  109. pthread_mutex_lock(&conf->async.lock);
  110. pthread_cond_broadcast(&conf->async.condition);
  111. pthread_mutex_unlock(&conf->async.lock);
  112. if( retval < 0 ) return NULL;
  113. pthread_cleanup_push( cleanup_aio, &arg );
  114. pthread_setcanceltype( PTHREAD_CANCEL_ASYNCHRONOUS, NULL );
  115. pthread_setcancelstate( PTHREAD_CANCEL_ENABLE, NULL );
  116. switch( arg.gpib_aio_type )
  117. {
  118. case GPIB_AIO_COMMAND:
  119. count = retval = my_ibcmd( conf, conf->async.buffer, conf->async.buffer_length );
  120. break;
  121. case GPIB_AIO_READ:
  122. retval = my_ibrd( conf, conf->async.buffer, conf->async.buffer_length, &count);
  123. break;
  124. case GPIB_AIO_WRITE:
  125. retval = my_ibwrt(conf, conf->async.buffer, conf->async.buffer_length, &count);
  126. break;
  127. default:
  128. retval = -1;
  129. fprintf( stderr, "libgpib: bug! in %s\n", __FUNCTION__ );
  130. break;
  131. }
  132. pthread_setcancelstate( PTHREAD_CANCEL_DISABLE, NULL );
  133. pthread_mutex_lock( &conf->async.lock );
  134. if(retval < 0)
  135. {
  136. if(ThreadIberr() != EDVR)
  137. conf->async.ibcntl = count;
  138. else
  139. conf->async.ibcntl = ThreadIbcntl();
  140. conf->async.iberr = ThreadIberr();
  141. conf->async.ibsta = CMPL | ERR;
  142. }else
  143. {
  144. conf->async.ibcntl = count;
  145. conf->async.iberr = 0;
  146. conf->async.ibsta = CMPL;
  147. }
  148. pthread_mutex_unlock( &conf->async.lock );
  149. pthread_cleanup_pop( 1 );
  150. return NULL;
  151. }
  152. int gpib_aio_join( struct async_operation *async )
  153. {
  154. int retval;
  155. pthread_mutex_lock( &async->join_lock );
  156. retval = pthread_join( async->thread, NULL );
  157. switch( retval )
  158. {
  159. case 0:
  160. break;
  161. case ESRCH: /* thread has already been joined */
  162. retval = 0;
  163. break;
  164. default:
  165. fprintf( stderr, "libgpib: pthread_join() returned %i in %s\n",
  166. retval, __FUNCTION__ );
  167. setIberr( EDVR );
  168. setIbcnt( retval );
  169. break;
  170. }
  171. pthread_mutex_unlock( &async->join_lock );
  172. return retval;
  173. }