头文件位置:bionic/libc/include/
源码实现位置:bionic/libc/bionic/

https://blog.csdn.net/weixin_46935110/article/details/130792477

https://blog.csdn.net/Lid_23/article/details/132036106
https://blog.csdn.net/qq_34888036/article/details/133960234
https://blog.csdn.net/swartz_lubel/article/details/77150949

特性说明(****)

不论哪个线程调用了 pthread_key_create(),所创建的 key 都是所有线程可以访问的,但各个线程可以根据自己的需要往 key 中填入不同的值,相当于提供了一个同名而不同值的全局变量(这个全局变量相对于拥有这个变量的线程来说)。

具体类讲解

pthread_types.h

typedef int pthread_key_t;
typedef long pthread_t

pthread_key.cpp

  • pthread_key_create方法

    124 int pthread_key_create(pthread_key_t* key, void (*key_destructor)(void*)) {
    125   for (size_t i = 0; i < BIONIC_PTHREAD_KEY_COUNT; ++i) {
    126     uintptr_t seq = atomic_load_explicit(&key_map[i].seq, memory_order_relaxed);
    127     while (!SeqOfKeyInUse(seq)) {
    128       if (atomic_compare_exchange_weak(&key_map[i].seq, &seq, seq + SEQ_INCREMENT_STEP)) {
    129         atomic_store(&key_map[i].key_destructor, reinterpret_cast<uintptr_t>(key_destructor));
    130         *key = i | KEY_VALID_FLAG;
    131         return 0;
    132       }
    133     }
    134   }
    135   return EAGAIN;
    136 }
  • pthread_setspecific方法

178 int pthread_setspecific(pthread_key_t key, const void* ptr) {
//KeyInValidRange判断key值有没有超出范围
179   if (__predict_false(!KeyInValidRange(key))) {
180     return EINVAL;
181   }
182   key &= ~KEY_VALID_FLAG;
183   uintptr_t seq = atomic_load_explicit(&key_map[key].seq, memory_order_relaxed);
184   if (__predict_true(SeqOfKeyInUse(seq))) {
185     pthread_key_data_t* data = &get_thread_key_data()[key];
186     data->seq = seq;
187     data->data = const_cast<void*>(ptr);
188     return 0;
189   }
190   return EINVAL;
191 }

pthread_key_t 实际为int类型

→key_map数组

 50 struct pthread_key_internal_t {
 51   atomic_uintptr_t seq;
 52   atomic_uintptr_t key_destructor;
 53 };
 54 
 55 static pthread_key_internal_t key_map[BIONIC_PTHREAD_KEY_COUNT];

根据http://xinyiworld.top/wordpress_it/?p=14519可以知道atomic_uintptr_t为类型为unsigned long类型的原子变量

//todo

pthread_setname_np.cpp

  • pthread_setname_np(设置线程名称)
    83 int pthread_setname_np(pthread_t t, const char* thread_name) {
    84   ErrnoRestorer errno_restorer;
    85 
    86   size_t thread_name_len = strlen(thread_name);
    87   if (thread_name_len >= MAX_TASK_COMM_LEN) return ERANGE;
    88 
    89   // Setting our own name is an easy special case.
    90   if (t == pthread_self()) {
    91     return prctl(PR_SET_NAME, thread_name) ? errno : 0;
    92   }
    93 
    94   // We have to set another thread's name.
    95   int fd = __open_task_comm_fd(t, O_WRONLY, "pthread_setname_np");
    96   if (fd == -1) return errno;
    97 
    98   ssize_t n = TEMP_FAILURE_RETRY(write(fd, thread_name, thread_name_len));
    99   close(fd);
    100 
    101   if (n == -1) return errno;
    102   if (n != static_cast<ssize_t>(thread_name_len)) return EIO;
    103   return 0;
    104 }

    /proc/进程id/task/线程id/comm文件中写入线程名称

pthread_self.cpp

 29 #include "pthread_internal.h"
 30 
 31 pthread_t pthread_self() {
 32   return reinterpret_cast<pthread_t>(__get_thread());
 33 }

ndk_cruft.cpp

  • __get_thread
    366 // Various third-party apps contain a backport of our pthread_rwlock implementation that uses this.
    367 pthread_internal_t* __get_thread() {
    368   return __real_get_thread();
    369 }

    __real_get_thread实现位置 ?


0 条评论

发表回复

您的电子邮箱地址不会被公开。