11dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* 21dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Copyright (C) 2008 The Android Open Source Project 31dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * All rights reserved. 41dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 51dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * Redistribution and use in source and binary forms, with or without 61dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * modification, are permitted provided that the following conditions 71dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * are met: 81dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions of source code must retain the above copyright 91dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer. 101dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * * Redistributions in binary form must reproduce the above copyright 111dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * notice, this list of conditions and the following disclaimer in 121dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * the documentation and/or other materials provided with the 131dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * distribution. 141dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * 151dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 161dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 171dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 181dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 191dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 201dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 211dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 221dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 231dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 241dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 251dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 261dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * SUCH DAMAGE. 271dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 281dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project#include <pthread.h> 291dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 301dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 311dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct user_desc { 321dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int entry_number; 331dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned long base_addr; 341dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int limit; 351dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int seg_32bit:1; 361dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int contents:2; 371dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int read_exec_only:1; 381dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int limit_in_pages:1; 391dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int seg_not_present:1; 401dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int useable:1; 411dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project unsigned int empty:25; 421dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 431dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 441dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectextern int __set_thread_area(struct user_desc *u_info); 451dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 461dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* the following can't be const, since the first call will 471dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * update the 'entry_number' field 481dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 491dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstatic struct user_desc _tls_desc = 501dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 511dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project -1, 521dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 531dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0x1000, 541dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1, 551dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 561dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 571dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1, 581dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0, 591dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1, 601dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 0 611dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 621dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 6331e72bc3289acdd85b0b745fbf64c5949ca33432Jack Renstatic pthread_mutex_t _tls_desc_lock = PTHREAD_MUTEX_INITIALIZER; 6431e72bc3289acdd85b0b745fbf64c5949ca33432Jack Ren 651dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectstruct _thread_area_head { 661dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project void *self; 671dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project}; 681dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 691dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project/* we implement thread local storage through the gs: segment descriptor 701dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project * we create a segment descriptor for the tls 711dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project */ 721dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Projectint __set_tls(void *ptr) 731dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project{ 741dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project int rc, segment; 751dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 7631e72bc3289acdd85b0b745fbf64c5949ca33432Jack Ren pthread_mutex_lock(&_tls_desc_lock); 771dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project _tls_desc.base_addr = (unsigned long)ptr; 781dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 791dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* We also need to write the location of the tls to ptr[0] */ 801dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ((struct _thread_area_head *)ptr)->self = ptr; 811dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 821dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project rc = __set_thread_area( &_tls_desc ); 831dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project if (rc != 0) 841dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project { 851dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* could not set thread local area */ 86c5393b23f6b7837d3b775e447573180fac4923fcJin Wei pthread_mutex_unlock(&_tls_desc_lock); 871dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return -1; 881dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project } 891dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 901dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project /* this weird computation comes from GLibc */ 911dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project segment = _tls_desc.entry_number*8 + 3; 921dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project asm __volatile__ ( 931dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project " movw %w0, %%gs" :: "q"(segment) 941dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project ); 9531e72bc3289acdd85b0b745fbf64c5949ca33432Jack Ren pthread_mutex_unlock(&_tls_desc_lock); 9631e72bc3289acdd85b0b745fbf64c5949ca33432Jack Ren 971dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project return 0; 981dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project} 991dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1001dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 1011dc9e472e19acfe6dc7f41e429236e7eef7ceda1The Android Open Source Project 102