This is the mail archive of the ecos-discuss@sources.redhat.com mailing list for the eCos project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: waking a thread that's in select()?


Hi

There is a race condition in select which could be contributing to
your problem. Hugo has fixes this. Here is a patch which i am
using. An official patch will go into the anoncvs soon.

        Andrew

Index: select.c
===================================================================
RCS file: /cvs/ecos/ecos-opt/net/net/tcpip/current/src/lib/select.c,v
retrieving revision 1.2
diff -u -5 -p -c -r1.2 select.c
*** select.c	2000/07/21 21:34:38	1.2
--- select.c	2000/09/29 11:18:32
*************** _cyg_select(int nfd, fd_set *in, fd_set 
*** 100,116 ****
          then = 0;  // Compiler warnings :-(
          ticks = 0;
      }
      // Scan sets for possible I/O until something found, timeout or error.
      while (true) {
!         num = 0;  // Total file descriptors "ready"
          for (mode = 0;  mode < 3;  mode++) {
              if (selection[mode]) {
                  for (fd = 0;  fd < nfd;  fd++) {
                      if (FD_ISSET(fd, selection[mode])) {
                          if (getfp(fd, &fp)) {
                              errno = EBADF;
                              return -1;
                          }
                          if ((*fp->f_ops->fo_select)(fp, mode_type[mode])) {
                              FD_SET(fd, result[mode]);
                              num++;
--- 100,118 ----
          then = 0;  // Compiler warnings :-(
          ticks = 0;
      }
      // Scan sets for possible I/O until something found, timeout or error.
      while (true) {
!        num = 0;  // Total file descriptors "ready"
!        cyg_scheduler_lock();
          for (mode = 0;  mode < 3;  mode++) {
              if (selection[mode]) {
                  for (fd = 0;  fd < nfd;  fd++) {
                      if (FD_ISSET(fd, selection[mode])) {
                          if (getfp(fd, &fp)) {
                              errno = EBADF;
+ 			    cyg_scheduler_unlock();
                              return -1;
                          }
                          if ((*fp->f_ops->fo_select)(fp, mode_type[mode])) {
                              FD_SET(fd, result[mode]);
                              num++;
*************** _cyg_select(int nfd, fd_set *in, fd_set 
*** 118,127 ****
--- 120,130 ----
                      }
                  }
              }
          }
          if (num) {
+             cyg_scheduler_unlock();
              // Found something, update user's sets
              if (in) {
                  memcpy(in, &in_res, sizeof(in_res));
              }
              if (out) {
*************** _cyg_select(int nfd, fd_set *in, fd_set 
*** 132,153 ****
              }
              return num;
          }
          // Nothing found, see if we want to wait
          if (tv) {
!             if (ticks == 0) {
                  // Special case of "poll"
                  return 0;
              }
              flag = cyg_flag_timed_wait(&select_flag, wait_flag,
                                         CYG_FLAG_WAITMODE_OR,
                                         then);
          } else {
              // Wait forever (until something happens)
              flag = cyg_flag_wait(&select_flag, wait_flag,
                                   CYG_FLAG_WAITMODE_OR);
          }
          if (flag & SELECT_ABORT) {
              errno = EINTR;
              return -1;
          }
          if (!flag) {
--- 135,158 ----
              }
              return num;
          }
          // Nothing found, see if we want to wait
          if (tv) {
!                 if (ticks == 0) {
                  // Special case of "poll"
+                 cyg_scheduler_unlock();
                  return 0;
              }
              flag = cyg_flag_timed_wait(&select_flag, wait_flag,
                                         CYG_FLAG_WAITMODE_OR,
                                         then);
          } else {
              // Wait forever (until something happens)
              flag = cyg_flag_wait(&select_flag, wait_flag,
                                   CYG_FLAG_WAITMODE_OR);
          }
+         cyg_scheduler_unlock();
          if (flag & SELECT_ABORT) {
              errno = EINTR;
              return -1;
          }
          if (!flag) {







Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]