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