ioproc.c 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <thread.h>
  4. #include "threadimpl.h"
  5. enum
  6. {
  7. STACK = 8192,
  8. };
  9. void
  10. iointerrupt(Ioproc *io)
  11. {
  12. if(!io->inuse)
  13. return;
  14. threadint(io->tid);
  15. }
  16. static void
  17. xioproc(void *a)
  18. {
  19. Ioproc *io, *x;
  20. io = a;
  21. /*
  22. * first recvp acquires the ioproc.
  23. * second tells us that the data is ready.
  24. */
  25. for(;;){
  26. while(recv(io->c, &x) == -1)
  27. ;
  28. if(x == 0) /* our cue to leave */
  29. break;
  30. assert(x == io);
  31. /* caller is now committed -- even if interrupted he'll return */
  32. while(recv(io->creply, &x) == -1)
  33. ;
  34. if(x == 0) /* caller backed out */
  35. continue;
  36. assert(x == io);
  37. io->ret = io->op(&io->arg);
  38. if(io->ret < 0)
  39. rerrstr(io->err, sizeof io->err);
  40. while(send(io->creply, &io) == -1)
  41. ;
  42. while(recv(io->creply, &x) == -1)
  43. ;
  44. }
  45. }
  46. Ioproc*
  47. ioproc(void)
  48. {
  49. Ioproc *io;
  50. io = mallocz(sizeof(*io), 1);
  51. if(io == nil)
  52. sysfatal("ioproc malloc: %r");
  53. io->c = chancreate(sizeof(void*), 0);
  54. io->creply = chancreate(sizeof(void*), 0);
  55. io->tid = proccreate(xioproc, io, STACK);
  56. return io;
  57. }
  58. void
  59. closeioproc(Ioproc *io)
  60. {
  61. if(io == nil)
  62. return;
  63. iointerrupt(io);
  64. while(send(io->c, 0) == -1)
  65. ;
  66. chanfree(io->c);
  67. chanfree(io->creply);
  68. free(io);
  69. }