Пример #1
0
__pthread_manager(void *arg)
{
  pthread_descr self = manager_thread = arg;
  int reqfd = __pthread_manager_reader;
  struct pollfd ufd;
  sigset_t manager_mask;
  int n;
  struct pthread_request request;

  /* If we have special thread_self processing, initialize it.  */
#ifdef INIT_THREAD_SELF
  INIT_THREAD_SELF(self, 1);
#endif
#if !(USE_TLS && HAVE___THREAD)
  /* Set the error variable.  */
  self->p_errnop = &self->p_errno;
  self->p_h_errnop = &self->p_h_errno;
#endif
  /* Block all signals except __pthread_sig_cancel and SIGTRAP */
  sigfillset(&manager_mask);
  sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
  sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
  if (__pthread_threads_debug && __pthread_sig_debug > 0)
    sigdelset(&manager_mask, __pthread_sig_debug);
  sigprocmask(SIG_SETMASK, &manager_mask, NULL);
  /* Raise our priority to match that of main thread */
  __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
  /* Synchronize debugging of the thread manager */
  n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request,
					 sizeof(request)));
  ASSERT(n == sizeof(request) && request.req_kind == REQ_DEBUG);
  ufd.fd = reqfd;
  ufd.events = POLLIN;
  /* Enter server loop */
  while(1) {
    n = __poll(&ufd, 1, 2000);

    /* Check for termination of the main thread */
    if (getppid() == 1) {
      pthread_kill_all_threads(SIGKILL, 0);
      _exit(0);
    }
    /* Check for dead children */
    if (terminated_children) {
      terminated_children = 0;
      pthread_reap_children();
    }
    /* Read and execute request */
    if (n == 1 && (ufd.revents & POLLIN)) {
      n = TEMP_FAILURE_RETRY(read_not_cancel(reqfd, (char *)&request,
					     sizeof(request)));
#ifdef DEBUG
      if (n < 0) {
	char d[64];
	write(STDERR_FILENO, d, snprintf(d, sizeof(d), "*** read err %m\n"));
      } else if (n != sizeof(request)) {
	write(STDERR_FILENO, "*** short read in manager\n", 26);
      }
#endif

      switch(request.req_kind) {
      case REQ_CREATE:
        request.req_thread->p_retcode =
          pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
                                request.req_args.create.attr,
                                request.req_args.create.fn,
                                request.req_args.create.arg,
                                &request.req_args.create.mask,
                                request.req_thread->p_pid,
				request.req_thread->p_report_events,
				&request.req_thread->p_eventbuf.eventmask);
        restart(request.req_thread);
        break;
      case REQ_FREE:
	pthread_handle_free(request.req_args.free.thread_id);
        break;
      case REQ_PROCESS_EXIT:
        pthread_handle_exit(request.req_thread,
                            request.req_args.exit.code);
	/* NOTREACHED */
        break;
      case REQ_MAIN_THREAD_EXIT:
        main_thread_exiting = 1;
	/* Reap children in case all other threads died and the signal handler
	   went off before we set main_thread_exiting to 1, and therefore did
	   not do REQ_KICK. */
	pthread_reap_children();

        if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
          restart(__pthread_main_thread);
	  /* The main thread will now call exit() which will trigger an
	     __on_exit handler, which in turn will send REQ_PROCESS_EXIT
	     to the thread manager. In case you are wondering how the
	     manager terminates from its loop here. */
	}
        break;
      case REQ_POST:
        sem_post(request.req_args.post);
        break;
      case REQ_DEBUG:
	/* Make gdb aware of new thread and gdb will restart the
	   new thread when it is ready to handle the new thread. */
	if (__pthread_threads_debug && __pthread_sig_debug > 0)
	  raise(__pthread_sig_debug);
        break;
      case REQ_KICK:
	/* This is just a prod to get the manager to reap some
	   threads right away, avoiding a potential delay at shutdown. */
	break;
      case REQ_FOR_EACH_THREAD:
	pthread_for_each_thread(request.req_args.for_each.arg,
	                        request.req_args.for_each.fn);
	restart(request.req_thread);
	break;
      }
    }
  }
}
Пример #2
0
int attribute_noreturn __pthread_manager(void *arg)
{
  int reqfd = (int) (long int) arg;
#ifdef USE_SELECT
  struct timeval tv;
  fd_set fd;
#else
  struct pollfd ufd;
#endif
  sigset_t manager_mask;
  int n;
  struct pthread_request request;

  /* If we have special thread_self processing, initialize it.  */
#ifdef INIT_THREAD_SELF
  INIT_THREAD_SELF(&__pthread_manager_thread, 1);
#endif
  /* Set the error variable.  */
  __pthread_manager_thread.p_errnop = &__pthread_manager_thread.p_errno;
  __pthread_manager_thread.p_h_errnop = &__pthread_manager_thread.p_h_errno;

#ifdef __UCLIBC_HAS_XLOCALE__
  /* Initialize thread's locale to the global locale. */
  __pthread_manager_thread.locale = __global_locale;
#endif /* __UCLIBC_HAS_XLOCALE__ */

  /* Block all signals except __pthread_sig_cancel and SIGTRAP */
  __sigfillset(&manager_mask);
  sigdelset(&manager_mask, __pthread_sig_cancel); /* for thread termination */
  sigdelset(&manager_mask, SIGTRAP);            /* for debugging purposes */
  if (__pthread_threads_debug && __pthread_sig_debug > 0)
      sigdelset(&manager_mask, __pthread_sig_debug);
  sigprocmask(SIG_SETMASK, &manager_mask, NULL);
  /* Raise our priority to match that of main thread */
  __pthread_manager_adjust_prio(__pthread_main_thread->p_priority);
  /* Synchronize debugging of the thread manager */
  n = TEMP_FAILURE_RETRY(read(reqfd, (char *)&request,
				     sizeof(request)));
#ifndef USE_SELECT
  ufd.fd = reqfd;
  ufd.events = POLLIN;
#endif
  /* Enter server loop */
  while(1) {
#ifdef USE_SELECT
    tv.tv_sec = 2;
    tv.tv_usec = 0;
    FD_ZERO (&fd);
    FD_SET (reqfd, &fd);
    n = select (reqfd + 1, &fd, NULL, NULL, &tv);
#else
    PDEBUG("before poll\n");
    n = poll(&ufd, 1, 2000);
    PDEBUG("after poll\n");
#endif
    /* Check for termination of the main thread */
    if (getppid() == 1) {
      pthread_kill_all_threads(SIGKILL, 0);
      _exit(0);
    }
    /* Check for dead children */
    if (terminated_children) {
      terminated_children = 0;
      pthread_reap_children();
    }
    /* Read and execute request */
#ifdef USE_SELECT
    if (n == 1)
#else
    if (n == 1 && (ufd.revents & POLLIN))
#endif
    {

      PDEBUG("before read\n");
      n = read(reqfd, (char *)&request, sizeof(request));
      PDEBUG("after read, n=%d\n", n);
      switch(request.req_kind) {
      case REQ_CREATE:
        PDEBUG("got REQ_CREATE\n");
        request.req_thread->p_retcode =
          pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
                                request.req_args.create.attr,
                                request.req_args.create.fn,
                                request.req_args.create.arg,
                                &request.req_args.create.mask,
                                request.req_thread->p_pid,
                                request.req_thread->p_report_events,
                                &request.req_thread->p_eventbuf.eventmask);
        PDEBUG("restarting %p\n", request.req_thread);
        restart(request.req_thread);
        break;
      case REQ_FREE:
        PDEBUG("got REQ_FREE\n");
        pthread_handle_free(request.req_args.free.thread_id);
        break;
      case REQ_PROCESS_EXIT:
        PDEBUG("got REQ_PROCESS_EXIT from %p, exit code = %d\n",
        request.req_thread, request.req_args.exit.code);
        pthread_handle_exit(request.req_thread,
                            request.req_args.exit.code);
        break;
      case REQ_MAIN_THREAD_EXIT:
        PDEBUG("got REQ_MAIN_THREAD_EXIT\n");
        main_thread_exiting = 1;
	/* Reap children in case all other threads died and the signal handler
	   went off before we set main_thread_exiting to 1, and therefore did
	   not do REQ_KICK. */
	pthread_reap_children();

        if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
          restart(__pthread_main_thread);
	  /* The main thread will now call exit() which will trigger an
	     __on_exit handler, which in turn will send REQ_PROCESS_EXIT
	     to the thread manager. In case you are wondering how the
	     manager terminates from its loop here. */
	}
        break;
      case REQ_POST:
        PDEBUG("got REQ_POST\n");
        sem_post(request.req_args.post);
        break;
      case REQ_DEBUG:
        PDEBUG("got REQ_DEBUG\n");
	/* Make gdb aware of new thread and gdb will restart the
	   new thread when it is ready to handle the new thread. */
	if (__pthread_threads_debug && __pthread_sig_debug > 0) {
	  PDEBUG("about to call raise(__pthread_sig_debug)\n");
	  raise(__pthread_sig_debug);
	}
      case REQ_KICK:
	/* This is just a prod to get the manager to reap some
	   threads right away, avoiding a potential delay at shutdown. */
	break;
      }
    }
  }
}
Пример #3
0
int __pthread_manager(void * arg)
{
  int reqfd = (int) arg;
  sigset_t mask;
  fd_set readfds;
  struct timeval timeout;
  int n;
  struct pthread_request request;

  /* If we have special thread_self processing, initialize it.  */
#ifdef INIT_THREAD_SELF
  INIT_THREAD_SELF(&__pthread_manager_thread);
#endif
  /* Block all signals except PTHREAD_SIG_RESTART */
  sigfillset(&mask);
  sigdelset(&mask, PTHREAD_SIG_RESTART);
  sigprocmask(SIG_SETMASK, &mask, NULL);
  /* Enter server loop */
  while(1) {
    FD_ZERO(&readfds);
    FD_SET(reqfd, &readfds);
    timeout.tv_sec = 2;
    timeout.tv_usec = 0;
    n = select(FD_SETSIZE, &readfds, NULL, NULL, &timeout);
    /* Check for termination of the main thread */
    if (getppid() == 1) {
      pthread_kill_all_threads(SIGKILL, 0);
      _exit(0);
    }
    /* Check for dead children */
    if (terminated_children) {
      terminated_children = 0;
      pthread_reap_children();
    }
    /* Read and execute request */
    if (n == 1 && FD_ISSET(reqfd, &readfds)) {
      n = read(reqfd, (char *)&request, sizeof(request));
      ASSERT(n == sizeof(request));
      switch(request.req_kind) {
      case REQ_CREATE:
        request.req_thread->p_retcode =
          pthread_handle_create((pthread_t *) &request.req_thread->p_retval,
                                request.req_args.create.attr,
                                request.req_args.create.fn,
                                request.req_args.create.arg,
                                &request.req_args.create.mask,
                                request.req_thread->p_pid);
        restart(request.req_thread);
        break;
      case REQ_FREE:
        pthread_handle_free(request.req_args.free.thread);
        break;
      case REQ_PROCESS_EXIT:
        pthread_handle_exit(request.req_thread,
                            request.req_args.exit.code);
        break;
      case REQ_MAIN_THREAD_EXIT:
        main_thread_exiting = 1;
        if (__pthread_main_thread->p_nextlive == __pthread_main_thread) {
          restart(__pthread_main_thread);
          return 0;
        }
        break;
      }
    }
  }
}