Example #1
0
static inline nc_thread_descriptor_t *nc_get_tdb(void) {
  /*
   * Fetch the thread-specific data pointer.  This is usually just
   * a wrapper around __libnacl_irt_tls.tls_get() but we don't use
   * that here so that the IRT build can override the definition.
   */
  return (void *) ((char *) __nacl_read_tp() + __nacl_tp_tdb_offset(TDB_SIZE));
}
Example #2
0
static void nacl_irt_thread_exit(int32_t *stack_flag) {
  struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp());

  __nc_tsd_exit();

  /*
   * Sanity check: Check that this function was not called on a thread
   * created by the IRT's internal pthread_create().  For such
   * threads, irt_thread_data == NULL.
   */
  assert(tdb->tdb.irt_thread_data != NULL);

  free(tdb->tdb.irt_thread_data);

  NACL_SYSCALL(thread_exit)(stack_flag);
  while (1) *(volatile int *) 0 = 0;  /* Crash.  */
}
Example #3
0
/*
 * This is the real first entry point for new threads.
 */
static void irt_start_thread(void) {
  struct nc_combined_tdb *tdb = get_irt_tdb(__nacl_read_tp());

  /*
   * Fetch the user's start routine.
   */
  void (*user_start)(void) = (void (*)(void)) tdb->tdb.start_func;

  /*
   * Now do per-thread initialization for the IRT-private C library state.
   */
  __newlib_thread_init();

  /*
   * Finally, run the user code.
   */
  (*user_start)();

  /*
   * That should never return.  Crash hard if it does.
   */
  while (1) *(volatile int *) 0 = 0;  /* Crash.  */
}