11.10.3 Putting it all together

Given an application that has the following declarations:

   __thread int errno;
   __thread int active_thread = -1;

The language tool will allocate the two 'int' sized objects into separate data space and initialize them at startup to be 0 (errno) and -1 (active_thread).

At the main the TLS context will be initialized to access the two variables declared.

A new context may be created and intilialised using the following sequence:

void *create_thread_context(void) {
  void *tls_data;
  void *aligned_tls_data;
  int tls_size = _tls_size();
  int tls_alignment = _tls_align(void);

  // allocate some aligned data
  tls_data = malloc(tls_size + (tls_alignment-1));
  // align the result
  aligned_tls_data = (tls_data + (tls_alignment-1)) & (~(tls_alignment-1));

  // initialise the new tls space to the default initial values
  //   these will be the same as main()'s default values
  _init_tls(aligned_tls_data);
 
  // if you wish to 'free' the space later, record tls_data and free that
  // return the allocated space
  return aligned_tls_data;
}

Once the space has been allocated, it may be activated at any time. Likely this would be on a context switch of some sort. It may also be that the current TLS context would like to be preserved for later restoration.

  // __current_tcb is used by the language tool to access TLS data
   //   this may be recorded
   extern void * __current_tcb;

   void *caller_tls_context = __current_tcb;

   // record current active thread_id, if this is called from the main thread
   //   this value will come from the main TLS block
   int current_thread = ++active_thread;

   // create and and initialise a new context
   void *my_context = create_thread_context();
   if (my_context == NULL) abort();
   _set_tls(my_context);

   // set the active_thread id in the current TLS block; this will not update
   //   any other versions of the 'active_thread' TLS variable
   active_thread = current_thread;

   execute_thread(); 

   // restore context to the previous (possibly the main TLS thread)
   _set_tls(caller_tls_context);