Esempio n. 1
0
/* Do some minimal initialization which has to be done during the
   startup of the C library.  */
void
__pthread_initialize_minimal(void)
{
#ifdef USE_TLS
  pthread_descr self;

  /* First of all init __pthread_handles[0] and [1] if needed.  */
# if __LT_SPINLOCK_INIT != 0
  __pthread_handles[0].h_lock = __LOCK_INITIALIZER;
  __pthread_handles[1].h_lock = __LOCK_INITIALIZER;
# endif
# ifndef SHARED
  /* Unlike in the dynamically linked case the dynamic linker has not
     taken care of initializing the TLS data structures.  */
  __libc_setup_tls (TLS_TCB_SIZE, TLS_TCB_ALIGN);
# elif !USE___THREAD
  if (__builtin_expect (GL(dl_tls_dtv_slotinfo_list) == NULL, 0))
    {
      tcbhead_t *tcbp;

      /* There is no actual TLS being used, so the thread register
	 was not initialized in the dynamic linker.  */

      /* We need to install special hooks so that the malloc and memalign
	 calls in _dl_tls_setup and _dl_allocate_tls won't cause full
	 malloc initialization that will try to set up its thread state.  */

      extern void __libc_malloc_pthread_startup (bool first_time);
      __libc_malloc_pthread_startup (true);

      if (__builtin_expect (_dl_tls_setup (), 0)
	  || __builtin_expect ((tcbp = _dl_allocate_tls (NULL)) == NULL, 0))
	{
	  static const char msg[] = "\
cannot allocate TLS data structures for initial thread\n";
	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
						msg, sizeof msg - 1));
	  abort ();
	}
      const char *lossage = TLS_INIT_TP (tcbp, 0);
      if (__builtin_expect (lossage != NULL, 0))
	{
	  static const char msg[] = "cannot set up thread-local storage: ";
	  const char nl = '\n';
	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
						msg, sizeof msg - 1));
	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO,
						lossage, strlen (lossage)));
	  TEMP_FAILURE_RETRY (write_not_cancel (STDERR_FILENO, &nl, 1));
	}

      /* Though it was allocated with libc's malloc, that was done without
	 the user's __malloc_hook installed.  A later realloc that uses
	 the hooks might not work with that block from the plain malloc.
	 So we record this block as unfreeable just as the dynamic linker
	 does when it allocates the DTV before the libc malloc exists.  */
      GL(dl_initial_dtv) = GET_DTV (tcbp);

      __libc_malloc_pthread_startup (false);
    }
Esempio n. 2
0
internal_function
init_tls (void)
{
	/* Number of elements in the static TLS block.  */
	_dl_tls_static_nelem = _dl_tls_max_dtv_idx;

	/* Do not do this twice.  The audit interface might have required
	   the DTV interfaces to be set up early.  */
	if (_dl_initial_dtv != NULL)
		return NULL;

	/* Allocate the array which contains the information about the
	   dtv slots.  We allocate a few entries more than needed to
	   avoid the need for reallocation.  */
	size_t nelem = _dl_tls_max_dtv_idx + 1 + TLS_SLOTINFO_SURPLUS;

	/* Allocate.  */
	_dl_assert (_dl_tls_dtv_slotinfo_list == NULL);
	_dl_tls_dtv_slotinfo_list = (struct dtv_slotinfo_list *)
		_dl_calloc (sizeof (struct dtv_slotinfo_list)
			+ nelem * sizeof (struct dtv_slotinfo), 1);
	/* No need to check the return value.  If memory allocation failed
	   the program would have been terminated.  */

	struct dtv_slotinfo *slotinfo = _dl_tls_dtv_slotinfo_list->slotinfo;
	_dl_tls_dtv_slotinfo_list->len = nelem;
	_dl_tls_dtv_slotinfo_list->next = NULL;

	/* Fill in the information from the loaded modules.  No namespace
	   but the base one can be filled at this time.  */
	int i = 0;
	struct link_map *l;
	for (l =  (struct link_map *) _dl_loaded_modules; l != NULL; l = l->l_next)
		if (l->l_tls_blocksize != 0)
		{
			/* This is a module with TLS data.  Store the map reference.
			   The generation counter is zero.  */

			/* Skeep slot[0]: it will be never used */
			slotinfo[++i].map = l;
		}
	_dl_assert (i == _dl_tls_max_dtv_idx);

	/* Compute the TLS offsets for the various blocks.  */
	_dl_determine_tlsoffset ();

	/* Construct the static TLS block and the dtv for the initial
	   thread.  For some platforms this will include allocating memory
	   for the thread descriptor.  The memory for the TLS block will
	   never be freed.  It should be allocated accordingly.  The dtv
	   array can be changed if dynamic loading requires it.  */
	void *tcbp = _dl_allocate_tls_storage ();
	if (tcbp == NULL) {
		_dl_debug_early("\ncannot allocate TLS data structures for initial thread");
		_dl_exit(30);
	}

	/* Store for detection of the special case by __tls_get_addr
	   so it knows not to pass this dtv to the normal realloc.  */
	_dl_initial_dtv = GET_DTV (tcbp);

	/* And finally install it for the main thread.  If ld.so itself uses
	   TLS we know the thread pointer was initialized earlier.  */
	const char *lossage = TLS_INIT_TP (tcbp, USE___THREAD);
	if(__builtin_expect (lossage != NULL, 0)) {
		_dl_debug_early("cannot set up thread-local storage: %s\n", lossage);
		_dl_exit(30);
	}
	tls_init_tp_called = true;

	return tcbp;
}
Esempio n. 3
0
void
_start(void)
{
	// WARNING: __hart_self_on_entry must be read before
	// anything is register-allocated!
	int id = __hart_self_on_entry;
	static int init = 0;
	// For dynamically-linked programs, the first time through,
	// __hart_self_on_entry could be clobbered (on x86), because
	// the linker will have overwritten eax.  Happily, the first
	// time through, we know we are vcore 0.  Subsequent entries
	// into this routine do not have this problem.
	if(init == 0)
		id = 0;
	
	// threads besides thread 0 must acquire a TCB.
	if(id != 0)
	{
		TLS_INIT_TP(__hart_thread_control_blocks[id],0);
		hart_entry();
		hart_yield();
		failmsg("why did hart_yield() return?");
		goto diediedie;
	}

	if(init)
	{
		failmsg("why did thread 0 re-enter _start?");
		goto diediedie;
	}
	init = 1;

	extern int main(int,char**,char**);
	extern void __libc_csu_init(int,char**,char**);
	extern void __libc_csu_fini(void);
	extern void __libc_start_main(typeof(&main),int,char**,
	              typeof(&__libc_csu_init),
	              typeof(&__libc_csu_fini),
	              void*,void*);

	char** argv = (char**)alloca(sizeof(__procinfo.argp));
	memcpy(argv,__procinfo.argp,sizeof(__procinfo.argp));

	char* argbuf = (char*)alloca(sizeof(__procinfo.argbuf));
	memcpy(argbuf,__procinfo.argbuf,sizeof(__procinfo.argbuf));

	for(int i = 0; i < PROCINFO_MAX_ARGP; i++)
		if(argv[i])
			argv[i] += argbuf - __procinfo.argbuf;

	int argc = 0;
	while(argv[argc])
		argc++;

	extern char** _environ;
	_environ = argv+argc+1;

	__libc_start_main(&main,argc,argv,&__libc_csu_init,&__libc_csu_fini,0,0);

	failmsg("why did main() return?");

diediedie:
	abort();
	#ifdef ABORT_INSTRUCTION
	ABORT_INSTRUCTION;
	#endif
	while(1);
}