1 // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*-
2 // vim: ts=8 sw=2 smarttab
4 * Ceph - scalable distributed file system
6 * Copyright (C) 2004-2011 New Dream Network
8 * This is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License version 2.1, as published by the Free Software
11 * Foundation. See file COPYING.
15 #include "include/compat.h"
16 #include "common/Thread.h"
17 #include "common/code_environment.h"
18 #include "common/debug.h"
19 #include "common/signal.h"
20 #include "common/io_priority.h"
26 static int _set_affinity(int id)
29 if (id >= 0 && id < CPU_SETSIZE) {
35 if (sched_setaffinity(0, sizeof(cpuset), &cpuset) < 0)
37 /* guaranteed to take effect immediately */
58 void *Thread::_entry_func(void *arg) {
59 void *r = ((Thread*)arg)->entry_wrapper();
63 void *Thread::entry_wrapper()
65 int p = ceph_gettid(); // may return -ENOSYS on other platforms
70 ioprio_priority >= 0) {
71 ceph_ioprio_set(IOPRIO_WHO_PROCESS,
73 IOPRIO_PRIO_VALUE(ioprio_class, ioprio_priority));
75 if (pid && cpuid >= 0)
78 ceph_pthread_setname(pthread_self(), thread_name);
82 const pthread_t &Thread::get_thread_id() const
87 bool Thread::is_started() const
89 return thread_id != 0;
92 bool Thread::am_self() const
94 return (pthread_self() == thread_id);
97 int Thread::kill(int signal)
100 return pthread_kill(thread_id, signal);
105 int Thread::try_create(size_t stacksize)
107 pthread_attr_t *thread_attr = NULL;
108 pthread_attr_t thread_attr_loc;
110 stacksize &= CEPH_PAGE_MASK; // must be multiple of page
112 thread_attr = &thread_attr_loc;
113 pthread_attr_init(thread_attr);
114 pthread_attr_setstacksize(thread_attr, stacksize);
119 // The child thread will inherit our signal mask. Set our signal mask to
120 // the set of signals we want to block. (It's ok to block signals more
121 // signals than usual for a little while-- they will just be delivered to
122 // another thread or delieverd to this thread later.)
124 if (g_code_env == CODE_ENVIRONMENT_LIBRARY) {
125 block_signals(NULL, &old_sigset);
128 int to_block[] = { SIGPIPE , 0 };
129 block_signals(to_block, &old_sigset);
131 r = pthread_create(&thread_id, thread_attr, _entry_func, (void*)this);
132 restore_sigset(&old_sigset);
135 pthread_attr_destroy(thread_attr);
141 void Thread::create(const char *name, size_t stacksize)
143 assert(strlen(name) < 16);
146 int ret = try_create(stacksize);
149 snprintf(buf, sizeof(buf), "Thread::try_create(): pthread_create "
150 "failed with error %d", ret);
156 int Thread::join(void **prval)
158 if (thread_id == 0) {
159 assert("join on thread that was never started" == 0);
163 int status = pthread_join(thread_id, prval);
166 snprintf(buf, sizeof(buf), "Thread::join(): pthread_join "
167 "failed with error %d\n", status);
178 return pthread_detach(thread_id);
181 int Thread::set_ioprio(int cls, int prio)
183 // fixme, maybe: this can race with create()
185 ioprio_priority = prio;
186 if (pid && cls >= 0 && prio >= 0)
187 return ceph_ioprio_set(IOPRIO_WHO_PROCESS,
189 IOPRIO_PRIO_VALUE(cls, prio));
193 int Thread::set_affinity(int id)
197 if (pid && ceph_gettid() == pid)
198 r = _set_affinity(id);