thread.c revision 118bdd58389c77dd69b37e377b4e98ea89d2b14e
1118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati/****************************************************************************** 2118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * 3118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * Copyright (C) 2014 Google, Inc. 4118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * 5118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * Licensed under the Apache License, Version 2.0 (the "License"); 6118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * you may not use this file except in compliance with the License. 7118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * You may obtain a copy of the License at: 8118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * 9118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * http://www.apache.org/licenses/LICENSE-2.0 10118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * 11118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * Unless required by applicable law or agreed to in writing, software 12118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * distributed under the License is distributed on an "AS IS" BASIS, 13118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * See the License for the specific language governing permissions and 15118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * limitations under the License. 16118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati * 17118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati ******************************************************************************/ 18118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 19118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#define LOG_TAG "osi_thread" 20118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 21118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <assert.h> 22118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <pthread.h> 23118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <string.h> 24118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <sys/prctl.h> 25118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <sys/types.h> 26118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include <utils/Log.h> 27118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 28118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include "semaphore.h" 29118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati#include "thread.h" 30118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 31118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatitypedef struct thread_t { 32118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati pthread_t pthread; 33118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati pid_t tid; 34118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati char name[THREAD_NAME_MAX+1]; 35118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} thread_t; 36118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 37118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatipid_t thread_id(const thread_t *thread) { 38118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(thread != NULL); 39118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return thread->tid; 40118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} 41118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 42118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavaticonst char *thread_name(const thread_t *thread) { 43118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(thread != NULL); 44118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return thread->name; 45118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} 46118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 47118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatistruct start_arg { 48118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_t *thread; 49118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati semaphore_t *start_sem; 50118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati int error; 51118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_start_cb start_routine; 52118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati void *arg; 53118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati}; 54118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 55118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatistatic void *run_thread(void *start_arg) { 56118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(start_arg != NULL); 57118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 58118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati struct start_arg *start = start_arg; 59118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_t *thread = start->thread; 60118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 61118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(thread != NULL); 62118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 63118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati if (prctl(PR_SET_NAME, (unsigned long)thread->name) == -1) { 64118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati ALOGE("%s unable to set thread name: %s", __func__, strerror(errno)); 65118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start->error = errno; 66118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati semaphore_post(start->start_sem); 67118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return NULL; 68118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati } 69118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread->tid = gettid(); 70118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 71118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati // Cache local values because we are about to let thread_create 72118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati // continue 73118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_start_cb start_routine = start->start_routine; 74118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati void *arg = start->arg; 75118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 76118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati semaphore_post(start->start_sem); 77118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return start_routine(arg); 78118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} 79118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 80118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatithread_t *thread_create(const char *name, 81118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_start_cb start_routine, void *arg) { 82118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(name != NULL); 83118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati assert(start_routine != NULL); 84118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 85118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati // Start is on the stack, but we use a semaphore, so it's safe 86118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati struct start_arg start; 87118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati thread_t *ret; 88118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati ret = calloc(1, sizeof(thread_t)); 89118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati if (!ret) 90118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati goto error; 91118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start.start_sem = semaphore_new(0); 92118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati if (!start.start_sem) 93118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati goto error; 94118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 95118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati strncpy(ret->name, name, THREAD_NAME_MAX); 96118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start.thread = ret; 97118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start.error = 0; 98118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start.start_routine = start_routine; 99118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati start.arg = arg; 100118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati pthread_create(&ret->pthread, NULL, run_thread, &start); 101118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati semaphore_wait(start.start_sem); 102118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati if (start.error) 103118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati goto error; 104118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return ret; 105118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 106118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatierror:; 107118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati semaphore_free(start.start_sem); 108118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati free(ret); 109118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return NULL; 110118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} 111118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati 112118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavatiint thread_join(thread_t *thread, void **retval) { 113118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati int ret = pthread_join(thread->pthread, retval); 114118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati if (!ret) 115118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati free(thread); 116118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati return ret; 117118bdd58389c77dd69b37e377b4e98ea89d2b14eSharvil Nanavati} 118